GNU GASM (x86_32) Preserving register value across functions (jmp)

Viewed 36

This program is adding up numbers from 1 to n (10 in this case) in %ebx and moving them into %edi so the return value of the executed program can be called with echo $?

        .global _start

_start:
        movl $0, %ebx
        movl $1, %ecx

addNumbers:
        cmpl $10, %ecx # sum up until n 
        jg exitRoutine
        addl %ecx, %ebx
        incl %ecx
        jmp addNumbers

exitRoutine:
        movl $1, %eax
        movl %ebx, %edi
        int $0x80

For testing, if this file is called addUpTo10.s :

as -o addUpTo10.o addUpTo10.s && ld -o addUpTo10 addUpTo10.o && (./addUpTo10 ; echo $?)

I understand that this works because the value written into %ebx is preserved across function calls. If we were to switch out %ebx and %ecx registers the value returned will be $n+1$ since the value in %ebx will be preserved but not in ecx.

The confusing part to me is what happens in addNumbers label with %ecx where we have a jmp.

  1. Why is the value there not cleared when we call addNumbers recursively ?
  2. What action (jmp, switching labels) actually causes registers to clear out?
1 Answers

Your program doesn't call any functions, and doesn't make any syscalls that return, so saved registers are completely irrelevant. None of the registers in your program are ever "cleared out". The real reason for the difference is that unlike on amd64 Linux, the first parameter of a syscall on i386 Linux isn't edi but rather ebx. If you swap ebx and ecx, and then put the final result back in ebx instead of edi, then you'll get the right answer again.

Related