美文网首页C语言深度总结
从gdb看函数的调用栈帧

从gdb看函数的调用栈帧

作者: bailongxian | 来源:发表于2018-06-14 19:58 被阅读10次

本文章所有的例子都是在x86-64运行,其他平台的可能细节上有细微的差别,但是原理基本的一致
在x86-64下 函数的栈桢大致如下图所示.


2.png

栈的扩展方向由高地址向低地址扩展,寄存器rbp指向函数的栈底,rsp指向函数的栈顶,所以在函数的栈桢中必有rbp>=rsp。在函数的栈桢中,rbp指向栈底,栈底的内容为父函数栈底的地址。

下面我们来看一个简单的例子。

  1 #include <stdio.h>
  2 
  3 int add(int n1, int n2)                                                                                                                                                                                                                  
  4 {
  5     int n = n1 + n2;
  6     return n;
  7 }
  8 
  9 int test()
 10 {
 11     int n1 = 100;
 12     int n2 = 200;
 13     return add(n1, n2);
 14 }
 15 
 16 int main()
 17 {
 18     printf("ret=%d\n", test());
 19     return 0;
 20 }

首先我们编译一下上面的文件,gcc -g main.c,然后用gdb运行生成的可执行文件。
分别在main函数和test函数打下断点。运行程序。


1.png

运行到main函数时,我们当前的寄存器的信息给打印出来,rbp和rsp的值分别是e490和e480。我们就行运行程序到test函数。我们打印出当前的寄存器信息。rbp和rsp的值分别是e470和e460。我们把e470地址的内容打印出来,在椭圆红框里,e470里面的内容为e490(即时父函数rbp的地址),我们再把rbp的上一个地址(rbp+8)的内容打印出来,为400573。 到这儿,我们用disassemble把main函数给反汇编出来,400573这个地址刚好就是main调用完test函数后,第一个要执行的地址。
在每个函数调用中,在开始函数调用时,有栈展开。

 pushl %ebp  # 保存原ebp值,设置当前函数的帧指针。  
 movl %esp,%ebp  
 subl $10,%esp  # 为局部变量c在栈内分配空间。

和栈回收

leave   # 恢复原ebp、esp值(即movl %ebp,%esp; popl %ebp;)。  
movl %ebp,%esp;  #回收栈顶,即把rsp指向rbp。
 popl %ebp;  #弹出父函数的rbp,并把rsp往上移动一个地址(这个地址存放子函数返回时的执行地址),(此时rsp在值和在未调用test之前的一致的)

这样,在一个函数调用结束时,父函数可以把rbp和rsp还原到未调用子函数之前时的内容,然后根据返回时执行的地址中的内容,然后继续往下运行。

上面已经讲完了在函数调用时,栈是如何展开和回收的,现在我们来将一下函数的参数是如何传递的。

相关文章

  • 从gdb看函数的调用栈帧

    本文章所有的例子都是在x86-64运行,其他平台的可能细节上有细微的差别,但是原理基本的一致在x86-64下 函...

  • 宏、普通函数、内联函数之间的区别

    普通函数 调用时向栈中push函数帧,调用结束后pop函数帧。编译器会在函数调用语句的前后,插入入栈和出栈的辅助代...

  • 5. linux下的栈帧分析

    @toc 1.linux下的栈帧分析2. 栈帧 1. 栈帧 每一次函数的调用,都会在调用栈上维护一个独立的栈帧(s...

  • 巧用函数栈实现栈的反转

    一、函数栈 函数的调用过程其实就是一个压栈的过程,在函数栈中,每个函数所占空间成为一个 栈帧。栈帧中保存着函数的形...

  • C 与汇编程序的约定调用

    1.说明 函数调用时通过栈帧来实现的,栈帧是指为一个单独的函数调用单独分配的那部分栈空间。当运行中的程序调用另一个...

  • Stack Queue

    在函数调用的过程中,操作系统使用函数调用栈来维护函数调用的状态。每个函数运行过程中有一段属于自己的栈帧结构,主要用...

  • 8086汇编三——AT&T栈帧-汇编C混编

    什么叫栈帧?就是函数的调用环境。bp和sp中间那一段就是函数调用环境。 在AT&T环境下栈帧是有点不一样的: 1、...

  • gdb函数调用栈简单分析

    最近在学gdb调试,感觉gdb调试还有好多可以深挖的内容,故函数的调用栈作为gdb分析的基础,不可不会,就参照网上...

  • 打印函数调用堆栈

    相关函数签名 backtrace():栈回溯,保存各个栈帧的地址。该函数用于获取当前线程的函数调用堆栈,获取的信息...

  • 2017-07-17

    在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回...

网友评论

    本文标题:从gdb看函数的调用栈帧

    本文链接:https://www.haomeiwen.com/subject/nrthmxtx.html