函数调用过程分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1. 函数调用过程分析
1. 函数调用
我们用下面的代码来研究函数调用的过程。 例 19.1. 研究函数的调用过程
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; }
如果在编译时加上-g 选项(在第 10 章 gdb 讲过-g 选项),那么用 objdump 反汇编时可以把 C 代 码和汇编代码穿插起来显示,这样 C 代码和汇编代码的对应关系看得更清楚。反汇编的结果很长, 以下只列出我们关心的部分。
$ gcc main.c -g $ objdump -dS a.out ...

08048394 : int bar(int c, int d) { 8048394: 8048395: 8048397: 55 89 e5 83 ec 10 push mov sub %ebp %esp,%ebp $0x10,%esp
int e = c + d; 804839a: 804839d: 80483a0: 80483a2: 8b 55 0c 8b 45 08 01 d0 89 45 fc mov mov add mov 0xc(%ebp),%edx 0x8(%ebp),%eax %edx,%eax %eax,-0x4(%ebp)
return e; 80483a5: } 80483a8: 80483a9: c9 c3 leave ret 8b 45 fc mov -0x4(%ebp),%eax
080483aa :
int foo(int a, int b) { 80483aa: 80483ab: 80483ad: 55 89 e5 83 ec 08 push mov sub %ebp %esp,%ebp $0x8,%esp
return bar(a, b); 80483b0: 80483b3: 80483b7: 8b 45 0c 89 44 24 04 8b 45 08 mov mov mov 0xc(%ebp),%eax %eax,0x4(%esp) 0x8(%ebp),%eax

80483ba: 80483bd: } 80483c2: 80483c3:
89 04 24 e8 d2 ff ff ff
mov call
%eax,(%esp) 8048394
c9 c3
leave ret
080483c4

:
int main(void) { 80483c4: 80483c8: 80483cb: 80483ce: 80483cf: 80483d1: 80483d2: 8d 4c 24 04 83 e4 f0 ff 71 fc 55 89 e5 51 83 ec 08 lea and 0x4(%esp),%ecx $0xfffffff0,%esp
pushl -0x4(%ecx) push mov push sub %ebp %esp,%ebp %ecx $0x8,%esp
foo(2, 3); 80483d5: 80483dc: 80483dd: 80483e4: c7 44 24 04 03 00 00 00 c7 04 24 02 00 00 00 e8 c1 ff ff ff call movl $0x2,(%esp) movl $0x3,0x4(%esp)
80483aa
return 0; 80483e9: } 80483ee: 80483f1: 80483f2: 83 c4 08 59 5d add pop pop $0x8,%esp %ecx %ebp b8 00 00 00 00 mov $0x0,%eax

80483f3: 80483f6: ...
8d 61 fc c3
lea ret
-0x4(%ecx),%esp
要查看编译后的汇编代码,其实还有一种办法是 gcc -S main.c,这样只生成汇编代码 main.s,而不 生成二进制的目标文件。 整个程序的执行过程是 main 调用 foo,foo 调用 bar,我们用 gdb 跟踪程序的执行,直到 bar 函数中 的 int e = c + d;语句执行完毕准备返回时,这时在 gdb 中打印函数栈帧。
(gdb) start ... main () at main.c:14 14 (gdb) s foo (a=2, b=3) at main.c:9 9 (gdb) s bar (c=2, d=3) at main.c:3 3 int e = c + d; return bar(a, b); foo(2, 3);
(gdb) disassemble Dump of assembler code for function bar: 0x08048394 : 0x08048395 : 0x08048397 : 0x0804839a : 0x0804839d : push mov sub mov mov %ebp %esp,%ebp $0x10,%esp 0xc(%ebp),%edx 0x8(%ebp),%eax %edx,%eax %eax,-0x4(%ebp) -0x4(%ebp),%eax
0x080483a0 : add 0x080483a2 : mov 0x080483a5 : mov 0x080483a8 : leave

0x080483a9 : ret End of assembler dump. (gdb) si 0x0804839d (gdb) si 0x080483a0 (gdb) si 0x080483a2 (gdb) si 4 (gdb) si 5 } return e; 3 int e = c + d; 3 int e = c + d; 3 int e = c + d;
(gdb) bt #0 bar (c=2, d=3) at main.c:5 #1 0x080483c2 in foo (a=2, b=3) at main.c:9 #2 0x080483e9 in main () at main.c:14 (gdb) info registers eax ecx edx ebx esp 0x5 5 -1074674624
0xbff1c440 0x3 3
0xb7fe6ff4 0xbff1c3f4
-1208061964 0xbff1c3f4
ebp esi edi eip eflags
0xbff1c404 0x8048410 0x80482e0 0x80483a8 0x200206
0xbff1c404 134513680 134513376 0x80483a8 [ PF IF ID ]

相关文档
最新文档