函数栈帧的创建与销毁(初级)

函数栈帧的创建与销毁(初级)

引言

如果你想知道:
1.局部变量是怎么创建的?
2.为什么是局部变量的值是随机值?
3.函数是怎么传参的?传参的顺序是怎样的?
4.形参和实参是什么关系?
5.函数调用是怎么做的?
6.函数调用结束怎么返回的?

我希望我写的东西对你有帮助。

在这里插入图片描述

进入正题

我是使用的环境是VS2013,不要使用太高级的编译器,越高级的编译器,越不容易学习和观察。同时在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现。

什么是函数栈帧:

栈帧又叫过程活动记录。C语言中,栈帧就是一个函数执行的环境。
函数的每次调用,都有它自己独立的栈帧。栈帧中维持着函数调用所需要的各种信息,包括函数的参数,局部变量,函数执行完成后下一步要执行的指令地址、寄存器信息等。

常见的寄存器:

eax、ebx、ecx、edx、esp、ebp
其中 esp、ebp这两个寄存器中存放的是地址,用来维护函数栈帧,每个函数调用都需要再栈区创建一个空间。

演示函数栈帧的创建与销毁

在这里插入图片描述
演示代码:

#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函数将会调用Add()函数,但main函数又是被谁调用的呢?
在这里插入图片描述

由图可知main函数是由 mainCRTSartup(),再由_tmainCRTStartup()调用。

开始表演

在这里插入图片描述
在这里插入图片描述
这两张分别是 main()函数,和Add()函数的反汇编。

1.main()函数栈帧的开辟:

在这里插入图片描述

在这里插入图片描述
解释:将ebp的值压入栈,同时esp移动一个单位(因为esp存放的地址,所以在32为平台下移动4个字节)

这里是将ebp的值放入栈区上,通常叫做压栈。栈区上数据通常从高地址—>低地址存放。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
解释:将esp的值赋给ebp

在这里插入图片描述

在这里插入图片描述
解释:将esp的值减去0E4h(16进制数,转为10进制就是228)。

在这里插入图片描述

这里是引用
解释:压入三个值:

在这里插入图片描述

这里是引用
解释:lea:load effective address(加载有效地址),就是将edi的值变为[ebp-0E4h]
将39h的值赋给ecx
将0CCCCCCCCh值赋给eax
dword是4个字节的意思,这条指令的意思是将从edi所指向空间向下,内存赋值0CCCCCCCCh,重复39h次,每次赋值4字节空间。

在这里插入图片描述

在这里插入图片描述
解释:以第一个为例,将0Ah(10)赋给地址为ebp-8的四字节空间。
在这里插入图片描述

2.调用Add()函数前准备:

这里是引用
解释:做传参准备。比如:将ebp-14h地址放的值(b:20)赋给eax,将eax的值压入栈。将ebp-8地址放的值(a:10)赋给ecx,并将ecx的值压入栈中。不要忘记push压栈时,esp所指向空间地址会减去一个单位(32字节下是4字节)而pop是出栈时,会加上一个单位。

在这里插入图片描述

在这里插入图片描述
将下一条指令IP00F51450压入栈中,并进入Add()函数。

在这里插入图片描述

在这里插入图片描述

3.Add()函数开辟栈帧

这里是引用

这里同上面为main()函数一样,都是为了开辟栈帧。

在这里插入图片描述

这里是引用
解释:将地址ebp-8空间的值赋为0.

在这里插入图片描述

这里是引用
解释:将ebp+8地址所指向空间的值赋给eax,再将eax的值加上ebp+0Ch所指向空间的值。最后将eax的值赋给ebp-8所指向空间。

在这里插入图片描述

这里是引用
解释:将ebp-8地址所指空间的值赋给30,也就是将返回值z交到一个寄存器手上,由它来返回。

4.Add()函数栈帧的销毁:

在这里插入图片描述
这是整个销毁的反汇编。

这里是引用
解释:将esp所指地址的值赋给edi,同时esp加上1个单位(4字节)。

在这里插入图片描述

edi就弹出去了。
同理,esi,ebx也会弹出去,也叫出栈。看下图
在这里插入图片描述

在这里插入图片描述
解释:将ebp的值赋给esp
将esp所指向空间的值交给ebp

在这里插入图片描述

这里是引用
解释:执行完这条命令,就会自动返回刚才call指令的下一行 00F51450。
在这里插入图片描述

点到为止,今天就说到这。
如果有什么不对的地方,还劳烦指教,谢谢大家。

在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值