linux c 程序函数调用栈帧分析

唐建 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、本文目的

      将自己跟踪linux c程序函数调用栈帧的情况mark 一下,以便后续可以查阅。网友们发现有误的,请直接指正。同时此文为我向孟宁老师学习内核的课间作业

二、函数原型

      为了更加直观的描述栈帧,所以写了一个非常简单的函数调用例子,这样便于理解栈帧的情况。

三个函数连续调用,同时直接进行值传递和返回,并进行加法运算。

三、下面将函数汇编出来的汇编代码也贴出来以便。

 从上往下分别是main() 、f()、g()三个函数。

从上面的汇编代码我们可以简单总结一下:

1、函数开始都是进行本函数的栈准备。

     push %ebp——保存上一个函数的栈现场

     push %esp,%ebp——开启当前函数的栈

2、函数调用前,会先将参数入栈,然后调用call

3、函数调用 call 实际上相当于 push %eip 和 goto 。保存当前函数的执行点,跳转到被调函数。

4、函数结束,都是回复上一个函数的栈

     leave  =   mov %ebp,%esp   和 pop %ebp,这就是恢复上一个函数的栈

     ret = pop %eip ——恢复上一个函数的执行点,就是该执行哪条指令了。

四、下面我们看一下通过汇编调试得到的栈帧

1、调用

Call 函数时会将跳转的下一条指令压栈:

于是我们贴出来调用f函数时的栈帧

 

上述红圈,栈底是到栈顶分别是入参(11)、下一条指令(0x8048406=134513670)、

 f()调用g()函数一样,我们下面贴出g()函数被调用后整体的栈帧。

2、返回

ret指令就是讲下一条指令出栈给eip,下图贴出的是f函数ret 返回时的情况

Ret 完成后就回到了f函数的栈区了。同时大家可以下图看到,回到f函数后,会马上将之前的调用g函数的入栈的调用参数出栈——“add $0x4,%esp

Leave 相当于

mov ebp ,esp

pop ebp 

大家看下图,就是f函数返回时,栈帧的变换,栈变回了main函数的栈顶和栈底

函数的返回值是通过eax寄存器传递的

原文地址:https://www.cnblogs.com/tjyuanxi/p/8469913.html