最近,读汇编与c的关系;读到将c源码反汇编时,有段代码不太了解----------------
此为c代码:
int bar(int c, int d) { int e = c + d; return e; } int foo(int a, int b) { return bar(a, b); } int main(void) { foo(2, 3); return 0; }反汇编:
int main:
foo(2, 3); 80483d5: c7 44 24 04 03 00 00 movl $0x3,0x4(%esp) 80483dc: 00 80483dd: c7 04 24 02 00 00 00 movl $0x2,(%esp) 80483e4: e8 c1 ff ff ff call 80483aa <foo> return 0; 80483e9: b8 00 00 00 00 mov $0x0,%eax
int foo(int a, int b) { 80483aa: 55 push %ebp
80483ab: 89 e5 mov %esp,%ebp
80483ad: 83 ec 08 sub $0x8,%esp
return bar(a, b); 80483b0: 8b 45 0c mov 0xc(%ebp),%eax 80483b3: 89 44 24 04 mov %eax,0x4(%esp) 80483b7: 8b 45 08 mov 0x8(%ebp),%eax 80483ba: 89 04 24 mov %eax,(%esp) 80483bd: e8 d2 ff ff ff call 8048394 <bar>
int bar(int c, int d) { 8048394: 55 push %ebp 8048395: 89 e5 mov %esp,%ebp 8048397: 83 ec 10 sub $0x10,%esp int e = c + d; 804839a: 8b 55 0c mov 0xc(%ebp),%edx 804839d: 8b 45 08 mov 0x8(%ebp),%eax 80483a0: 01 d0 add %edx,%eax 80483a2: 89 45 fc mov %eax,-0x4(%ebp)一直看不懂调用开头的
push %bep
mov %esp, %ebp
是什么意思。
经过在网上查阅资料,终于在csdn上找到了答案:
http://bbs.csdn.net/topics/300013871
下面是我自己的总结:
ebp是基址指针寄存器;
esp是堆栈指针寄存器;
c语言在进行编译时,会将各个函数的局部变量压入堆栈中;
+| (栈底方向,高位地址) |
| ....................|
| ....................|
| 参数3 |
| 参数2 |
| 参数1 |
| 返回地址 |
-| 上一层[EBP] |
| 局部变量1 |
| 局部变量2 |
|.....................|
栈一直随着函数调用的深入,一直想栈顶方向压下去。每次调用函数时候,先压函数参数(从右往左顺序压),
再压入函数调用下条指令的地址(由call完成)。
接着进入调用函数体中先执行PUSH EBP; MOV EBP ESP;(一般已经由编译器加入到函数头中了),
接着就是把函数体中的局部变量压入栈中。
再遇到函数的调用的嵌套则依此类推。
“PUSH EBP”“MOV EBP ESP”这两条指令实在大有深意:首先将EBP入栈,然后将栈顶指针ESP赋值给EBP。
“MOV EBP ESP”这条指令表面上看是用ESP把EBP原来的值覆盖了,
其实不然——因为给EBP赋值之前,原EBP值已被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
此时EBP寄存器就已处于一个很重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),
从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,
而该地址处又存储着上一层函数调用时的EBP值!
这两条指令合起来是把原来ebp
的值保存在栈上,
然后又给ebp
赋了新值。
在每个函数的栈帧中,ebp
指向栈底,而esp
指向栈顶,
在函数执行过程中esp
随着压栈和出栈操作随时变化,而ebp
是不动的,
函数的参数和局部变量都是通过ebp
的值加上一个偏移量来访问
1
2
3
4
|
int
main()
{
return
0;
}
|
1
2
3
4
|
反汇编生成的汇编代码:
2 00411370 55
push
ebp ;保存ebp指针
2 00411371 8bec
mov
ebp,esp ;将esp赋值给ebp,使ebp指向栈顶
2 00411373 81ecc0000000
sub
esp,0C0h ;在堆栈中留出0ch字节的空间给局部变量使用
|