函数的调用过程之栈帧的创建与销毁

要想深度的理解函数,我们就得深入的研究一下函数的调用过程。这个过程要为函数开辟栈空间,用于本次函数的调用中临时变量的保存、现场保护,这块栈空间我们称之为函数栈帧。

首先,我们需要了解一下内存的划分:


其次我们需要了解一下栈(stack):

栈遵循的是”先进后出“或”后进先出“;

入栈:push

出栈:pop

下来就是CPU了,我们需要知道一些相关的寄存器:

通用寄存器:EAX、EBX、ECX、EDX

EIP(PC):程序计数器(当前正在执行指令的下一条指令的地址)

ESP:栈顶寄存器(存放栈顶指针)

EBP:栈底寄存器(存放栈底指针)


为了验证这个过程,我们在VC6.0环境下对一个程序进行研究,下面为源代码:

#include<stdio.h>

int add(int x, int y)
{
	int 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;
}

下面我们转到汇编来看,首先是main函数栈帧的创建


接下来我们再看add函数的调用,

这里就涉及到了汇编中call的使用,先来介绍一下call:

①保存当前指令的下一条指令的地址(将返回值地址保存到栈里,保存的目的是为了恢复);

②跳转至目标函数的入口地址处(修改EIP实现)(jmp);


执行call指令的时候按F11,就到了这里:


再按F11就进入add函数的执行代码处了:


剩下的就是函数返回部分了,

我们需要先了解汇编中的ret:

①将当前保存的函数返回值地址出栈;

②用弹出来的数据修改EIP;

此时EIP寄存器为:


返回到call的下一条指令地址处,


这里我们不对printf研究,整个函数的调用过程以及栈帧的创建与销毁就是这些了,

注:栈帧的销毁不是把全部数据清零,而是将这块区域失效,可覆盖。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值