函数栈帧的形成与释放

article/2025/10/18 19:57:16

✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!!
📃个人主页:@rivencode的个人主页
🔥系列专栏:玩转C语言
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习

1.栈区的特点
在这里插入图片描述
栈区是从高地址向低地址方向生长:高地址是栈底,低地址是栈顶,也使用高地址空间在使用低地址空间。

在这里插入图片描述
但由起始地址(地址最低的地址),存放变量的字节地址是顺序且递增的

在这里插入图片描述
这就是为什么数组的元素是地址是递增的,虽然栈是从高地址向低地址方向生长,但是数组是整体在栈上开辟空间,数组的其他元素的地址是依次递增

2.函数栈帧

在讲函数栈帧之前先看常用的汇编指令,和寄存器
在这里插入图片描述
接下来就以main函数调用Add函数为例,详细阐述调用Add函数,形成函数栈帧,函数调用完毕释放栈帧的详细过程,其中涉及到形成临时变量,形成函数栈帧,函数结束如何销毁栈帧,如何返回到调用Add函数的main中继续执行后面的代码。
在这里插入图片描述
vs2013 有栈随机化的处理(有关数据的地址可能不一样),重新运行代码可能会导致,每次看到的相关数据可能会不太一致,不过我们重点关注变化原理和过程,

先看一下函数调用的整个过程

请添加图片描述
接下来就是逐段代码详细讲解

main函数也是被其他函数调用
在这里插入图片描述

main函数被其他函数调用,则形成main函数的栈帧(在栈分配一块内存)。

在这里插入图片描述
在这里插入图片描述
这里如何形成的main栈帧,等讲完main函数调用Add函数形成Add函数的栈帧过程就理解了。

在这里插入图片描述
int x =0xA对应的汇编代码执行前
在这里插入图片描述
int x =0xA对应的汇编代码执行后
在这里插入图片描述
int y =0xB 与 int z =0 执行完之后,与上面过程类似
在这里插入图片描述

三个变量分配内存并初始化。
在这里插入图片描述

形成x,y的临时变量a,b(形参)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

总结:

在这里插入图片描述
1.临时变量的形成是在函数正式被调用就形成了的
2.形参实例化的顺序是从右向左

在这里插入图片描述
接下来开始调用Add函数
在这里插入图片描述
在这里插入图片描述
函数调用包含两个
1.压入返回地址(入栈返回地址)
2.转入目标函数

第二好理解,要调用Add函数肯定要转入Add函数中执行Add函数的代码,但等函数调用完毕得返回main函数中在继续执行后续代码,所以必须保存返回地址->返回main函数调用Add函数的下一条指令。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
返回地址入栈,栈顶上移
在这里插入图片描述

接下来就是创建Add函数栈帧,但在这之前要线存储main函数栈底地址保存下来(入栈),因为Add函数调用完毕之后,销毁栈帧,此时得栈底指针ebp与栈顶指针esp要重新指向main函数栈帧栈底与栈顶,所以必须提前保存main函数栈帧栈底地址。
在这里插入图片描述
先保存main函数栈帧栈底地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
接下来就是形成Add函数的栈帧
第一步:
在这里插入图片描述
在这里插入图片描述
第二步
在这里插入图片描述
在这里插入图片描述

总结:
在这里插入图片描述
当函数被调用时,即Add函数被调用时,编译器就会自动形成Add函数栈帧,至于函数的栈帧大小,编译器也会自己根据函数中变量与变量的类型来估计函数栈帧的大小,总之一句话函数栈帧由编译器搞定

Add函数栈帧开辟成功后,则开始执行Add函数中的代码,实现变量分配内存并初始化及数据运算。
在这里插入图片描述
int c =0 对应的汇编代码执行前

在这里插入图片描述
int c =0 对应的汇编代码执行后
在这里插入图片描述
此时将c变量分配空间并初始化为0
在这里插入图片描述
接下来就是进行加法运算
在这里插入图片描述

在这里插入图片描述

ebp+8就是保存的0xA也就是a变量
ebp+c就是保存的0xB也就是b变量

