Reputation: 2520
This is the program:
#include <stdio.h>
void test_function(int a, int b, int c, int d){
int flag;
flag = 31337;
}
int main(){
test_function(1,2,3,4);
}
From GDB:
Breakpoint 1, main () at stack_example.c:14
14 test_function(1,2,3,4);
(gdb) i r esp ebp eip
esp 0xffffcf88 0xffffcf88
ebp 0xffffcf98 0xffffcf98
eip 0x8048402 0x8048402 <main+6>
(gdb) cont
Continuing.
Breakpoint 2, test_function (a=1, b=2, c=3, d=4) at stack_example.c:8
8 flag = 31337;
(gdb) i r esp ebp eip
esp 0xffffcf70 0xffffcf70
ebp 0xffffcf80 0xffffcf80
eip 0x80483f3 0x80483f3 <test_function+6>
(gdb)
Dump of assembler code for function test_function:
0x080483ed <+0>: push ebp
x080483ee <+1>: mov ebp,esp
0x080483f0 <+3>: sub esp,0x10
=> 0x080483f3 <+6>: mov DWORD PTR [ebp-0x4],0x7a69
0x080483fa <+13>: leave
0x080483fb <+14>: ret
From GDB,
Why does EBP not have the same value as what ESP was in main()? Shouldn't mov ebp, esp
make EBP == 0xffffcf88
? I thought this sets EBP to what ESP is.
EDIT:
I think I may have answered my own question. Please correct me. ESP is moved when the return address and saved frame pointer are pushed onto the stack.
The ESP
value was 0xffffcf88
before the two values(both 4 bytes) were pushed onto the stack. Afterwards, it's value is 0xffffcf88 - 0x8
== 0xffffcf80
. This is what EBP's current value is. Then ESP -= 0x10.
How is the value of ESP modified? Is it something like mov ESP, ESP - 0x8
?
Upvotes: 2
Views: 730
Reputation: 9476
I hope I understand your question.
First, you are correct about new value of frame pointer. Here you need to know that "break test_function" actually stops gdb after the function prologue has been executed, so you are already past the point where ebp is explicitly stored to stack. See detailed explanation.
ESP is decreased by four for every push (or call). It's also decreased (some immediate value subtracted) by the amount of space required by the local variables, etc. Different "calling conventions" are being used on x86, so these details may vary a bit.
Some parts of this are also compiler specific. For example GCC by default keeps stack 4-word aligned on x86 (for one reason to keep SSE unit happy). See this SO thread.
BTW: frame pointer is actually redundant as long as compiler knows how to unwind stack from any point in function and it is typically omitted with optimized code.
Upvotes: 2