考研复习-函数栈帧(详解)

news2024/11/16 22:40:34

目录

1. 什么是函数栈帧

2.函数栈帧的创建和销毁解析

2.1相关寄存器:

2.2相关汇编命令

 运行代码:

3.预备知识:

4.正式开始:

4.1转到反汇编

4.2函数栈帧的创建

4.3函数栈帧的销毁


1. 什么是函数栈帧

我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。 那函数是如何调用的?函数的返回值又是如何待会的?函数参数是如何传递的?这些问题都和函数栈帧 有关系。 函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间 是用来存放: 函数参数和函数返回值 临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量) 保存上下文信息(包括在函数调用前后需要保持不变的寄存器)。

2.函数栈帧的创建和销毁解析

栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函 数,没有局部变量,也就没有我们如今看到的所有的计算机语言。 在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈,push),也可 以将已经压入栈中的数据弹出(出栈,pop),但是栈这个容器必须遵守一条规则:先入栈的数据后出 栈(First In Last Out, FIFO)。就像叠成一叠的术,先叠上去的书在最下面,因此要最后才能取出。 在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据 从栈顶弹出。压栈操作使得栈增大,而弹出操作使得栈减小。 在经典的操作系统中,栈总是向下增长(由高地址向低地址)的。 在我们常见的i386或者x86-64下,栈顶由成为 esp 的寄存器进行定位的。

2.1相关寄存器:

eax:通用寄存器,保留临时数据,常用于返回值

ebx:通用寄存器,保留临时数据

ebp:栈底寄存器

esp:栈顶寄存器

eip:指令寄存器,保存当前指令的下一条指令的地址

2.2相关汇编命令

mov:数据转移指令

push:数据入栈,同时esp栈顶寄存器也要发生改变

pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变

sub:减法命令

add:加法命令

call:函数调用,1. 压入返回地址 2. 转入目标函数

jump:通过修改eip,转入目标函数,进行调用

ret:恢复返回地址,压入eip,类似pop eip命令 

 运行代码:

#include <stdio.h>
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 3;
int b = 5;
int ret = 0;
ret = Add(a, b);
printf("%d\n", ret);
return 0;
}

3.预备知识:

首先我们达成一些预备知识才能有效的帮助我们理解,函数栈帧的创建和销毁。

1. 每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。

2. 这块空间的维护是使用了2个寄存器: esp 和 ebp , ebp 记录的是栈底的地址, esp 记录的是栈顶 的地址。 

3.函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异,

4.正式开始:

这段代码,如果我们在VS2019编译器上调试,调试进入Add函数后,我们就可以观察到函数的调用堆栈

函数调用堆栈是反馈函数调用逻辑的,那我们可以清晰的观察到, main 函数调用之前,是由 invoke_main 函数来调用main函数。 在 invoke_main 函数之前的函数调用我们就暂时不考虑了。 那我们可以确定, invoke_main 函数应该会有自己的栈帧, main 函数和 Add 函数也会维护自己的栈 帧,每个函数栈帧都有自己的 ebp 和 esp 来维护栈帧空间。 那接下来我们从main函数的栈帧创建开始讲解:

4.1转到反汇编

调试到main函数开始执行的第一行,右击鼠标转到反汇编。

注:VS编译器每次调试都会为程序重新分配内存,课件中的反汇编代码是一次调试代码过程中数据,每 次调试略有差异。

4.2函数栈帧的创建

lea是load effective address(加载有效地址)的缩写。而 lea edi,[ebp-0E4h]的意思就是把ebp-0E4h这个地址放到edi里面。还记得第二步move ebp,esp嘛?。执行完第二步后ebp和esp指向了同一个地址,然后第三步sub esp,0E4h,让esp指向的地址减了0E4h(228),,此后ebp指向的地址没有发生任何变化,第四步的3个push操作让esp指向的地址又减小了12(一次push减小4,3次push就减小12)。而当前的第五步中的地址ebp-0E4h也就是在执行完第三步后esp所指向的地址,就是要把这个地址放到edi里面(其实就是让edi指向这个地址,因为edi是一个变址寄存器,用存储地址的)如下图:

 

 

上面的这段代码最后4句,等价于下面的伪代码:

0xCC就是烫

接下来我们再分析main函数中的核心代码:

当我们跳转到Add函数,就要开始观察Add函数的反汇编代码了。

代码执行到Add函数的时候,就要开始创建Add函数的栈帧空间了。