在这里插入图片描述
在这里插入图片描述
此时就完成了c=a+b
在这里插入图片描述
最后返回的时候将c的值写入eax临时寄存器中,也就是说Add函数的返回值是通过CPU中的临时寄存器返回
在这里插入图片描述
接下来就是函数调用完毕,释放Add函数的栈帧,返回main函数中执行,栈底指针ebp与栈顶指针esp重新指向main函数的栈帧栈底与栈顶
在这里插入图片描述
在这里插入图片描述

下图这句代码相当于释放Add函数的栈帧
在这里插入图片描述

在这里插入图片描述
使栈底指针ebp重新指向main函数栈帧栈底
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此时eip寄存器拿到栈顶的返回地址,则即可返回main函数中执行main函数后续代码
在这里插入图片描述
回到main函数中,直接执行
add esp,8 即让esp后移8个单位,即释放原来的临时变量

在这里插入图片描述
自此Add函数栈帧销毁,所以入栈元素全部销毁包括原来入栈的两个临时变量
在这里插入图片描述
接下来就是接收返回值,前面已经讲了返回值c变量的值已经存储在eax临时寄存器,现在将eax中的返回值0x15,移动到ebp-20h中而ebp-20h内容就是z变量,相当于将返回值放入z变量中
在这里插入图片描述
在这里插入图片描述
至此整个调用Add函数创建栈帧,执行完毕后释放栈帧过程全部完毕

其他函数的调用也就类似,main函数也是被其他函数调用,当main函数被调用时,编译器自动形成main函数栈帧,等main函数执行完毕后也会释放main的栈帧

总结:
函数调用返回的整个过程
在这里插入图片描述
1.调用函数,需要先形成临时拷贝,形成过程是从右向左的
2.临时空间的开辟,是在对应函数栈帧内部开辟的,函数调用完毕,栈帧结构被释放掉,因此函数中的变量的空间也随之释放,所以临时变量具有临时性。
3.调用函数是有成本的,成本体现在时间和空间上,本质是形成和释放栈帧有成本
4. 函数调用,因拷贝所形成的临时变量,变量和变量之间的位置关系是有规律的

在这里插入图片描述


http://chatgpt.dhexx.cn/article/XlFcFYEP.shtml

相关文章

【函数栈帧的创建和销毁】(超详细图解)

想必大家在学完C语言函数章节之后,是否有这样的困惑: 局部变量是怎么创建的 ? 为什么局部变量的值是随机值 ? 函数是怎么传参的?传参的顺序又是什么样的 ? 形参和实参是什么关系 ? 函数调用…

C语言函数栈帧详解

系列文章目录 前言 最近正在学习栈帧方面的知识,由于本人对汇编不太熟悉,对其中频繁出现的ESP寄存器和EBP寄存器一直没搞清楚,在查找资料后,在此进行整理,方便以后温故知新。 一、预备知识 要清楚理解栈帧的概念&…

详解栈帧结构

https://www.1024do.com/?p367 栈帧结构 含义:C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录,是编译器用来实现过程函数调用的一种数据结构。 从逻辑上讲,栈帧就是…

函数栈帧详解

目录 一.什么是函数栈帧 1.寄存器: 2.函数栈帧 3.栈帧的作用和维护 4.栈帧结构 二.函数栈帧的创建 1.汇编代码 2.main函数函数栈帧的创建 1.汇编语言讲解: 2.栈帧创建: 3.详细步骤 3.ADD函数栈帧的创建 栈帧创建: 3.函…

栈帧

首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(地址地)。下图为典型的存取器安排,观察栈在其中的位置 入栈操…

什么是函数栈帧

函数栈帧的创建与销毁 一、函数栈帧的创建1.寄存器2.函数栈帧3.函数中调用函数 二、函数栈帧的销毁总结 一、函数栈帧的创建 1.寄存器 一般来说,计算机中的寄存器有六种 分别是:eax, ebx, ecx,edx,ebp,esp 而ebp,esp这两个寄存器中存放的是地址&#…

栈帧 stack frame

