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语言分层理解(函数栈帧的创建和销毁)

前言

我们都知道函数是个很神奇的东西,程序员可以自己写个函数完成对应的功能,但是这里有很多实现的小细节。具体我们来用一段短小精悍的代码来解释函数栈帧的创建和销毁。
在理解的同时,我们要关注以下这几个问题:

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

注意:不同编译器下,函数调用过程中栈帧的创建有差异的,具体细节取决于编译器的实现

正题

1.了解寄存器

1.1 寄存器是什么?

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。详细一点就是寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。

1.2 常见的寄存器

4个数据寄存器(eax、ebx、ecx、edx)
2个变址和指针寄存器(esi、edi)
2个指针寄存器(esp、ebp)
esp:寄存器存放当前线程的栈顶指针
ebp:寄存器存放当前线程的栈底指针
esp和ebp这两个寄存器中存放地址,这两个地址用来维护函数栈帧

具体寄存器知识还有很多,这里我们先做了解。

1.3 什么是栈,什么是栈帧?

1.3.1 什么是栈?

在数据结构中,栈是限定仅在表尾进行插入或删除操作的线性表。栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。
在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值,是由系统自动分配的,一般速度较快;存储地址是连续且存在有限栈容量,会出现溢出现象程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使栈减小。栈用于维护函数调用的上下文,离开了栈函数调用就没法实现。

1.3.2 什么是栈帧?

每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame).每个独立的栈帧一般包括:

  1. 函数的返回地址和参数
  2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量
  3. 函数调用的上下文

栈是从高地址向低地址延伸,一个函数的栈帧用ebp 和 esp 这两个寄存器来划定范围,ebp 指向当前的栈帧的底部,esp 始终指向栈帧的顶部。

1.4 常见的反汇编指令

add:加法指令,第一个是目标操作数,第二个是源操作数,格式为:目标操作数 = 目标操作数 + 源操作数

sub:减法指令,格式和add格式一样

call:调用函数,一般函数的参数放在寄存器中

ret:跳转会调用函数的地方。对应于call,返回到对应的call调用的下一条指令,若有返回值,则放入eax中

push:把一个32位的操作数压入堆栈中,这个操作在32位机中会使得esp被减4(字节),也就是说,push指令一旦下达,esp的指针偏移量就会减4

pop:与push相反,esp每次加4(字节),一个数据出栈

mov:数据传送。第一个参数是目的操作数,第二个参数是源操作数,就是把源操作数拷贝到目的一份

lea:取得第二个参数地址后放入到前面的寄存器(第一个参数)中。(lea就是load effective address的意思)

stos:串行存储指令,它实现把eax中的数据放入到edi所指的地址中,同时edi后移4个字节

jmp:无条件跳转指令,对应于大量的条件跳转指令

cmp:进行比较两个操作数的大小,为第一个操作减去第二个操作数,但不影响第两个操作数的值

以上知识目前只了解,待我能力杠杠的时候,会深度去探讨和研究这些汇编和底层的东西,现在只需要知道即可。

上面的准备知识已经完毕,下面我们一起来通过代码调试到汇编,从汇编的角度去看问题。

2.探讨函数栈帧的创建和销毁

首先展示代码:

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

2.1 main函数被谁调用?

我们一定要知道一个知识:每个函数调用都要创建自己的空间。
有了这句话我们就想知道main函数是不是也是被别的函数调用的呢?是的,main函数也是被调用的,我们用vs2022x86版本来看(不同的版本和不同的编译器其中的实现都有所不同)。




结论:main函数是被其他函数调用的,具体是被invoke_main这个函数调用的,而这个invoke_main这个函数被_srct_common_main_seh这个函数调用的,这个_srct_common_main_seh函数是被_srct_common_main这个函数调用的。而这个_srct_common_main这个函数是被mainCRTStartup调用的。
这就搞清楚了main函数被调用的过程。再次理解了每个函数都是被调用的,都创建了自己的空间。

2.2 怎么在栈区开辟空间以及如何利用空间?

首先要知道这个知识点:函数的创建都是在栈上开辟空间的。
其次,函数既然是栈上开辟空间,那么如何利用呢?看图解释:

2.3 汇编角度深入函数栈帧的创建和销毁

在x86情况下,调试起来看这段代码的整个流程:

2.3.1 从main函数开始理解栈帧

这是main函数里面的反汇编代码:

3 问题问答

这张图就可以解决上述问题。
再来对上述问题进行总结:

1.局部变量是怎么创建的?
回答:就是把对应的数据放进寄存器中。

2.为什么局部变量不初始化的值是随机值?
回答:在创建函数栈帧时,按照对应的设置个数,把栈顶指针指向的地址,向下按照对应的设置个数进行设置,设置为0xCCCCCCCC的值,所以我们看到有时候就是随机值的现象。

3.函数是怎么传参的?传参的顺序是怎么样的?
数据放进寄存器传参,传参的顺序是从右向左的。

4.形参和实参是什么关系?
形参就是实参的一份临时拷贝,用的寄存器存储数据,形参使用的时候直接找到寄存器中存储的数据直接使用。

5.函数调用是怎么做的?
首先开辟函数栈帧,然后进行相应的操作。

6.函数调用是结束后怎么返回的?
值是通过寄存器返回的。函数是通过ret指令返回到进入函数时记录的地址。

感谢支持,谢谢你们的陪伴,我们一起加油!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:11  更:2022-10-08 20:22:42 
 
开发: 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/19 2:49:41-

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