FEAT Added subroutines to the list of skills taught in this tutorial.

This commit is contained in:
Elf M. Sternberg 2018-04-27 13:34:02 -07:00
parent 3b1f0e9a3d
commit 127e5c0b71
4 changed files with 142 additions and 0 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ hello32
hello64
counted-hello32
counted-hello64
subroutine-hello32
subroutine-hello64

View File

@ -23,5 +23,13 @@ counted-hello64: counted-hello64.s ## Build the 32 bit version of Project 3
nasm -f elf64 counted-hello64.s
ld -o counted-hello64 counted-hello64.o
subroutine-hello32: subroutine-hello32.s ## Build the 32 bit version of Project 3
nasm -f elf subroutine-hello32.s
ld -m elf_i386 -o subroutine-hello32 subroutine-hello32.o
subroutine-hello64: subroutine-hello64.s ## Build the 32 bit version of Project 3
nasm -f elf64 subroutine-hello64.s
ld -o subroutine-hello64 subroutine-hello64.o
clean: ## Delete all built and intermediate features
rm -f hello32 hello64 counted-hello32 counted-hello64 *.o

66
subroutine-hello32.s Normal file
View File

@ -0,0 +1,66 @@
;; 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 4
%define SYS_exit 1
;; unistd.h
%define STDOUT 1
section .data
msg db "Okay, so we're doing 32-bit subroutines now, huh?", 0Ah, 00h
section .text
global _start
_start:
mov eax, msg ; Put the address of our message into eax.
call strlen ; call the function strlen. We're using EAX as our argument.
mov edx, eax ; We know printit wants these two
mov eax, msg
call printit
call exit
strlen:
push ebx ; Push ebx onto the stack, since the calling scope
; will probably want its state restored correctly, right?
mov ebx, eax
strlen_next:
cmp byte [eax], 0
jz strlen_done
inc eax
jmp strlen_next
strlen_done:
sub eax, ebx ; Straight from the counted-hello file
pop ebx ; restore EBX for the calling scope, which is
; expecting its answer in eax
ret
;; Takes EAX as the address of the message and EDX as the
;; length, and prints them. Restores all used registers
;; when finished.
printit:
push eax
push ebx
push ecx
mov ecx, eax
mov ebx, STDOUT
mov eax, SYS_write
int 80h
pop ecx
pop ebx
pop eax
ret
;; Since this terminates the program, I'm not worried about
;; managing the stack correctly.
exit:
mov ebx, 0
mov eax, SYS_exit
int 80h

66
subroutine-hello64.s Normal file
View File

@ -0,0 +1,66 @@
;; 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 rdx
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