FEAT Added subroutines to the list of skills taught in this tutorial.
This commit is contained in:
		
							parent
							
								
									3b1f0e9a3d
								
							
						
					
					
						commit
						127e5c0b71
					
				|  | @ -6,3 +6,5 @@ hello32 | |||
| hello64 | ||||
| counted-hello32 | ||||
| counted-hello64 | ||||
| subroutine-hello32 | ||||
| subroutine-hello64 | ||||
|  |  | |||
							
								
								
									
										8
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										8
									
								
								Makefile
								
								
								
								
							|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -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 | ||||
		Loading…
	
		Reference in New Issue