66 lines
1.8 KiB
ArmAsm
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
|