asmtutorials/x86_64/subroutines.s

66 lines
1.8 KiB
ArmAsm

;; Hello World Program #1
;; Compile with: nasm -f elf hello.s
;; Link with: ld -m elf_i386 -o hello hello.o
;; Run with: ./hello
;; sys/unistd_32.h
%define SYS_write 1
%define SYS_exit 60
;; unistd.h
%define STDOUT 1
section .data
msg db "Okay, so we're doing 64-bit subroutines now, huh?", 0Ah, 00h
section .text
global _start
_start:
mov rsi, msg ; Put the address of our message into rax.
call strlen ; call the function strlen. We're using RAX as our argument.
;; At this point, RDX is length and RSI still points to the source.
;; The differences here make me wonder if my understanding of the 32-bit
;; version are incorrect, since now the two fields that matter are
;; already populated.
;;
;; Note that this is non-standard. RAX is usually assumed to hold
;; the return value, but I'm cheating by knowing that printit
;; wants the result of strlen in RDX. Whether this is exploitable
;; in a compiler (you know, that whole "choosing registers"
;; question) is something to ponder.
call printit
call exit
strlen:
mov rdx, rsi
strlen_next:
cmp byte [rdx], 0
jz strlen_done
inc rdx
jmp strlen_next
strlen_done:
sub rdx, rsi
ret
;; Takes RDI as the address of the message and RDX as the length,
;; and prints them. Restores all used registers when finished.
printit:
push rdi
push rax
mov rdi, STDOUT ; using STDOUT (see definition above)
mov rax, SYS_write ; Using WRITE in 32-bit mode?
syscall
pop rax
pop rdi
;; Since this terminates the program, I'm not worried about
;; managing the stack correctly.
exit:
mov rdi, 0
mov rax, SYS_exit
syscall