函数栈帧详解

Posted 针眼_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数栈帧详解相关的知识,希望对你有一定的参考价值。

本文从汇编角度观察函数栈帧发生调用中的变化
本文使用vs2013来讲述,并不建议使用vs2019等新版本,越新的版本函数栈帧相关越复杂

什么是函数栈帧

首先来了解一下:什么是函数栈帧?

栈帧是指为一个函数调用单独分配的那部分栈空间。 比如,当运行中的程序调用另一个函数时,就要进入一个新的栈帧,原来函数的栈帧称为调用者的帧,新的栈帧称为当前帧。 被调用的函数运行结束后当前帧全部收缩,回到调用者的帧。

函数栈帧

直接讲解函数栈帧未免纸上谈兵,所以这里引用下面这一块代码

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;
}

首先要先了解一个知识点 : 函数在内存中调用和运行,是由“esp”和“ebp”两个寄存器来维护的
这两个寄存器存放的是地址,分别是当前运行函数的边界的地址。

我们先来进入调试,一步一步的分析栈帧的创建以及维护。

进入main函数后,我们在“调试”中打开一个“调用堆栈”窗口。
之后我们多次F11来直接走完整个函数,之后我们发现调用堆栈中出现了两个函数

用一张图来解释

我们退出调试,重新在进入调试,按一下F11,
之后我们右击鼠标,来查看汇编指令

这都是啥啊,为什么在第一个语句之前还有这么多奇怪的指令
这些指令其实是用来为main函数开辟栈帧


F11继续调试

之后我们为了方便观看,右击空白处将"显示符号名"勾选去掉,之后得到的是这样

我们F10走过创建三个变量:a,b,c的语句,此时我们观看内存


之后就要进入我们的add函数了
大的药来了!!!



之后进入了add函数
首先仍然是给add函数创建栈帧

计算,然后返回

注意,如果这时候我们查看传入的形参a和b,也就是eax和ecx,你会发现这两个并不在add函数的栈帧中
大概是这样的

最后执行其他的语句

以上是关于函数栈帧详解的主要内容,如果未能解决你的问题,请参考以下文章

函数调用过程栈帧变化详解

函数栈帧详解

C语言深入逐汇编详解函数栈帧的创建和销毁过程

详解JavaScript调用栈尾递归和手动优化

栈帧详情转载

JVM:栈帧动态连接与方法调用详解