C程序运行过程中堆栈结构分析-Linux 64位系统

  // 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+8>        movl   $0x1,-0x14(%rbp)    //第一个内部变量赋值
0x400599 <main+15>        movl   $0x2,-0x10(%rbp)    //第二个内部变量赋值
0x4005a0 <main+22>        movl   $0x3,-0xc(%rbp)    //第三个内部变量赋值
0x4005a7 <main+29>        movl   $0x4,-0x8(%rbp)    //第四个内部变量赋值
0x4005ae <main+36>        mov    -0x8(%rbp),%ecx    //为sum函数调用准备参数
0x4005b1 <main+39>        mov    -0xc(%rbp),%edx
0x4005b4 <main+42>        mov    -0x10(%rbp),%esi
0x4005b7 <main+45>        mov    -0x14(%rbp),%eax
0x4005ba <main+48>        mov    $0x6,%r9d
0x4005c0 <main+54>        mov    $0x5,%r8d
0x4005c6 <main+60>        mov    %eax,%edi
0x4005c8 <main+62>        callq  0x400501 <sum>
0x4005cd <main+67>        mov    %eax,-0x4(%rbp)
0x4005d0 <main+70>        mov    $0x0,%eax
0x4005d5 <main+75>        leaveq
0x4005d6 <main+76>        retq
0x4005d7                    nopw   0x0(%rax,%rax,1)
0x4005e0 <__libc_csu_init>    push   %r15
              
(gdb) b main
Breakpoint 1 at 0x400592: file test.c, line 21.
(gdb) display $rsp        //监测sp的值
(gdb) display $rbp        //监测bp的值
(gdb) display $rip        //监测ip的值
(gdb) layout asm        //显示汇编语句窗口
(gdb)r                     //运行程序
Starting program: /home/cmaxd/src/4-1/test
Breakpoint 1, main () at test.c:21
21        x1 = 1;

(gdb)si                    //指令级单步执行
3: $rip = (void (*)()) 0x400592 <main+8>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00:    0xf63d4e2e    0x00000000    0x0040030b    0x00000000
0x7fffffffdc10:    0xffffffff    0x00000000    0xffffdd78    0x00007fff
0x7fffffffdc20:    0xf7a211f8    0x00007fff    0xf7fe2000    0x00007fff
0x7fffffffdc30:    0xf7ffe1c8    0x00007fff    0x00000000    0x00000000
0x7fffffffdc40:    0x00000001    0x00000000    0x0040062d    0x00000000
0x7fffffffdc50:    0xffffdc80    0x00007fff    0x00000000    0x00000000
0x7fffffffdc60:    0x004005e0    0x00000000    0x00400400    0x00000000
0x7fffffffdc70:    0xffffdd60    0x00007fff    0x00000000    0x00000000
0x7fffffffdc80:    0x00000000    0x00000000    0xf7a32f45    0x00007fff

//以下完成main函数内部变量x1~x4的赋值,x1~x4的存储空间分配在栈中
(gdb) si
3: $rip = (void (*)()) 0x400599 <main+15>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
(gdb) si
3: $rip = (void (*)()) 0x4005a0 <main+22>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
(gdb) si
3: $rip = (void (*)()) 0x4005a7 <main+29>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
(gdb) si
3: $rip = (void (*)()) 0x4005ae <main+36>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60