在Add函数中创建栈帧的方法和在main函数中是相似的,在栈帧空间的大小上略有差异而已。

1. 将main函数的 ebp 压栈

2. 计算新的 ebp 和 esp

3. 将 ebx , esi , edi 寄存器的值保存

4. 计算求和,在计算求和的时候,我们是通过 ebp 中的地址进行偏移访问到了函数调用前压栈进去的 参数,这就是形参访问。

5. 将求出的和放在 eax 寄存器尊准备带回

图片中的 a' 和 b' 其实就是 Add 函数的形参 x , y 。这里的分析很好的说明了函数的传参过程,以及函数 在进行值传递调用的时候,形参其实是实参的一份拷贝。对形参的修改不会影响实参。

4.3函数栈帧的销毁

当函数调用要结束返回的时候,前面创建的函数栈帧也开始销毁。 那具体是怎么销毁的呢?我们看一下反汇编代码。

最后执行ret指令**,ret指令会从栈顶弹出元素给IP,也就是下一条要执行的指令的地址**。此时的

栈顶存储的就是call指令下一条指令的地址,这就是为什们当时要存call指令下一条指令的地址。

回到了call指令的下一条指令的地方:

但调用完Add函数,回到main函数的时候,继续往下执行,可以看到:

拓展了解: 其实返回对象时内置类型时,一般都是通过寄存器来带回返回值的,返回对象如果时较大的对象时,一 般会在主调函数的栈帧中开辟一块空间,然后把这块空间的地址,隐式传递给被调函数,在被调函数中 通过地址找到主调函数中预留的空间,将返回值直接保存到主调函数

的。

另外栈帧中还可能有的一些内容,以及内存中的位置

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

签约仪式如何策划和安排流程?如何邀约媒体现场见证报道

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 签约仪式的策划和安排流程&#xff0c;以及邀约媒体现场见证报道&#xff0c;都是确保活动成功和提升影响力的关键环节。以下是一些建议&#xff1a; 签约仪式的策划和安排流程 明确目标…

UE5 UE4 开发常用工具AssetDeveTool

AssetDeveTool工具&#xff0c;支持UE5 5.0-.5.3 UE4 4.26/4.27 下载链接&#xff1a; 面包多 https://mbd.pub/o/bread/ZZubkphu 工坊&#xff1a; https://gf.bilibili.com/item/detail/1104960041 包含功能&#xff1a; 自动化批量展UV功能 快速选择功能 自动化批量减面功能…

启动查看工具总结

启动目标&#xff1a;2s内优秀&#xff0c;2-5s普通&#xff0c;之后的都需要优化&#xff0c;热启动则是1.5s-2s内 1 看下大致串联启动流程&#xff1a; App 进程在 Fork 之后&#xff0c;需要首先执行 bindApplication Application 的环境创建好之后&#xff0c;就开始activ…

【CSP试题回顾】202109-2-非零段划分

CSP-202109-2-非零段划分 关键点&#xff1a;差分数组 详见&#xff1a;【CSP考点回顾】差分数组 时间复杂度分析 使用差分数组的优势在于&#xff0c;它将问题转化为了在一次遍历中识别并利用关键变化点&#xff08;波峰和波谷&#xff09;&#xff0c;从而避免了对每个可能…

【重要公告】BSV区块链协会开始对Teranode节点软件进行技术测试

​​发表时间&#xff1a;2024年2月22日 Teranode节点软件将使BSV区块链网络的交易处理速度提升至每秒110万笔&#xff0c;从而拓宽企业和政府客户的区块链应用范围。 2024年2月22日&#xff0c;瑞士楚格 - BSV区块链协会宣布已经开始对Teranode节点软件进行技术测试&#xff…

软考高级:系统工程生命周期阶段概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Vue:自动按需导入element-plus图标

自动导入使用 unplugin-icons 和 unplugin-auto-import 从 iconify 中自动导入任何图标集。 完整vite.config.js参考模板 https://download.csdn.net/download/ruancexiaoming/88928539 导入element-plus图标 命令行安装unplugin-icons pnpm i -D unplugin-icons//没有安装自…

Vue中用户权限如何处理?

Vue中用户权限如何处理&#xff1f; 在 Vue 中&#xff0c;可以采用多种方式来处理用户权限&#xff0c;以下是一些常见的方法&#xff1a; 1. 使用路由守卫 Vue Router 提供了 beforeEach 导航守卫&#xff0c;可以在路由跳转之前进行权限检查。例如&#xff1a; router.be…

