// C函数调用堆栈结构分析例程
// 测试环境:平台ubuntu 14.04_3 64位 GCC Ubuntu 4.8.5-2
1 #include <stdio.h>
2 int add(int m, int n)
3 {
4 int x;
5 x = 100;
6 return x+m+n;
7 }
8 int sum(int a, int b, int c, int d, int e, int f)
9 {
10 int a1,a2,a3,a4,a5,a6;
11 a1 = 10;
12 a2 = 20;
13 a3 = 30;
14 a4 = 40;
15 a5 = 50;
16 a6 = 60;
17 return add(a1,a2)+a3+a4+a5+a6+a+b+c+d+e+f;
18 }
19
20 int main()
21 {
22 int x1,x2,x3,x4,sum_of;
23 x1 = 1;
24 x2 = 2;
25 x3 = 3;
26 x4 = 4;
27 sum_of = sum(x1,x2,x3,x4,5,6);
28 return 0;
29 }
//对应的汇编语言程序
0x4004ed <add> push %rbp // bp值压栈
0x4004ee <add+1> mov %rsp,%rbp //当前sp->bp
0x4004f1 <add+4> mov %edi,-0x4(%rbp) //第一实参存储紧邻栈顶
0x4004f4 <add+7> mov %esi,-0x8(%rbp) //第二实参存储
0x4004f7 <add+10> mov -0x8(%rbp),%eax //完成运算
0x4004fa <add+13> mov -0x4(%rbp),%edx
0x4004fd <add+16> add %edx,%eax
0x4004ff <add+18> pop %rbp //恢复bp
0x400500 <add+19> retq //函数返回 返回值通过eax
0x400501 <sum> push %rbp // bp值压栈
0x400502 <sum+1> mov %rsp,%rbp //当前sp->bp
0x400505 <sum+4> sub $0x38,%rsp //根据函数参数及内部变量数调整栈顶指针
0x400509 <sum+8> mov %edi,-0x24(%rbp) //第一实参存储紧邻内部变量
0x40050c <sum+11> mov %esi,-0x28(%rbp) //第二实参存储紧邻内部变量
0x40050f <sum+14> mov %edx,-0x2c(%rbp) //第三实参存储
0x400512 <sum+17> mov %ecx,-0x30(%rbp) //第四实参存储
0x400515 <sum+20> mov %r8d,-0x34(%rbp) //第五实参存储
0x400519 <sum+24> mov %r9d,-0x38(%rbp) //第六实参存储
0x40051d <sum+28> movl $0xa,-0x18(%rbp) //第一个内部变量赋值
0x400524 <sum+35> movl $0x14,-0x14(%rbp) //第二个内部变量赋值
0x40052b <sum+42> movl $0x1e,-0x10(%rbp) //第三个内部变量赋值
0x400532 <sum+49> movl $0x28,-0xc(%rbp) //第四个内部变量赋值
0x400539 <sum+56> movl $0x32,-0x8(%rbp) //第五个内部变量赋值
0x400540 <sum+63> movl $0x3c,-0x4(%rbp) //第六个内部变量赋值
0x400547 <sum+70> mov -0x14(%rbp),%edx //为add函数调用准备参数传递
0x40054a <sum+73> mov -0x18(%rbp),%eax //本编译器通过寄存器传参
0x40054d <sum+76> mov %edx,%esi
0x40054f <sum+78> mov %eax,%edi
0x400551 <sum+80> callq 0x4004ed <add>
0x400556 <sum+85> mov -0x10(%rbp),%edx
0x400559 <sum+88> add %eax,%edx //函数返回值有eax传递
0x40055b <sum+90> mov -0xc(%rbp),%eax
0x40055e <sum+93> add %eax,%edx
0x400560 <sum+95> mov -0x8(%rbp),%eax
0x400563 <sum+98> add %eax,%edx
0x400565 <sum+100> mov -0x4(%rbp),%eax
0x400568 <sum+103> add %eax,%edx
0x40056a <sum+105> mov -0x24(%rbp),%eax
0x40056d <sum+108> add %eax,%edx
0x40056f <sum+110> mov -0x28(%rbp),%eax
0x400572 <sum+113> add %eax,%edx
0x400574 <sum+115> mov -0x2c(%rbp),%eax
0x400577 <sum+118> add %eax,%edx
0x400579 <sum+120> mov -0x30(%rbp),%eax
0x40057c <sum+123> add %eax,%edx
0x40057e <sum+125> mov -0x34(%rbp),%eax
0x400581 <sum+128> add %eax,%edx
0x400583 <sum+130> mov -0x38(%rbp),%eax
0x400586 <sum+133> add %edx,%eax
0x400588 <sum+135> leaveq
0x400589 <sum+136> retq //函数返回
0x40058a <main> push %rbp // bp值压栈
0x40058b <main+1> mov %rsp,%rbp //当前sp->bp
0x40058e <main+4> sub $0x20,%rsp //根据函数参数及内部变量数调整栈顶指针
0x400592 <main
// 测试环境:平台ubuntu 14.04_3 64位 GCC Ubuntu 4.8.5-2
1 #include <stdio.h>
2 int add(int m, int n)
3 {
4 int x;
5 x = 100;
6 return x+m+n;
7 }
8 int sum(int a, int b, int c, int d, int e, int f)
9 {
10 int a1,a2,a3,a4,a5,a6;
11 a1 = 10;
12 a2 = 20;
13 a3 = 30;
14 a4 = 40;
15 a5 = 50;
16 a6 = 60;
17 return add(a1,a2)+a3+a4+a5+a6+a+b+c+d+e+f;
18 }
19
20 int main()
21 {
22 int x1,x2,x3,x4,sum_of;
23 x1 = 1;
24 x2 = 2;
25 x3 = 3;
26 x4 = 4;
27 sum_of = sum(x1,x2,x3,x4,5,6);
28 return 0;
29 }
//对应的汇编语言程序
0x4004ed <add> push %rbp // bp值压栈
0x4004ee <add+1> mov %rsp,%rbp //当前sp->bp
0x4004f1 <add+4> mov %edi,-0x4(%rbp) //第一实参存储紧邻栈顶
0x4004f4 <add+7> mov %esi,-0x8(%rbp) //第二实参存储
0x4004f7 <add+10> mov -0x8(%rbp),%eax //完成运算
0x4004fa <add+13> mov -0x4(%rbp),%edx
0x4004fd <add+16> add %edx,%eax
0x4004ff <add+18> pop %rbp //恢复bp
0x400500 <add+19> retq //函数返回 返回值通过eax
0x400501 <sum> push %rbp // bp值压栈
0x400502 <sum+1> mov %rsp,%rbp //当前sp->bp
0x400505 <sum+4> sub $0x38,%rsp //根据函数参数及内部变量数调整栈顶指针
0x400509 <sum+8> mov %edi,-0x24(%rbp) //第一实参存储紧邻内部变量
0x40050c <sum+11> mov %esi,-0x28(%rbp) //第二实参存储紧邻内部变量
0x40050f <sum+14> mov %edx,-0x2c(%rbp) //第三实参存储
0x400512 <sum+17> mov %ecx,-0x30(%rbp) //第四实参存储
0x400515 <sum+20> mov %r8d,-0x34(%rbp) //第五实参存储
0x400519 <sum+24> mov %r9d,-0x38(%rbp) //第六实参存储
0x40051d <sum+28> movl $0xa,-0x18(%rbp) //第一个内部变量赋值
0x400524 <sum+35> movl $0x14,-0x14(%rbp) //第二个内部变量赋值
0x40052b <sum+42> movl $0x1e,-0x10(%rbp) //第三个内部变量赋值
0x400532 <sum+49> movl $0x28,-0xc(%rbp) //第四个内部变量赋值
0x400539 <sum+56> movl $0x32,-0x8(%rbp) //第五个内部变量赋值
0x400540 <sum+63> movl $0x3c,-0x4(%rbp) //第六个内部变量赋值
0x400547 <sum+70> mov -0x14(%rbp),%edx //为add函数调用准备参数传递
0x40054a <sum+73> mov -0x18(%rbp),%eax //本编译器通过寄存器传参
0x40054d <sum+76> mov %edx,%esi
0x40054f <sum+78> mov %eax,%edi
0x400551 <sum+80> callq 0x4004ed <add>
0x400556 <sum+85> mov -0x10(%rbp),%edx
0x400559 <sum+88> add %eax,%edx //函数返回值有eax传递
0x40055b <sum+90> mov -0xc(%rbp),%eax
0x40055e <sum+93> add %eax,%edx
0x400560 <sum+95> mov -0x8(%rbp),%eax
0x400563 <sum+98> add %eax,%edx
0x400565 <sum+100> mov -0x4(%rbp),%eax
0x400568 <sum+103> add %eax,%edx
0x40056a <sum+105> mov -0x24(%rbp),%eax
0x40056d <sum+108> add %eax,%edx
0x40056f <sum+110> mov -0x28(%rbp),%eax
0x400572 <sum+113> add %eax,%edx
0x400574 <sum+115> mov -0x2c(%rbp),%eax
0x400577 <sum+118> add %eax,%edx
0x400579 <sum+120> mov -0x30(%rbp),%eax
0x40057c <sum+123> add %eax,%edx
0x40057e <sum+125> mov -0x34(%rbp),%eax
0x400581 <sum+128> add %eax,%edx
0x400583 <sum+130> mov -0x38(%rbp),%eax
0x400586 <sum+133> add %edx,%eax
0x400588 <sum+135> leaveq
0x400589 <sum+136> retq //函数返回
0x40058a <main> push %rbp // bp值压栈
0x40058b <main+1> mov %rsp,%rbp //当前sp->bp
0x40058e <main+4> sub $0x20,%rsp //根据函数参数及内部变量数调整栈顶指针
0x400592 <main