栈帧 stack frame 每一次函数调用都会维护一个栈帧(stack frame),栈帧主要用于传递参数、保存返回地址、保存局部变量等。先直接上一个《深入理解计算机系统》上的原图。 其中,%rsp 指向栈顶位置,%rbp 指向栈底位置。…

C/函数栈帧

🌱博客主页:大寄一场. 🌱系列专栏:C语言学习笔记 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 ​ 目录 前言 寄存器 1. 寄存器的种类与功能 C语言汇编指令介绍 函数栈帧的创建与销毁过程 1.函数栈帧的…

浅谈函数栈帧(Stack Frame)

💙作者:阿润菜菜 📖专栏:C 本文目录 什么是栈帧 在调试中观察 总结 什么是栈帧 那我们先来看看什么是栈: 栈(stack)是限定仅在表尾进行插入或者删除的线性表。栈是一种数据结构,它按照后进先出的原则存储…

栈和栈帧

栈 堆栈(stack)又称为栈或堆叠,是计算机科学里最重要且最基础的数据结构之一,它按照FILO(First In Last Out,后进先出)的原则存储数据。 栈的相关概念: 栈顶和栈底:允许元素插入与删除的一端…

函数栈帧的创建和销毁(图解)

目录 基础知识介绍1. 寄存器的种类与功能2. 常用汇编指令3. 内存模型 演示函数栈帧的创建销毁过程1. 为main()函数开辟栈帧2. 在main()函数中创建变量3. 调用Add()函数前的准备4. 为Add()函数开辟栈帧5. 在Add()函数中创建变量并运算6. Add()栈帧的销毁7. 返回main()函数栈帧 总…

运行时栈帧结构是怎样的?

写在前面 本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 栈帧(Stack Frame)是J…

函数栈帧(详细图解)

目录 一、栈 二、常用寄存器及简单汇编指令 三、理解栈帧 3.1 main函数栈帧创建 3.1.1 main函数栈帧创建动态演示 3.2 局部变量创建 3.2.1 局部变量创建动态演示 3.3 函数传参与调用 3.3.1 函数传参 3.3.2 函数传参动态演示 3.3.3 函数调用 3.3.4 函数返回 四、END…

栈帧详解——C语言进阶

目录 传统艺能😎过渡区🤣正片开始👀寄存器👏main函数创建👏局部变量创建👏函数部分👏形参与实参👏 传统艺能😎 小编是大一菜鸟不赘述,欢迎大佬指点江山&…

栈帧结构详解

前言 Java虚拟机以方法作为基本的执行单位,“栈帧”是用于支持虚拟机进行方法调用和执行的数据结构,每一个方法从调用开始到执行结束,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程,栈帧也是虚拟机运行时数据区中虚拟机栈的栈…

浅谈栈帧

一、 什么是栈帧? 什么是栈帧,首先引用百度百科的经典解释:“栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。 实际上,可以简单理解为:栈帧就是存储在用户栈上的(当然内…

栈帧(Stack Frame)

0x01.栈在计算机中的应用 在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值,是由系统自动分配的,一般速度较快;存储地址是连续且…

什么是栈帧

栈帧浅析 什么是栈帧 引用百度百科中的解释: 栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。函数的每次调用,都有它自己独立的栈帧。栈帧中维持着函数调用所需要的各种信息,包括函数的入参、函数的局部变…

【详解】函数栈帧——多图(c语言)

目录 前言 一.函数栈帧是什么? 二、栈帧准备知识 1.内存分区 2.什么是栈? 3.esp,ebp,eax寄存器 三、详解栈帧创建与销毁全过程 调用函数之前: 将传入函数的值放入栈中 函数执行: 1.保护当前ebp 2.…

【mcuclub】模数转换ADC0832

一、实物图 二、原理图 编号名称功能1CS片选使能,低电平芯片使能。2CH0模拟输入通道0,或作为IN/-使用。3CH1模拟输入通道1,或作为IN/-使用。4GND电源地5DI数据信号输入,选择通道控制。6DO数据信号输出,转换数据输出。7…