Contents |
%eipinstruction pointer%esptop of stack pointer%ebpbase pointer
How are functions called in C?
The callee function should have its own %ebp, thus, to
restore the state after the function call, the caller's %ebp must
be saved on the stack.
Caller:
call function - equivalent to:
pushl 2(%eip) # save return address (next instruction) jmp function
Callee:
%ebp containing the base pointer of the caller to the stack (pushl %ebp)
%ebp - now we can reference the parameters and return address relatively to %ebp
subl $8, %esp reserves space for 2 words)
%ebp) and local variables (negative offsets to %ebp)
%eax
leave) - equivalent to:
movl %ebp, %esp # copy base pointer to stack pointer again like before the call
# - this has the effect of de-allocating all local variables
popl %ebp # restore old base pointer from stack
ret) - equivalent to:
popl %eip
pushl $10 # push argument 1 to stack
pushl $20 # push argument 2 to stack
pushl 2(%eip) # save return address (next instruction)
jmp function
...
function:
pushl %ebp # save caller base pointer
movl %esp, %ebp # define callee base pointer
subl $4, %esp # allocate space for local variables
# (1 word, in this example)
...
movl %ebp, %esp # de-allocate local variables
popl %ebp # restore caller base pointer from stack
popl %eip # ret
Or the short version:
pushl $10 # push argument 1 to stack
pushl $20 # push argument 2 to stack
call function
function:
enter 4
...
leave
ret
A simple function call:
int addNumbers(int x, int y) {
int z = x+y;
return z;
}
int main(void) {
return addNumbers(30, 50);
}
Compiles to:
...
addNumbers:
pushl %ebp # save caller base pointer
movl %esp, %ebp # use current stack pointer as base pointer
# for addNumbers
subl $4, %esp # reserve one word for z
movl 12(%ebp), %eax # copy y to %eax (50)
addl 8(%ebp), %eax # add x to %eax (50+30=80)
movl %eax, -4(%ebp) # copy %eax to z
movl -4(%ebp), %eax # copy z to %eax (redundant, z didn't need to
# be introduced at all, but
# who cares :)
leave # restore caller stack frame
ret # return to caller
...
main:
...
subl $8, %esp # reserve space in stack for 2 arguments
movl $50, 4(%esp) # push 50 to one below top of stack (y)
movl $30, (%esp) # push 30 to top of stack (x)
call addNumbers # call function
...
addNumbers memory layout after subl $4, %esp
z %ebp - 4 = %esp old base pointer %ebp return address %ebp + 4 x %ebp + 8 y %ebp + 12