【vue.js】文档解读【day 3】 | 条件渲染

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 文章目录 条件渲染前言&#xff1a;v-ifv-elsev-else-iftemplate中的v-ifv-showv-if vs v-show 条件渲染 前言&#xff1a; 在JavaScript中&#xff0c;我们知道条件控制语句可以控制程序的走向&#…

手写分布式配置中心(六)整合springboot(自动刷新)

对于springboot配置自动刷新&#xff0c;原理也很简单&#xff0c;就是在启动过程中用一个BeanPostProcessor去收集需要自动刷新的字段&#xff0c;然后在springboot启动后开启轮询任务即可。 不过需要对之前的代码再次做修改&#xff0c;因为springboot的配置注入value("…

746. 使用最小花费爬楼梯 (Swift版本)

题目 给你一个整数数组 cost&#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费。 限制条件 2…

6. 虚拟机及Linux安装

虚拟机及Linux安装 进行嵌入式项目开发&#xff0c;第一步就是要建立嵌入式开发环境&#xff0c;主要包括安装 Bootloader 工具、不同平台的交叉编译器&#xff08;如ARM 平台的arm-linux-gcc&#xff09;、内核源码树&#xff08;在需要编译和配置内核时&#xff09;、在调试…

Python-sklearn.datasets-make_blobs

​​​​​​sklearn.datasets.make_blobs()函数形参详解 """ Title: datasets for regression Time: 2024/3/5 Author: Michael Jie """from sklearn import datasets import matplotlib.pyplot as plt# 产生服从正态分布的聚类数据 x, y, cen…

Ps:渐变工具 - 经典渐变

渐变工具 Gradient Tool常用于背景填充和界面元素设计&#xff0c;可创建平滑的颜色过渡效果。也可用于图层蒙版上&#xff0c;控制图像或效果的平滑混合。 快捷键&#xff1a;G 渐变工具选项栏中有两种模式&#xff1a;渐变 Gradient和经典渐变 Classic gradient&#xff0c;经…

CSS中em/px/rem/vh/vw区别详解

文章目录 一、介绍二、单位pxemremvh、vw 三、总结 一、介绍 传统的项目开发中&#xff0c;我们只会用到px、%、em这几个单位&#xff0c;它可以适用于大部分的项目开发&#xff0c;且拥有比较良好的兼容性 从CSS3开始&#xff0c;浏览器对计量单位的支持又提升到了另外一个境…

信息系统项目管理师--进度管理

项⽬进度管理是为了保证项⽬按时完成&#xff0c;对项⽬所需的各个过程进⾏管理&#xff0c;包括规划进度、 定义活动、排列活动顺序、估算活动持续时间、制订项⽬进度计划和控制进度。⼩型项⽬中&#xff0c; 定义活动、排列活动顺序、估算活动持续时间及制定进度模型形成进度…

【办公类-21-09】三级育婴师 视频转音频Python

背景需求&#xff1a; 用AI对话工具试试能否Python将MP4视频转成音频&#xff0c;再转成文字docx&#xff08;不用格式工厂转&#xff09; 结果&#xff1a; 视频MP4转音频wav 视频MP4转音频wav 作者&#xff1a;AI对话大师&#xff0c; 时间&#xff1a;2024年3月8日 impo…

利用GPT开发应用004:从GPT-1到GPT-3

文章目录 一、GPT-1二、GPT-2三、GPT-3四、从GPT-3到InstructGPT 一、GPT-1 2018年年中&#xff0c;就在变换器架构问世一年后&#xff0c;OpenAI发表了一篇题为“通过生成式预训练改进语言理解”的论文&#xff0c;作者是Radford, Alec等人。在这篇论文中&#xff0c;该公司介…

ODI报错

三月 08, 2024 1:20:09 下午 oracle.odi.mapping 信息: Start generation of map physical design: MapPhysicalDesign New_Mapping.物理 三月 08, 2024 1:20:09 下午 oracle.odi.mapping 信息: Finished generation of map physical design: MapPhysicalDesign New_Mapping.物…

BUUCTF-Misc4

镜子里面的世界1 1.打开附件 解压&#xff0c;是一张图片 2. zsteg工具 用zsteg分析图片 3.得到flag ningen1 1.打开附件 是一张图片 2.binwalk 用binwalk -e 分离文件 3.ARCHPR工具 打开分离后的文件夹&#xff0c;有一个加密的压缩包&#xff0c;用ARCHPR解密 4.解密 将…