函数调用及栈帧详解

我们在写c语言函数时,经常会使用F11调试跳转到函数内部,但是从内存的角度,函数调用实际上是一个怎样的过程呢?
关于栈帧,从逻辑上来说,可以想象成函数调用时的环境,需要考虑函数参数,函数的局部变量,函数执行完返回值等等。
下面详细解释一下函数调用的过程以及栈帧的概念。
首先在VC6.0下写一段简单的程序,

#include <stdio.h>
#include <windows.h>
int Myadd(int x,int y)
{
    int z=x+y;
    return z;
}
int main()
{
    int a=0xAAAAAAAA;
    int b=0XBBBBBBBB;
    int c=Myadd(a,b);
    printf("%d\n",c);
    system("pause");
    return 0;
}

将程序在调试状态转到反汇编可以查看到当前代码的汇编代码,通过汇编代码可以了解到函数的调用过程到底如何。
从程序的地址空间来看,临时变量的创建都在栈上(除static修饰除外)。所以以下全部用图来说明。
main函数的汇编代码:
这里写图片描述

对于汇编语言在此不做深究,了解一些基本的寄存器:esp栈顶寄存器,ebp栈底寄存器,eip(pc指针)保存当前正在执行指令的下一条指令的地址。我们取出中间重要的部分来解释。
这里写图片描述
第一句将ebp-4即就是a放入main函数的栈帧结构中,当main函数生成时,它的栈帧结构也由它自己被创建。
第二句指令将ebp-8即就是b放入main函数的栈帧结构中。
接下来,ebp-8即就是b放入寄存器eax中(eax通用寄存器),将eax压入栈中(push压栈指令),将ebp-4即就是a放入ecx中,再将ecx压入栈中。
这里写图片描述
可以查看esp的值就是我们的a和b。
这里写图片描述
接下来到了call命令:主要有两个功能1:将当前正在执行的命令的下一条指令的地址压入栈中。(00401093)2:跳转至指定函数。
这里写图片描述
此时将地址也压入栈中了,通过esp的值来观察到地址确实已经被压入栈中,由于是小端存储,所以地址从右向左依次递增。
这里写图片描述

接下来,F11进入函数内部:
这里写图片描述
第一条push指令将main函数的ebp压入栈中,第二条指令将ebp指向esp
这里写图片描述
第三条sub指令将esp移向下端(具体位置我们并不关心)
这里写图片描述
此时Myadd函数的栈帧已经形成。接下来分析:
这里写图片描述
接下来的指令将ebp+8即就是a放入eax中,再将ebp+0Ch即就是b与eax相加并放入eax中,此时eax中就是a+b的值即就是z,然后将eax放入Myadd函数的栈帧中。
这里写图片描述
继续分析此时函数已经完成他的任务,那么该如何返回呢?
这里写图片描述
第一条指令将ebp-4即就是z放入eax中
然后mov    esp,ebp这条指令,将ebp给esp,
这里写图片描述
此时:ebp与esp指向同一位置
这里写图片描述
接下来,pop      ebp将ebp此时的内容弹出(main-ebp)放入ebp中,并且ebp上移。
这里写图片描述
ret指令两个功能:1弹出栈顶,2将栈顶结构的返回值的地址写入eip。通过观察可以发现eip此时已被修改为之前call命令的下一跳命令的地址。(00401093
这里写图片描述
这里写图片描述
此时已经回到了main函数的栈帧。
这里写图片描述
第一条指令将esp加8,此时esp上移
这里写图片描述
最后一条指令将eax即就是z的值放入main函数的栈帧结构中,此时定义了一个新的变量叫c,c的值就是z。
这里写图片描述

至此,函数调用的过程就结束了,总结以下:
1形参实例化a,b在两个栈帧中间。
2形参实例化的顺序是从右向左
3函数中定义的变量是在自己的栈帧中,生命周期随着栈帧,因此具有临时性。
4函数自己形成自己的栈帧,并且由自己释放。
5常规情况下,函数返回值是以寄存器形式返回。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值