BUG Fix bug in 64-bit subroutine lesson. Streamline 32-bit subroutine lesson.

There was a bug in the 64-bit subroutine lesson that popped the stack
once too many times: there were two pushes but three pops.  That this
didn't generate a stack underflow condition confuses and worries me.
I would have expected a segfault when I decremented the stack counter
once too often.  This makes me wonder if I understand this program well
enough.

The effect on the registers was, fortunately, harmless as the next step
completely repurposed the registers to initialize the exit() routine.

Once I'd figured out how to use the RSI and RAX registers correctly, I
streamlined the 32-bit version so that the products of strlen(), the
start and length of the message, were already in the registers when I
issued my syscall to WRITE().  I'm sure this is, in some ways, *bad*
assembly, but I'm not (yet) an ASM stylist.
This commit is contained in:
Elf M. Sternberg 2018-04-27 16:44:37 -07:00
parent 127e5c0b71
commit 89b58186fb
2 changed files with 8 additions and 18 deletions

View File

@ -17,45 +17,36 @@ section .text
global _start global _start
_start: _start:
mov eax, msg ; Put the address of our message into eax. mov ecx, msg ; Put the address of our message into eax.
call strlen ; call the function strlen. We're using EAX as our argument. 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 printit
call exit call exit
strlen: strlen:
push ebx ; Push ebx onto the stack, since the calling scope
; will probably want its state restored correctly, right? ; will probably want its state restored correctly, right?
mov ebx, eax mov edx, ecx
strlen_next: strlen_next:
cmp byte [eax], 0 cmp byte [edx], 0
jz strlen_done jz strlen_done
inc eax inc edx
jmp strlen_next jmp strlen_next
strlen_done: strlen_done:
sub eax, ebx ; Straight from the counted-hello file sub edx, ecx ; Straight from the counted-hello file
pop ebx ; restore EBX for the calling scope, which is
; expecting its answer in eax
ret ret
;; Takes EAX as the address of the message and EDX as the ;; Takes EAX as the address of the message and EDX as the
;; length, and prints them. Restores all used registers ;; length, and prints them. Restores all used registers
;; when finished. ;; when finished. EDX contains the count.
printit: printit:
push eax
push ebx push ebx
push ecx push eax
mov ecx, eax
mov ebx, STDOUT mov ebx, STDOUT
mov eax, SYS_write mov eax, SYS_write
int 80h int 80h
pop ecx
pop ebx
pop eax pop eax
pop ebx
ret ret
;; Since this terminates the program, I'm not worried about ;; Since this terminates the program, I'm not worried about

View File

@ -55,7 +55,6 @@ printit:
mov rax, SYS_write ; Using WRITE in 32-bit mode? mov rax, SYS_write ; Using WRITE in 32-bit mode?
syscall syscall
pop rax pop rax
pop rdx
pop rdi pop rdi
;; Since this terminates the program, I'm not worried about ;; Since this terminates the program, I'm not worried about