NASM - The Netwide Assembler
NASM Forum => Example Code => Topic started by: TightCoderEx on May 08, 2012, 05:34:40 PM
-
Coincidentally, the two versions of this are exactly the same size in bytes
global _start
; =========================================================================================================
section .data
Prompt db 10, 'Hello Cruel World!', 10, 0
section .text
; =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-= =-=
; Dispaly applications signon message
_start: enter 24, 0 ; Create dummy frame
mov rsi, Prompt
call Console
.Exit: leave ; Kill dummy frame
xor rax, rax
mov rdi, rax ; Exit status NULL
mov al, SYS_EXIT
syscall
; =========================================================================================================
; Display ASCII string on console (monitor)
; ENTRY: RSI = Pointer to null terminated string to be displayed.
; LEAVE: RAX = Bytes displayed excluding null.
; All other registers preseved.
; FLAGS: ZR = 1 If nothing was displayed.
; 30H - 48 Bytes
; ---------------------------------------------------------------------------------------------------------
Console: push rdi
push rcx
push rdx
; First order of business is to search for end of string (NULL). Why? because we don't always
; know because there are times where strings are being built at runtime and this would have
; to be done anyway.
xor rcx, rcx
dec rcx ; Should be sufficiently large enough
mov al, 0 ; Byte we are search for
mov rdi, rsi
repnz scasb ; Find terminating character
neg rcx
dec rcx
dec rcx ; This is the actual length of string excluding null
; Setup registers for syscall
xor rax, rax
mov al, STDOUT ; I do this like this becuase it uses 5 bytes
mov rdi, rax ; versus mov RDI, STDOUT would take 11
mov al, SYS_WRITE
mov rdx, rcx ; Move count of bytes
syscall
pop rdx
pop rcx
pop rdi
or rax, rax
ret ; Return with string size in RAX and ZR=1 if string empty.
-
Essentially, this version is the same as the previous except a little extra functionality and being 8 bytes smaller. I'm beginning to utilize sign extension as much as possible this eliminating REX prefix.
SYS_WRITE equ 1
STDOUT equ 1
global Show
; ENTER: RSI = Pointer to string to be displayed
; LEAVE: RAX = Strings length including terminator
; = 1 Equivalent to NULL string
; RSI = Points to next avaliable string (assuming there is one)
section .text
Show push rdi
push rdx ; Preserve
push rcx
; Find EOS
or ecx, -1 ; Should be big enough
mov rdi, rsi ; RDI needs to be pointer
mov al, 0
repnz scasb ; Search for EOS
neg ecx
sub ecx, 2
push rdi ; We'll need this later
jz .ZeroStr
; Display string. ARG2 : Passed by caller
mov rdx, rcx ; ARG3 : character count
mov eax, STDOUT
mov rdi, rax ; ARG1 : file descriptor
syscall
; Setup registers for return to caller
.ZeroStr inc eax ; Bump over terminator
pop rsi ; Restore pointer to next position
pop rcx
pop rdx ; Retrieve
pop rdi
ret