谈谈函数的调用过程,栈帧的创建和销毁。

标题 ##谈谈函数的调用过程,栈帧的创建和销毁。

以下面一段代码为例,说一说函数的调用过程,栈帧的创建与销毁。
我们来深入刨析一下函数的调用过程
以下这段代码要在VC6.0下调试,因为VC6.0对这部分的处理简单些,利于学习使用。

#include<stdio.h>
int add(int x,int y)
{
 int z = 0;
 z = x + y;
 return z;
}
int main()
{
  int a = 10;
  int b = 20;
  int ret = add(a,b);
  printf("ret=%d\n",ret);
  return 0;
}

我们知道每一次函数调用都是一个过程,这个过程我们通常称为:函数的调用过程。
这个过程要为函数开辟栈空间,用于本次函数的调用中存放临时变量和现场保护,这块栈空间称之为函数栈帧。

当我们调用一个函数时,每个函数都要开辟一个空间。而开辟的这个空间是在栈上开辟的并且是给函数开辟的,我们在用这块空间的时候要知道它的大小,用完要还回去。这时候就要用两个地址维护这个空间 ,一个是ebp里存的地址,另一个是esp里存的地址。只要知道了这两个地址就可以掌控这个空间。

而栈帧的维护,我们就必须了解以下几个寄存器:

ebp(基址寄存器)———指向当前的栈帧的底部(高地址)寄存器ebp称为“基址指针”,在未受改变之前始终指向栈底,用途是:在堆栈中寻址。
esp(栈顶寄存器)————指向当前的栈帧的顶部(低地址)寄存器esp称为“栈指针”,会随着数据的入栈出栈移动,也就是说始终指向栈 顶
eip(指令指针寄存器)——存储着cpu要读取指令的地址,没有它,cpu就无法执行
eax,ebx,ecx,edx(数据寄存器)————主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间
esi,edi(变址寄存器)———存放存储单元在段内的偏移量

在vc6.0中:在进入main函数在未执行main函数时,我们为mainCRTStartup开辟了一块空间.

当我们要详细研究函数调用过程,必须得对照的汇编代码。
从main函数的地方开始,要展开main函数的调用就得为main函数创建栈帧。
这里写图片描述
1.我们知道ebp和esp是用来维护函数的栈底指针和栈顶指针,push ebp,将__mainCRTStarup函数的ebp压栈,在它的栈顶开辟一块空间放入它的ebp;
2.将esp给ebp,此时ebp与esp同时指向刚刚开辟空间的顶端;(创建栈帧的过程)
3.esp减去0e4h大小的值,我们知道栈空间中元素存放顺序是由高地址到低地址,则该步骤在ebp的上面开辟了0e4h大小的内存空间;
4.ebx,esi,edi三块空间进行压栈,随着压栈的进行,esp指向edi的顶端;
这里写图片描述
6.将10赋给a,20赋给b。
7.b的值,将它mov给eax寄存器并且压栈;同理a的值,将它mov给ecx寄存器并且压栈。
8.接着调用call指令。注意,在调用call指令的时候,在ecx的上方又开辟了一块空间用于存放call指令下一条指令的地址(这个地址的作用是在call指令调用add函数结束的的时候jump指令能够找到call指令下一条指令的地址,从而回到main函数中)
9.由call指令进入add函数之后,第一步就是进行压栈,将main函数的ebp压栈保存在上面开辟的空间中。
创建z空间,放进去内容为0;
‘x’指向x=10的存储空间,将10放到寄存器eax中;同理“y”指向y=20的存储空间,将20add到eax中,此时eax中的内容为30;
将eax给“z”意思为将z的内容由零改为30;
将z的值放回到eax中,这一步骤代表着返回机制,z的值将来由寄存器eax带回到main函数中。
之后执行pop出栈操作,edi,esi,ebx三块空间出栈后,esp向下移动,这三块空间已经不属于add函数,但是依然存在。
将ebp给esp,此时esp回退到当前ebp的位置。
之后对下一块空间执行出栈操作, 由于保存的是main函数的ebp,栈底指针ebp得以回到main函数ebp的位置。
这里写图片描述
这里写图片描述
call指令的下一条指令就是“add esp,8”
movdword ptr [ret],eax
//将eax的值传给了ret
至此整个add函数的调用已经结束。再往下直到esp和ebp回到__mainCRTStarup函数相应的位置.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值