36 c语言函数调用堆栈信息

前言

之前有一篇 java 的方法调用堆栈信息的分析 main方法的栈帧信息

这里 我们来看一下 c 语言的函数调用的堆栈信息, 相比于 java 的堆栈信息, 这里是要简单一些 

因为 堆栈信息的所有的东西都在对应的汇编中能够看到 

但是 java 的方法调用自己又封装了一层, 成本稍微高一些 

测试用例


    #include "stdio.h"

    int func_3(int arg3) {
        int locals_3 = 3;
        int locals_4 = 4;
        return locals_3 + locals_4 + arg3;
    }

    int func_2(int arg2) {
        int locals_2 = 2;
        return func_3(locals_2 + arg2);
    }

    int func_1(int arg1) {
        int locals_1 = 1;
        return func_2(locals_1 + arg1);
    }

    int main(int argc, char **argv) {

        int locals_0 = 10;
        int result = func_1(locals_0);

        printf(" func_1 arg0 : %d, result : %d \n", locals_0, result);

    }

堆栈信息

堆栈信息如下 

    (gdb) x /20gx 0x7fffffffe3d0
    0x7fffffffe3d0: 0x0000000000000000 0x0000000d00000000 // func_3_locals | arg3
    0x7fffffffe3e0: 0x0000000000000000 0x0000000400000003 // func_3_locals | local_3, locals_4
    0x7fffffffe3f0: 0x00007fffffffe418 0x000000000040056b // func_2's bp, func_2'sreturnAddress
    0x7fffffffe400: 0x0000000b00000000 0x0000000000000000 // func_2_locals | arg2
    0x7fffffffe410: 0x0000000200000000 0x00007fffffffe440 // func_2_locals, func_1's bp | locals_2
    0x7fffffffe420: 0x000000000040058e 0x0000000a00000000 // func_1's returnAddress, func_1_locals | arg1
    0x7fffffffe430: 0x0000000000000001 0x000000010040062d // func_1_locals | locals_1
    0x7fffffffe440: 0x00007fffffffe470 0x00000000004005b0 // main's bp, main'sReturnAddress
    0x7fffffffe450: 0x00007fffffffe558 0x0000000100400430 // main_locals | si, di
    0x7fffffffe460: 0x00007fffffffe550 0x000000000000000a // main_locals | locals_0
    0x7fffffffe470: 0x00000000004005e0 0x00007ffff7a2d840 // caller's bp, x
    0x7fffffffe480: 0x0000000000000000 0x00007fffffffe558

我们分别列一下 各个函数的内容, 可以对照上面的堆栈信息看一下 

这里只是举得一个简单点额例子, 如果参数过多, 会有一部分参数 也放置在 堆栈中

(gdb) disassemble main 
Dump of assembler code for function main:
   0x0000000000400590 <+0>:	push   %rbp
   0x0000000000400591 <+1>:	mov    %rsp,%rbp
   0x0000000000400594 <+4>:	sub    $0x20,%rsp
   0x0000000000400598 <+8>:	mov    %edi,-0x14(%rbp)
   0x000000000040059b <+11>:	mov    %rsi,-0x20(%rbp)
   0x000000000040059f <+15>:	movl   $0xa,-0x8(%rbp)
   0x00000000004005a6 <+22>:	mov    -0x8(%rbp),%eax
   0x00000000004005a9 <+25>:	mov    %eax,%edi
   0x00000000004005ab <+27>:	callq  0x40056d <func_1>
   0x00000000004005b0 <+32>:	mov    %eax,-0x4(%rbp)
   0x00000000004005b3 <+35>:	mov    -0x4(%rbp),%edx
   0x00000000004005b6 <+38>:	mov    -0x8(%rbp),%eax
   0x00000000004005b9 <+41>:	mov    %eax,%esi
   0x00000000004005bb <+43>:	mov    $0x400668,%edi
   0x00000000004005c0 <+48>:	mov    $0x0,%eax
   0x00000000004005c5 <+53>:	callq  0x400400 <printf@plt>
   0x00000000004005ca <+58>:	mov    $0x0,%eax
   0x00000000004005cf <+63>:	leaveq 
   0x00000000004005d0 <+64>:	retq   
End of assembler dump.
(gdb) disassemble func_1
Dump of assembler code for function func_1:
   0x000000000040056d <+0>:	push   %rbp
   0x000000000040056e <+1>:	mov    %rsp,%rbp
   0x0000000000400571 <+4>:	sub    $0x18,%rsp
   0x0000000000400575 <+8>:	mov    %edi,-0x14(%rbp)
   0x0000000000400578 <+11>:	movl   $0x1,-0x4(%rbp)
   0x000000000040057f <+18>:	mov    -0x4(%rbp),%edx
   0x0000000000400582 <+21>:	mov    -0x14(%rbp),%eax
   0x0000000000400585 <+24>:	add    %edx,%eax
   0x0000000000400587 <+26>:	mov    %eax,%edi
   0x0000000000400589 <+28>:	callq  0x40054a <func_2>
   0x000000000040058e <+33>:	leaveq 
   0x000000000040058f <+34>:	retq   
End of assembler dump.
(gdb) disassemble func_2
Dump of assembler code for function func_2:
   0x000000000040054a <+0>:	push   %rbp
   0x000000000040054b <+1>:	mov    %rsp,%rbp
   0x000000000040054e <+4>:	sub    $0x18,%rsp
   0x0000000000400552 <+8>:	mov    %edi,-0x14(%rbp)
   0x0000000000400555 <+11>:	movl   $0x2,-0x4(%rbp)
   0x000000000040055c <+18>:	mov    -0x4(%rbp),%edx
   0x000000000040055f <+21>:	mov    -0x14(%rbp),%eax
   0x0000000000400562 <+24>:	add    %edx,%eax
   0x0000000000400564 <+26>:	mov    %eax,%edi
   0x0000000000400566 <+28>:	callq  0x400526 <func_3>
   0x000000000040056b <+33>:	leaveq 
   0x000000000040056c <+34>:	retq   
End of assembler dump.
(gdb) disassemble func_3
Dump of assembler code for function func_3:
   0x0000000000400526 <+0>:	push   %rbp
   0x0000000000400527 <+1>:	mov    %rsp,%rbp
   0x000000000040052a <+4>:	mov    %edi,-0x14(%rbp)
   0x000000000040052d <+7>:	movl   $0x3,-0x8(%rbp)
   0x0000000000400534 <+14>:	movl   $0x4,-0x4(%rbp)
   0x000000000040053b <+21>:	mov    -0x8(%rbp),%edx
   0x000000000040053e <+24>:	mov    -0x4(%rbp),%eax
   0x0000000000400541 <+27>:	add    %eax,%edx
   0x0000000000400543 <+29>:	mov    -0x14(%rbp),%eax
=> 0x0000000000400546 <+32>:	add    %edx,%eax
   0x0000000000400548 <+34>:	pop    %rbp
   0x0000000000400549 <+35>:	retq   

完 

猜你喜欢

转载自blog.csdn.net/u011039332/article/details/128305693
36