从汇编视角看函数调用
2017-08-03 18:49
337 查看
C语言函数如下
让我们从汇编的角度跟踪函数的执行,main对应的汇编函数如下:
刚刚进入main函数,而且已经建立调用stack时,对应的寄存器状态为:
(gdb) info registers rbp rsp
rbp 0x7fffffffdc80 0x7fffffffdc80
rsp 0x7fffffffdc80 0x7fffffffdc80
执行三条指令(si 3),进入foo函数之后,汇编指令如下:
此时的函数堆栈如下:此时,尚未切换栈基地址,但是栈顶地址已经发生变化(因为call将main中的返回地址入栈)
(gdb) info registers rbp rsp
rbp 0x7fffffffdc80 0x7fffffffdc80
rsp 0x7fffffffdc78 0x7fffffffdc78
接下来两句,建立新函数的堆栈;50e~515是取得函数实参的过程,这三句汇编等价于push edi, push esi. 指令执行到0518行,寄存器的状态
(gdb) info registers rbp rsp
rbp 0x7fffffffdc70 0x7fffffffdc70
rsp 0x7fffffffdc68 0x7fffffffdc68
输入命令si 9, 进入到新的函数调用栈。
此时的堆栈状态是:
(gdb) info registers rbp rsp
rbp 0x7fffffffdc70 0x7fffffffdc70
rsp 0x7fffffffdc60 0x7fffffffdc60
此时f0~f1仍然是建立新的函数调用stack。注意,接下来的几句,并没有进行函数stack的扩展,因为没有更深的函数调用。(另外,和对fun函数的调用不同,这里多了508对应的pop操作, 实际上,在fun函数中,是leave操作,这个操作等价于mov esp,ebp; pop ebp. 这里为什么没有将ebp的值传递给esp呢?因为ebp和esp是相同的)
Enter的作用相当==push ebp和mov ebp,esp
这后面两句大家很熟悉吧?函数开始一般都是这两句
Leave的作用相当==mov esp,ebp和pop ebp
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, 5); return 0; }
让我们从汇编的角度跟踪函数的执行,main对应的汇编函数如下:
Dump of assembler code for function main: 12 { 0x0000000000400529 <+0>: 55 push %rbp 0x000000000040052a <+1>: 48 89 e5 mov %rsp,%rbp 13 foo(2, 5); => 0x000000000040052d <+4>: be 05 00 00 00 mov $0x5,%esi 0x0000000000400532 <+9>: bf 02 00 00 00 mov $0x2,%edi 0x0000000000400537 <+14>: e8 ce ff ff ff callq 0x40050a <foo> 14 return 0; 0x000000000040053c <+19>: b8 00 00 00 00 mov $0x0,%eax 15 } 0x0000000000400541 <+24>: 5d pop %rbp 0x0000000000400542 <+25>: c3 retq End of assembler dump.
刚刚进入main函数,而且已经建立调用stack时,对应的寄存器状态为:
(gdb) info registers rbp rsp
rbp 0x7fffffffdc80 0x7fffffffdc80
rsp 0x7fffffffdc80 0x7fffffffdc80
执行三条指令(si 3),进入foo函数之后,汇编指令如下:
Dump of assembler code for function foo: 8 { => 0x000000000040050a <+0>: 55 push %rbp 0x000000000040050b <+1>: 48 89 e5 mov %rsp,%rbp 0x000000000040050e <+4>: 48 83 ec 08 sub $0x8,%rsp 0x0000000000400512 <+8>: 89 7d fc mov %edi,-0x4(%rbp) 0x0000000000400515 <+11>: 89 75 f8 mov %esi,-0x8(%rbp) 9 return bar(a, b); 0x0000000000400518 <+14>: 8b 55 f8 mov -0x8(%rbp),%edx 0x000000000040051b <+17>: 8b 45 fc mov -0x4(%rbp),%eax 0x000000000040051e <+20>: 89 d6 mov %edx,%esi 0x0000000000400520 <+22>: 89 c7 mov %eax,%edi 0x0000000000400522 <+24>: e8 c9 ff ff ff callq 0x4004f0 <bar> 10 } 0x0000000000400527 <+29>: c9 leaveq 0x0000000000400528 <+30>: c3 retq End of assembler dump.
此时的函数堆栈如下:此时,尚未切换栈基地址,但是栈顶地址已经发生变化(因为call将main中的返回地址入栈)
(gdb) info registers rbp rsp
rbp 0x7fffffffdc80 0x7fffffffdc80
rsp 0x7fffffffdc78 0x7fffffffdc78
接下来两句,建立新函数的堆栈;50e~515是取得函数实参的过程,这三句汇编等价于push edi, push esi. 指令执行到0518行,寄存器的状态
(gdb) info registers rbp rsp
rbp 0x7fffffffdc70 0x7fffffffdc70
rsp 0x7fffffffdc68 0x7fffffffdc68
输入命令si 9, 进入到新的函数调用栈。
(gdb) disassemble /rm Dump of assembler code for function bar: 3 { => 0x00000000004004f0 <+0>: 55 push %rbp 0x00000000004004f1 <+1>: 48 89 e5 mov %rsp,%rbp 0x00000000004004f4 <+4>: 89 7d ec mov %edi,-0x14(%rbp) 0x00000000004004f7 <+7>: 89 75 e8 mov %esi,-0x18(%rbp) 4 int e = c + d; 0x00000000004004fa <+10>: 8b 45 e8 mov -0x18(%rbp),%eax 0x00000000004004fd <+13>: 8b 55 ec mov -0x14(%rbp),%edx 0x0000000000400500 <+16>: 01 d0 add %edx,%eax 0x0000000000400502 <+18>: 89 45 fc mov %eax,-0x4(%rbp) 5 return e; 0x0000000000400505 <+21>: 8b 45 fc mov -0x4(%rbp),%eax 6 } 0x0000000000400508 <+24>: 5d pop %rbp 0x0000000000400509 <+25>: c3 retq End of assembler dump.
此时的堆栈状态是:
(gdb) info registers rbp rsp
rbp 0x7fffffffdc70 0x7fffffffdc70
rsp 0x7fffffffdc60 0x7fffffffdc60
此时f0~f1仍然是建立新的函数调用stack。注意,接下来的几句,并没有进行函数stack的扩展,因为没有更深的函数调用。(另外,和对fun函数的调用不同,这里多了508对应的pop操作, 实际上,在fun函数中,是leave操作,这个操作等价于mov esp,ebp; pop ebp. 这里为什么没有将ebp的值传递给esp呢?因为ebp和esp是相同的)
Enter的作用相当==push ebp和mov ebp,esp
这后面两句大家很熟悉吧?函数开始一般都是这两句
Leave的作用相当==mov esp,ebp和pop ebp
相关文章推荐
- 函数调用-汇编分析
- 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)
- 透过汇编另眼看世界之多继承下的虚函数函数调用(二)
- 为何汇编里调用C函数需要堆栈,而汇编语言的函数的调用却不需要堆栈
- C++中的虚函数调用原理的反汇编实例分析(1)
- INTEL汇编的函数调用过程
- c++下类成员函数的调用发生了啥(从汇编看)
- 一个很简单的例子,从汇编层次理解函数调用
- arm汇编如何调用函数,如何写延迟函数
- 汇编——函数调用汇编原理
- C/C++中调用直接用汇编写的函数
- 反汇编 函数的调用和实现_笔记
- 虚函数调用过程(用汇编和几个例子解释)
- linuxC一站式编程的函数调用的过程汇编理解
- Linux汇编---函数调用过程
- 函数调用堆栈的汇编解析
- C 汇编代码 函数调用指令和栈平衡
- 汇编中的函数调用与寄存器
- 为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈
- C++中的虚函数调用原理的反汇编实例分析(2)