【C语言】-函数栈帧的创建和销毁(详细版)

目录

一、需要的知识储备(准备工作)

1、常用寄存器类型

2、部分汇编指令的认识

3、栈的存储方式以及main函数的栈帧

1>、栈的存储方式

2>、main()函数的栈帧

二、函数栈帧的创建和销毁

1、关于main()函数的操作

1>、为main()函数开辟栈帧

 2>、在main()函数中创建变量

2、关于Add()函数操作

 1>、调用Add()时的准备 

2>、给Add()函数开辟栈帧

3>、在Add()函数中创建变量并计算

4>、Add()栈帧的销毁

3、返回main()函数


一、需要的知识储备(准备工作)

1、常用寄存器类型

<1>、  sp/esp/rsp       栈顶指针

<2>、  bp/ebp/rbp      栈底指针   

           这两个指针的作用是维护栈帧的范围

<3>、 eax  累加寄存器

<4>、 ebx  基地址寄存器,在内存寻地址时存放基地址

<5>、 ecx  计数寄存器

<6>、 edx  多功能寄存器,总是被用来存放整数除法产生的余数

2、部分汇编指令的认识

<1>、push指令:称为压栈,从栈顶增加一个元素。具体操作为:它首先减少esp的值,即esp向上移动,再将操作数复制到esp所指向的地址,在32位计算机下,esp每次减少4个字节

<2>、mov指令:用于将一个数据从源地址传送到目标地址,原操作地址的内容不变

          注解:此处即为esp的值给ebp,就是ebp移动到esp的位置

<3>、pop 指令:称为出栈,和压栈相对应的从栈顶删除一个元素,同时esp++

<4>、call  指令:将该指令的下一条指令的地址压入栈中,并跳转(jump)到子函数中

<5>、sub 指令:减操作指令,从寄存器减去数值,然后将结果保存到寄存器中

 

<6>、add 指令:加操作指令,从寄存器加上数值,然后将结果保存到寄存器中

<7>、lea  指令:为“load effective address”的缩写,可以将地址赋给目标寄存器

<8>、rep   指令:重复指令

         注解:即从edi开始39h(十六进制)个空间全部令为eax的内容,即0cccccccch,(相当                      于初始化)每次操作四个字节(每个word是两个字节,dword为四个字节)

3、栈的存储方式以及main函数的栈帧

1>、栈的存储方式

在栈中,上位是低地址,下位是高地址,在函数调用时会优先分配高地址空间,然后再分配低地址空间。

2>、main()函数的栈帧

在C语言中main函数也是被调用的,如下图中:

<1>、代码先给mainCRTstartup分配空间,然后进入mainCRTstartup中调用__tnainCRTstartup

<2>、分配空间给__tnainCRTstartup,然后进入__tnainCRTstartup,再调用main

<3>、分配空间给main,然后才进入main函数中

 从vs上演示:

注释:vs2019及以上版本无法演示调用main函数的函数

用vs2013如下图所示:

用F10调试,查看调用堆栈,跳出main函数后,发现main函数之外还有两个被调用的

在此处:mainCRTstartup调用__tnainCRTstartup

              进入mainCRTstartup函数后

              __tnainCRTstartup调用main函数

二、函数栈帧的创建和销毁

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS
#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;
}

1、关于main()函数的操作

1>、为main()函数开辟栈帧

 2>、在main()函数中创建变量

2、关于Add()函数操作

 1>、调用Add()时的准备 

   

2>、给Add()函数开辟栈帧

 

3>、在Add()函数中创建变量并计算

4>、Add()栈帧的销毁

3、返回main()函数

 

总结

看到这里,想必之前存在的很多疑问已经迎刃而解。

比如:

1、局部变量是怎么创建的?

2、为什么局部变量的值是随机值?

3、函数是怎么传参的?传参顺序是怎样的?

4、形参和实参是什么关系?

5、函数调用是怎么做的?

6、函数调用是结束后怎么返回的?

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学Java的冬瓜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值