(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00:    0xf63d4e2e    0x00000000    0x0040030b    0x00000000
0x7fffffffdc10:    0xffffffff    0x00000000    0xffffdd78    0x00007fff
0x7fffffffdc20:    0xf7a211f8    0x00007fff    0xf7fe2000    0x00007fff
0x7fffffffdc30:    0xf7ffe1c8    0x00007fff    0x00000000    0x00000000
0x7fffffffdc40:    0x00000001    0x00000000    0x0040062d    0x00000000
0x7fffffffdc50:    0xffffdc80    0x00007fff    0x00000000    0x00000000
0x7fffffffdc60:    0x004005e0    0x00000000    0x00400400    0x00000001
0x7fffffffdc70:    0x00000002    0x00000003    0x00000004    0x00000000
0x7fffffffdc80:    0x00000000    0x00000000    0xf7a32f45    0x00007fff
(gdb) si 7
3: $rip = (void (*)()) 0x4005c8 <main+62>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
//这段程序完成sum函数调用前的参数准备
//参数传递顺序为 第一个参数->edi, 第二个参数->esi,第三个参数->edx,第四个参数->ecx,第五个参数->r8,第六个参数->r9
(gdb) info reg
rax            0x1      1
rbx            0x0      0
rcx            0x4      4
rdx            0x3      3
rsi            0x2      2
rdi            0x1      1
rbp            0x7fffffffdc80   0x7fffffffdc80
rsp            0x7fffffffdc60   0x7fffffffdc60
r8             0x5      5
r9             0x6      6
r10            0x7fffffffdb10   140737488345872
r11            0x7ffff7a32e50   140737348054608
r12            0x400400 4195328
r13            0x7fffffffdd60   140737488346464
r14            0x0      0
r15            0x0      0
rip            0x4005c8 0x4005c8 <main+62>
eflags         0x206    [ PF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) si
sum (a=32767, b=-134340608, c=32767, d=-140373512, e=32767, f=-8840) at test.c:7
3: $rip = (void (*)()) 0x400501 <sum>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc58
//系统自动完成函数返回地址的压栈,为sum函数调用作准备
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0xf63d4e2e      0x00000000      0x0040030b      0x00000000
0x7fffffffdc10: 0xffffffff      0x00000000      0xffffdd78      0x00007fff
0x7fffffffdc20: 0xf7a211f8      0x00007fff      0xf7fe2000      0x00007fff
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x00000000      0x00000000
0x7fffffffdc40: 0x00000001      0x00000000      0x0040062d      0x00000000
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff

(gdb) si
3: $rip = (void (*)()) 0x400502 <sum+1>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc50
//bp入栈
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0xf63d4e2e      0x00000000      0x0040030b      0x00000000
0x7fffffffdc10: 0xffffffff      0x00000000      0xffffdd78      0x00007fff
0x7fffffffdc20: 0xf7a211f8      0x00007fff      0xf7fe2000      0x00007fff
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x00000000      0x00000000
0x7fffffffdc40: 0x00000001      0x00000000      0x0040062d      0x00000000
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff

(gdb) si
3: $rip = (void (*)()) 0x400505 <sum+4>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc50
// sp -> bp

(gdb) si
3: $rip = (void (*)()) 0x400509 <sum+8>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc18
//根据内部变量及函数参数调整栈顶指针

(gdb) si 16
3: $rip = (void (*)()) 0x400551 <sum+80>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc18
//存储实参值、内部变量赋值、为调用add函数进行参数传递准备

(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0xf63d4e2e      0x00000000      0x0040030b      0x00000000
0x7fffffffdc10: 0xffffffff      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff
(gdb)info reg
rax            0xa      10
rbx            0x0      0
rcx            0x4      4
rdx            0x14     20
rsi            0x14     20
rdi            0xa      10
rbp            0x7fffffffdc50   0x7fffffffdc50
rsp            0x7fffffffdc18   0x7fffffffdc18
r8             0x5      5
r9             0x6      6
r10            0x7fffffffdb10   140737488345872
r11            0x7ffff7a32e50   140737348054608
r12            0x400400 4195328
r13            0x7fffffffdd60   140737488346464
r14            0x0      0
r15            0x0      0
rip            0x400551 0x400551 <sum+80>
eflags         0x216    [ PF AF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

(gdb) si
add (m=0, n=-163754450) at test.c:3
3: $rip = (void (*)()) 0x4004ed <add>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc10
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0xf63d4e2e      0x00000000      0x0040030b      0x00000000
0x7fffffffdc10: 0x00400556      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff
//系统自动完成返回地址压栈,为add函数调用作准备
(gdb) si
3: $rip = (void (*)()) 0x4004ee <add+1>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc08
//bp压栈
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0xf63d4e2e      0x00000000      0xffffdc50      0x00007fff
0x7fffffffdc10: 0x00400556      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff

(gdb) si
3: $rip = (void (*)()) 0x4004f1 <add+4>
2: $rbp = (void *) 0x7fffffffdc08
1: $rsp = (void *) 0x7fffffffdc08
// sp->bp
3: $rip = (void (*)()) 0x4004fd <add+16>
2: $rbp = (void *) 0x7fffffffdc08
1: $rsp = (void *) 0x7fffffffdc08
//实参存储、参数到寄存器的转移
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0x00000014      0x0000000a      0xffffdc50      0x00007fff
0x7fffffffdc10: 0x00400556      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x00000000
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff

rax            0x14     20
rbx            0x0      0
rcx            0x4      4
rdx            0xa      10
rsi            0x14     20
rdi            0xa      10
(gdb) si
3: $rip = (void (*)()) 0x4004ff <add+18>
2: $rbp = (void *) 0x7fffffffdc08
1: $rsp = (void *) 0x7fffffffdc08
rax            0x1e     30
//完成加运算
(gdb) si   
3: $rip = (void (*)()) 0x400500 <add+19>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc10
//恢复 bp 准备函数返回
(gdb) si
0x0000000000400556 in sum (a=1, b=2, c=3, d=4, e=5, f=6) at test.c:15
3: $rip = (void (*)()) 0x400556 <sum+85>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc18
//add函数返回
(gdb) si 20
3: $rip = (void (*)()) 0x400588 <sum+135>
2: $rbp = (void *) 0x7fffffffdc50
1: $rsp = (void *) 0x7fffffffdc18
// 完成sum函数中的其他工作
(gdb) si
3: $rip = (void (*)()) 0x400589 <sum+136>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc58
// leaveq 指令完成堆栈指针调整
(gdb) si
0x00000000004005cd in main () at test.c:25
3: $rip = (void (*)()) 0x4005cd <main+67>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
//sum函数返回
(gdb) si
3: $rip = (void (*)()) 0x4005d0 <main+70>
2: $rbp = (void *) 0x7fffffffdc80
1: $rsp = (void *) 0x7fffffffdc60
//sum函数返回值通过eax寄存器传出并赋值给sum_of变量

(gdb) p &sum_of
$1 = (int *) 0x7fffffffdc7c
(gdb) p sum_of
$2 = 231
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0x00000014      0x0000000a      0xffffdc50      0x00007fff
0x7fffffffdc10: 0x00400556      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x000000e7
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff

(gdb) si
3: $rip = (void (*)()) 0x4005d6 <main+76>
2: $rbp = (void *) 0x0
1: $rsp = (void *) 0x7fffffffdc88
//leaveq 函数调整堆栈指针
(gdb) si
__libc_start_main (main=0x40058a <main>, argc=1, argv=0x7fffffffdd68, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
    stack_end=0x7fffffffdd58) at libc-start.c:321
3: $rip = (void (*)()) 0x7ffff7a32f45 <__libc_start_main+245>
2: $rbp = (void *) 0x0
1: $rsp = (void *) 0x7fffffffdc90
(gdb) x /40xw 0x7fffffffdc00
0x7fffffffdc00: 0x00000014      0x0000000a      0xffffdc50      0x00007fff
0x7fffffffdc10: 0x00400556      0x00000000      0x00000006      0x00000005
0x7fffffffdc20: 0x00000004      0x00000003      0x00000002      0x00000001
0x7fffffffdc30: 0xf7ffe1c8      0x00007fff      0x0000000a      0x00000014
0x7fffffffdc40: 0x0000001e      0x00000028      0x00000032      0x0000003c
0x7fffffffdc50: 0xffffdc80      0x00007fff      0x004005cd      0x00000000
0x7fffffffdc60: 0x004005e0      0x00000000      0x00400400      0x00000001
0x7fffffffdc70: 0x00000002      0x00000003      0x00000004      0x000000e7
0x7fffffffdc80: 0x00000000      0x00000000      0xf7a32f45      0x00007fff
0x7fffffffdc90: 0x00000000      0x00000000      0xffffdd68      0x00007fff

堆栈内容分析
地址    内容    注释
0x7…dc00    0x00000014          实参n
0x7…dc04    0x0000000a          实参m
0x7…dc08    0xffffdc50          add函数后bp的原值存储此,此后pb、sp<-0x7fffffffdc08
0x7…dc0c    0x00007fff    
0x7…dc10    0x00400556         add函数调用之后的sp 位置,内容为add函数的返回地址
0x7…dc14    0x00000000          
0x7…dc18    0x00000006          实参 f  add调用前的sp指针 <sum+4>
0x7…dc1c    0x00000005    实参 e
0x7…dc20    0x00000004          实参 d
0x7…dc24    0x00000003          实参 c
0x7…dc28    0x00000002          实参 b
0x7…dc2c    0x00000001    实参 a
0x7…dc30    0xf7ffe1c8          
0x7…dc34    0x00007fff          
0x7…dc38    0x0000000a          sum内部变量a1
0x7…dc3c    0x00000014    sum内部变量a2
0x7…dc40    0x0000001e          sum内部变量a3
0x7…dc44    0x00000028          sum内部变量a4
0x7…dc48    0x00000032          sum内部变量a5
0x7…dc4c    0x0000003c    sum内部变量a6
0x7…dc50    0xffffdc80          sum函数后bp的原值存储在此,
此后bp<-0x7fffffffdc50 sp<-0x7fffffffdc18
0x7…dc54    0x00007fff          
0x7…dc58    0x004005cd          sum函数调用之后的sp位置,内容为sum函数的返回地址,系统自动压栈
0x7…dc5c    0x00000000    
0x7…dc60    0x004005e0          sum函数调用之前的sp位置,内容为main函数的返回地址,由<main+4>调整
0x7…dc64    0x00000000          
0x7…dc68    0x00400400          
0x7…dc6c    0x00000001    main函数内部变量x1
0x7…dc70    0x00000002          main函数内部变量x2
0x7…dc74    0x00000003          main函数内部变量x3
0x7…dc78    0x00000004          main函数内部变量x4
0x7…dc7c    0x000000e7    main函数内部变量sum_of
0x7…dc80    0x00000000          进入main函数后bp的原值存储在此
此后bp<-0x7fffffffdc80 sp<-0x7fffffffdc60
0x7…dc84    0x00000000    



 
// 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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值