内功修炼《函数栈帧的创建和销毁》建议收藏
文章目录
- 前言
- 一、 寄存器的概念
- 二、 通用寄存器的结构
- 三、 指针寄存器和变址寄存器
- 四、 EBP和ESP
- 五、总结
前言
在前期的学习过程中,我们可能会有很多的困惑:
1️⃣ 局部变量是怎么创建的?
2️⃣ 为什么未初始化的局部变量的值是随机值?
3️⃣ 函数是如何传参的?以及传参的顺序是怎样的?
4️⃣ 形参和实参是什么关系?
5️⃣ 函数调用是怎么做的?
6️⃣ 函数调用结束后是怎么返回的?
⚠ 这里使用的环境是 Visual Studio 2013 ,提示不要使用太过高级的编译器,因为越高级的编译器越不容易观察。同时这里需要注意的是在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器。
一、 寄存器的概念
寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
二、 通用寄存器的结构
通用寄存器组包括AX、BX、CX、DX4个16位寄存器,用以存放16位数据或地址。也可用作8位寄存器。用作8位寄存器时分别记为AH、AL、BH、BL、CH、CL、DH、DL,只能存放8位数据,不能存放地址
1️⃣ AX(AH、AL):累加器。有些指令约定以AX(或AL)为源或目的寄存器。输入/输出指令必须通过AX或AL实现。
2️⃣ BX(BH、BL):基址寄存器。BX可用作间接寻址的地址寄存器和基地址寄存器,BH、BL可用作8位通用数据寄存器。
3️⃣ CX(CH、CL):计数寄存器。CX在循环和串操作中充当计数器,指令执行后CX内容自动修改,因此称为计数寄存器。
4️⃣ DX(DH、DL):数据寄存器。除用作通用寄存器外,在I/O指令中可用作端口地址寄存器,乘除指令中用作辅助累加器。
三、 指针寄存器和变址寄存器
1️⃣ BP( Base Pointer Register):基址指针寄存器。
2️⃣ SP( Stack Pointer Register):堆栈指针寄存器。
3️⃣ SI( Source Index Register):源变址寄存器。
4️⃣ DI( Destination Index Register):目的变址寄存器。
这组寄存器存放的内容是某一段内地址偏移量,用来形成操作数地址,主要在堆栈操作和变址运算中使用。BP和SP寄存器称为指针寄存器,与SS联用,为访问现行堆栈段提供方便。通常BP寄存器在间接寻址中使用,操作数在堆栈段中,由SS段寄存器与BP组合形成操作数地址即BP中存放现行堆栈段中一个数据区的“基址”的偏移量,所以称BP寄存器为基址指针。
SP寄存器在堆栈操作中使用,PUSH和POP指令是从SP寄存器得到现行堆栈段的段内地址偏移量,所以称SP寄存器为堆栈指针,SP始终指向栈顶。
寄存器SI和DI称为变址寄存器,通常与DS一起使用,为访问现行数据段提供段内地址偏移量。在串指令中,其中源操作数的偏移量存放在SⅠ中,目的操作数的偏移量存放在DI中,SI和DI的作用不能互换,否则传送地址相反。在串指令中,SI、DI均为隐含寻址,此时,SI和DS联用,Dl和ES联用。
四、 EBP和ESP
这是单独把 EBP 和 ESP单独拎出来,不用说它两肯定和我们的主题脱不了干系 —— EBP 和 ESP 是用来维护函数栈帧的。
下面就以一段简单的代码来演示:
#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;
}
不知道大家有没有好奇 Add 被 main 函数调用,而 main 函数被谁调用呢 ❔❓
1、调试代码后,打开调用堆栈
2、这时看到调用堆栈这个窗口 main 函数被调用了,问题也就出现了 —— main函数被谁调用了
3、当程序继续走时,它跳到了crtexe.c文件中,这时再看堆栈窗口发现 main 函数被 __tmainCRTStartup() 调用
4、而 __tmainCRTStartup() 又被 mainCRTStartup() 调用
解决完疑问后,这里就细看代码的底层是如何执行的 ❔❓
这里观察C语言代码所对应的汇编代码 —— 调试代码后,右击鼠标转到反汇编
1️⃣ 先为调用 main 函数的这个函数 __tmainCRTStartup 开辟函数栈帧,并用 esp 和 ebp 维护
2️⃣ 为 main 函数开辟函数栈帧
2.1、push ebp
压栈 ebp,esp 指向的位置也随之改变 (地址减小)
▶ 压栈前
▶ 压栈后
内功修炼《函数栈帧的创建和销毁》建议收藏相关推荐
- 程序员内功修炼——函数栈帧的创建与销毁
一.什么是函数的栈帧 c语言是由函数构成的,那么函数是如何进行传参的?如何调用的?如何返回值的?这些问题与函数的栈帧有关. 函数栈帧:就是函数调用过程中程序的调用栈所开辟的空间,这些空间用来存放: 1 ...
- 函数调用过程详解:函数栈帧的创建与销毁
前言:我们在学习C语言的过程中,可以会产生很多疑问,比如: 局部变量是怎么创建的 为什么局部变量的值不做初始化就是随机值 函数是怎么传参的?传参的顺序是怎么样的? 形参和实参是什么关系? 函数调用是怎 ...
- (动图详解)汇编视角观察函数栈帧的创建和销毁
目录 1.阅读本文的价值 2.函数栈帧及栈的概念 3.部分寄存器及汇编指令 4.main函数的调用 5.main函数的栈帧创建 6.变量的栈帧创建 6.函数传参 7.函数内部运算及销毁 ...
- 函数栈帧的创建与销毁
目录 前言 一.预备知识 1.内存区域的划分和分配 2.栈帧简介 3.寄存器简介 二.函数栈帧介绍 1.源代码 2.如何查看汇编代码 3.函数栈帧的创建与销毁(重点) 三.小彩蛋 总结 前言 最近在学 ...
- 程序员内功心法之函数栈帧的创建和销毁
目录 1.本节目标 2.相关寄存器 3.相关汇编指令 4.什么是函数栈帧 5.什么是调用堆栈 6.函数栈帧的创建和销毁 (1).main函数栈帧的创建与初始化 (2).main函数的核心代码 (3). ...
- 【C语言】程序员筑基功法——《函数栈帧的创建与销毁》
<函数栈帧的创建与销毁> 文章目录 1. 前言 2. 问题引入 3. 前提准备 3.1 寄存器 3.2 汇编指令 4. 函数栈帧的维护 5. 如何调用堆栈 6. 函数栈帧的创建和销毁 6. ...
- C语言内功修炼之函数栈帧的创建与销毁(举例加图解)
大家可能会函数栈帧不了解,可能都没有听过这个,不用着急,在理解函数栈帧之前,我们先来了解一下程序对内存使用的分区大概情况: 区域 作用 栈区(stack) 由编译器自动分配和释放,存放函数的参数值, ...
- 函数栈帧的创建和销毁图解
目录 一.问题: 二.寄存器 栈区 1.寄存器有哪些?有什么作用? 2.编译环境 3.栈区的使用习惯: 4.main函数也是被其他函数调用的 5.汇编代码 三.为main函数创建栈帧 1.main函数 ...
- 一文带你深入了解函数栈帧的创建和销毁
作者介绍:友友们好我是沐曦希,可以叫我小沐
最新文章
- 【Python】函数图像绘制:二维图像、三维图像、散点图、心形图
- 北京大学纳家勇治研究组在《美国国家科学院院刊》发文阐明时序记忆的神经机制
- linux的运维管理UNIT3
- 金碧辉煌!皇城定制5月22日正式对外运营开业!
- 服务器内存技术知识充电
- mysql字段数值累加_mysql字段值(字符串)累加 | 学步园
- np读取csv文件_pandas.read_csv函数参数详解
- 搜索Maven依赖资源_搜索Maven工件_搜索Maven构件_搜索依赖_搜索构件_搜索工件
- VoLTE技术中的会话持续性-eSRVCC
- Linux debian live USB,用 Live Magic 制作 Debian Live 光盘
- 那些小城里的分析大师们为什么发不了财?
- 基于SSM的大学拍卖网站(含文档)
- Python爬虫QQ空间
- Linux下zip文件解压乱码
- This request has been blocked; the content must be served over HTTPS.
- 关于“八音盒自定义弹奏”的一些想法
- 讲座记录——科技论文写作及科研方法
- Java Swing制作古老的打砖块游戏
- U盘图标不显示(转)
- 一个很好的JAVASCRIPT例子[转载]
热门文章
- cs1.5服务器指定ip,求上海地区cs1.5服务器IP
- 智慧书-永恒的处世经典格言:1-40
- Java6-7章复习
- UG数控编程:草图之视图方向着色方式和草图的基准设置
- 踏遍青山情未老 —— 九山顶重游记(五)
- EEA算法的Matlab实现
- html5画分形图形,HTML5/Canvas 可在线调整的朱丽叶分形图
- 推荐一个在线测试服务器延迟和丢包的工具 Ping.pe
- android连接酒店wifi,Android 在APP内、应用内 连接WiFi
- Excel加载项(VS2019、C#)