IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言中函数栈帧的创建与销毁,局部变量的创建 -> 正文阅读

[C++知识库]C语言中函数栈帧的创建与销毁,局部变量的创建


首先,给出一段简单的代码

#include <stdio.h>
int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a=42;
	int b=35;
	int c=0;

	c = Add(a, b);

	printf("%d\n", c);

	return 0;
}

代码实现了一个简单的函数,加法函数。

函数栈帧简单概念

每一个函数调用,都要在栈区指定一块空间,而这块栈空间就被称为函数栈帧。每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量
函数栈帧由两个寄存器中存放的指针所确定。

寄存器

在此简单提一下寄存器。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和地址。此处函数栈帧由esp和ebp寄存器确定空间范围。
下文还会用到的寄存器还有eax,ebx,ecx,edx这4个寄存器。
esp中存放的指针指向栈顶,ebp中存放的指针指向栈底。两个寄存器之间的内存空间就是函数栈帧。以最开始给出的加法函数为例,看图演示:
函数栈帧部分描述

函数栈帧的创建与销毁

接下来通过分析上述代码的汇编代码来讲述函数栈帧的主要创建过程。

  push        ebp  
  mov         ebp,esp  
  sub         esp,0E4h  

push意为压栈,即将某元素进入栈顶。第一行指令意为,将ebp的值放到栈顶,此时因为有新元素入栈,栈顶发生改变,且esp始终指向栈顶元素,故esp指向ebp值对应的位置。图示如下:
push    ebp
因为main函数也是被调用的,此处是被invoke_main的函数调用,因此,在调用main之前,esp和ebp在维护invoke_main的空间。

mov ebp,esp意为,将esp中的数据放入ebp中,因为esp中存放着指针,mov完成后,ebp就和esp一起指向同一元素。图示:
在这里插入图片描述

sub esp,0E4h ,sub是减法指令,指令意为esp=esp-0E4h
栈区空间使用特点为,先使用高地址,再使用低地址。此处esp值减小,则esp向上移动,指向新位置。而ebp留在原来的位置,esp和ebp之间出现了间隔,这个间隔就是两者维护的空间,即main函数的函数栈帧。
在这里插入图片描述

 push        ebx  
 push        esi  
 push        edi   

三个元素依次压栈,esp也依次指向栈顶元素。
在这里插入图片描述

 lea         edi,[ebp-24h]  
 mov         ecx,9  
 mov         eax,0CCCCCCCCh  
 rep stos    dword ptr es:[edi]

lea全称load effective address,加载有效地址
ecx中存入9h,eax中存入CCCCCCCC
这4条语句意为,将从edi开始向下ecx个dword(double word双字,一字为2个字节,dword为4个字节)初始化为eax中的内容。
即从edi开始,将4个字节的数据初始化为CCCCCCCC,进行9次这样的操作
在这里插入图片描述

    int a=42;
mov         dword ptr [ebp-8],2Ah  
	int b=35;
mov         dword ptr [ebp-14h],23h  
	int c=0;
mov         dword ptr [ebp-20h],0

将abc要赋的值,存入对应分配给abc的指定空间。
在这里插入图片描述

  	c = Add(a, b);
  mov         eax,dword ptr [ebp-14h]  
  push        eax  
  mov         ecx,dword ptr [ebp-8]  
  push        ecx

对照上图知,ebp-14h为b,ebp-8为a。以上指令,就是在传参。先传b的值,再传a的值,b,a分别放入寄存器eax和ecx并分别入栈,需要说明的是,传参过程中,参数存储在寄存器中,而并非在Add函数内部,图示如下:
在这里插入图片描述
然后执行call指令
在这里插入图片描述

  push        ebp  
  mov         ebp,esp  
  sub         esp,0CCh  
  push        ebx  
  push        esi  
  push        edi  
  lea         edi,[ebp-0Ch]  
  mov         ecx,3  
  mov         eax,0CCCCCCCCh  
  rep stos    dword ptr es:[edi]

以上指令是Add函数的部分。同main函数类似,通过几步完成Add函数栈帧的创建。如图
在这里插入图片描述

int z = 0;
  mov         dword ptr [ebp-8],0  
	z = x + y;
  mov         eax,dword ptr [ebp+8]  
  add         eax,dword ptr [ebp+0Ch]  
  mov         dword ptr [ebp-8],eax  
	return z;
  mov         eax,dword ptr [ebp-8]

ebp+8就是刚才传参时的a,即42,ebp+0Ch就是b,35,执行完的效果如图
将a+b的结果存入ebp-8。也就是说传参并没有传到Add函数内部,而是传到外面,需要时直接找到刚才传参的位置调用。
在这里插入图片描述
最后return z的时候,z的值存在ebp-8中,mov将z的值放入寄存器eax中,寄存器集成在CPU上,所以Add函数调用完成后,销毁局部变量,释放内存空间。z的值也正常存储,因为在函数结束前,已经拷贝到寄存器中了,寄存器是独立于内存的。

函数栈帧的销毁

  pop         edi  
  pop         esi  
  pop         ebx  

三个元素依次出栈,esp随之下移
在这里插入图片描述

mov         esp,ebp  
pop         ebp  
ret 

mov esp,ebp
函数完成,esp与ebp间隔消失,空间回收,函数栈帧随之销毁
在这里插入图片描述
pop ebp
pop意为出栈,ebp出栈,通过ebp–main中存储的数据,回到原来的位置
在这里插入图片描述
ret 栈顶元素出栈,通过栈顶存放的地址,转到对应地址的指令。即执行call指令下一行的指令。

007E18F1  push        ecx  
007E18F2  call        007E10B4  
007E18F7  add         esp,8  
007E18FA  mov         dword ptr [ebp-20h],eax 

add esp,8 ,刚才ret执行完,栈顶元素出栈,此时esp指向值为42的形参,esp+8,将两个形参所占空间释放。
mov dword ptr [ebp-20h],eax ,刚才将Add函数返回值存入了eax,eax再将值传入ebp-20h,即c。
在这里插入图片描述
最后依然是函数栈帧的销毁,上文已经讲过,此处不再赘述。

局部变量的创建

通过分析与观察,不难发现,main函数中的局部变量是在main函数栈帧创建之后,在函数栈帧内部规律地被分配空间。且因为在函数栈帧创建之初内部大量空间会被赋一个随机值,故在给局部变量赋值之前,局部变量存放的是一个随机值。局部变量在最终使用完之后,空间才会被释放掉。

笔者能力有限,如文章有问题,还请及时指正。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:03:37  更:2021-08-09 10:04:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 3:19:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码