函数栈帧的创建与销毁



写在前面

在我们前期的学习编程的过程中,我们会遇到许多诸如:“局部变量是如何创建的?”、“形参和实参有什么关系?”、“为什么局部变量是随机值?”、“函数调用时如何调用的?”等等的一些问题,今天我就来给你们讲解一下VS2013编译器下的函数栈帧的创建与销毁,当然不同的编译器底下的这个过程有略微的差异,大体上还是相同的。

函数栈帧的创建与销毁

了解两个寄存器ebp和esp

ebp和esp两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。每一次函数调用都要在栈区开辟一块空间,而这块空间就是由这两个寄存器来维护的,一个ebp(栈底指针)和一个esp(栈顶指针)。我们拿一串简单的代码来做演示

#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 c = 0;

	c = Add(a, b);
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

函数栈帧创建与销毁的具体过程

main函数的函数栈帧

开辟由于栈区是在高地址先开辟空间,后向低地址开辟空间,随着main函数中的函数创建,exp和ebp会向上移动,维护新创建的函数栈帧。
在这里插入图片描述
在这里插入图片描述
main函数在__mainCRTStartup内部被调用,__mainCRTStartup在mainCRTStartup函数内部被调用。main函数中返回值为0是返回给mainret这个变量。
我们来分析一下上面那串代码的函数栈帧的创建与销毁的过程:
在这里插入图片描述
先是push一下ebp,push是压栈的意思,也就是在函数栈顶压入ebp这个元素,
在这里插入图片描述
在这里插入图片描述

接下来就是mov ebp和esp,mov是把后一个值赋给前一个值的意思,
在这里插入图片描述
两个寄存器的内容相同,指针指向同一个地址。
在这里插入图片描述
接下来就是sub就是减去,esp指针内容地址都减去0E4h,esp指针就向上移动,两个指针共同来维护为main函数新开辟的函数栈帧。
在这里插入图片描述

在这里插入图片描述
压进去后,
在这里插入图片描述
在这里插入图片描述
接下来是lea,lea是加载的意思,把后面的值加载到edi中。
在这里插入图片描述
一个word是两个字节,dword是双字的意思,也就是4个字节,每次操控4个字节的内容,共39h次。将从edi地址开始向下到esp这些内容全部改成0xcccccccc。
在这里插入图片描述
在这里插入图片描述
这块内容就全部初始化为0xcccccccc的内容,所以这就是为什么局部变量未初始化是为随机值的原因。
以上的所有内容就是为main函数准备的栈帧。

变量的创建

在这里插入图片描述

接下来就是执行代码,在ebp-8的位置放入0Ah(10),ebp-14h的位置放入14h(20),ebp-20h的位置放入0。
在这里插入图片描述

Add函数栈帧的创建与销毁

以下就是传参的过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
call指令是调用函数且记住下一条指令的地址。先进入函数,方便之后出函数可以找到call的下一条指令。
在这里插入图片描述

现在进入了Add函数,你会发现,这里与main函数栈帧的准备过程有一些相似之处,其实遮羞就是Add函数栈帧的准备过程。接下来我们再来分析一下:
在这里插入图片描述
在这里插入图片描述
接下来又是创建临时变量的过程了。
在这里插入图片描述
在这里插入图片描述
接下来就是传参的过程了,找到之前压入的值,然后赋值给形参x和y。
在这里插入图片描述
其实在调用函数的时候,就已经通过压栈的形式 来进行传参,传参先行。这也证实了形参是实参的一份临时拷贝这句话。
最后就是返回z,把ebp-8的值赋给eax。eax是一个寄存器,函数销毁时,这个寄存器还是在的
在这里插入图片描述
接下来就是pop几次,弹出的意思,esp往下移动,这样Add函数就销毁了。
在这里插入图片描述

回到main函数

在这里插入图片描述

最后执行完call指令,通过之前压入的call的下一条指令的地址,回到原来的地方。这就是为啥当时保存call指令的下一条指令。出的去,也要回的来。
在这里插入图片描述

总结

这就是一个函数栈帧的创建与销毁的整个过程。相信大家所以疑惑也都解开了,当然这也只是简单的一些函数栈帧的创建与销毁。今天的讲解就到这结束了,欢迎点赞支持与指正~
在这里插入图片描述

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆兽学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值