When you call a function in C, you need to ensure mainly 5 things:
________________ <---- Bottom of the stack (fixed) | | Higher memory address | | | | |________________|<---- Top of the stack (moving down) | Lower memory address | V Grows downwards in memory
Thus, **ESP alone represents the current status of the stack.
By convention, procedures will take their parameters from stack. If a procedure returns a value that will fit in a register, it will be returned in AL, AX, EAX, depending on its size. A procedure will in general have local variables on stack as well.
A standard method of accessing both local variables and parameters is to "mark" a place on the stack, and then address both parameters and local variables by their offsets from the "mark". This mark or reference point is called "FRAME POINTER" , because all the information that is pushed into the stack at the time of procedure call is called a frame for that procedure.
Frame Pointer (FP) for the running procedure is always stored in EBP.
[[ call func ]]
[[ pushl %ebp ]]
[[ movl %esp, %ebp ]]
[[ subl $4, %esp ]]
[[ movl %ebp, %esp]]
[[ popl %ebp ]]
[[ ret ]]
static int a = 8; /*Static Storage*/ extern c; static int func1 (int x) { int t = 8; /* Local Variable */ return (x+t); /* Return */ } int main() { int b = 0; b = func1(a); c = b; return(0); }
a: .long 8 &<-- Static variable a func1: pushl %ebp <-- Step 3, Push EBP movl %esp, %ebp <-- Step 4, Copy ESP -> EBP subl $4, %esp <-- Step 5, Create space on stack for t movl $8, -4(%ebp) <-- Initialize "t" to 8 movl -4(%ebp), %eax <-- Step 6, Copy "t" to EAX addl 8(%ebp), %eax <-- Step 6, Add "c" to EAX leave <-- Step 7 and 8: 7: Restore ESP (EBP -> ESP) 8: Restore EBP (Pop STACK -> EBP) ret <-- Step 9, (Pop STACK -> Program Counter) main: ......... pushl a <-- Step 1, push parameters call func1 <-- Step 2, call func1 addl $16, %esp movl %eax, -4(%ebp) movl -4(%ebp), %eax movl %eax, c .........
During execution of func1, STACK looks like:
_______________ <---- Bottom of the stack (fixed) | | | main | |_______________| func1 frame --> | a |<---- Parameters pushed starts here |_______________| | RET Addr |<---- Return address pushed by "call" |_______________| Frame Pointer-->| EBP |<---- FP for main pushed by func1 for func1 |_______________| Copy ESP to EBP | t |<---- Local variable "t" |_______________| | V
From the figure, you can make out that , to refer to parameters, we have to add 8 offset to EBP ie. 8(%ebp). And to refer to local variable, we'll say -4(%ebp).
**Remember, ESP points to the last item pushed, so 0(%ebp) will give us FP of main.
Copyright 2006-2022 Manu
Garg.