【C/C++数据结构与算法】C语言函数栈帧

news2024/11/27 0:21:15

目录

一、源代码理论分析

二、主函数的创建

三、c语言代码的汇编


注:不同编译器环境的函数栈帧存在一定差异,本文使用VS2019

一、源代码理论分析

源代码:

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);
    return 0;
}
  • 源代码的主函数和自定义函数运行时都会在栈上开辟空间,变量、参数也是存储在栈里
  • 函数的创建与销毁、变量的创建与销毁都依靠寄存器实现,寄存器的作用是存储数据或地址
  • 寄存器有eax、ebx、ecx ...... 和 ebp、esp,后两个寄存器指向当前函数的始末,前面的数个寄存器一般保存数据
  • 参数传递、临时变量存储是依靠寄存器完成
  • 在栈中,栈底是高地址,栈顶是低地址
  • main函数也是需要其他函数进行调用的,由编译器实现

二、主函数的创建

1. 逐步骤调试,打开反汇编窗口和监视窗口,查询ebp、esp

        这里可见ebp、esp是存在的,ebp指向0x0055f9a0,esp指向0x0055f984

        ebp的值大于esp,即ebp指向高地址(栈底),esp在低地址(栈顶)

2. 逐步分析main函数创建反汇编代码

push ebp

push表示压栈,将ebp寄存器压入栈顶存储

执行之后可见esp的指向的地址发生改变,从0x0055f984变为0x0055f980,代表esp的地址减少了4字节,esp指向更低的地址

mov ebp,esp

move表示移动,将esp的值移动到ebp中,也就是ebp指向esp指向的地址,即从栈底移到栈顶

sub esp,0E4h

sub表示减法,指esp - 0E4h

0E4h是一个十六进制数,esp减去这个数之后指向更低地址的栈空间

esp指向的地址由0x0055f980变为0x0055f89c

push ebx

push esi

push edi

连续三次压栈,ebx、esi、edi压入栈顶

esp的指向的地址改变,从0x0055f89c变到0x0055f890

打开内存监视窗口,查询esp的内存地址,可以看到ebx、esi、edi的被压入栈(小端存储),这几个寄存器的值具体是什么我们暂不关注

lea edi,[ebp-24h]

lea 全名是 load effective address,加载有效地址

这行代码表示edi指向 [ebp-24h] 表示的地址,edi指向的地址为0x0055f95c

mov ecx,9

mov eax,0CCCCCCCCh

将9这个值移入到ecx中,将0xCCCCCCCC这个值移动到eax中

rep stos dword ptr es:[edi]

dword表示双字节,占4个字节

这行代码表示从 edi 指向的地址处(0x0055f95c),往高地址处(栈底)的9个双字节都写入0xCCCCCCCC,这里的9是ecx,0xCCCCCCCC是eax

经计算易得 0x0055f95c 到 ebp的地址 0x0055f980正好相差36,即36字节

打开内存监视进行查看地址0x0055f95c 到 0x0055f980 之间的值

edi最后指向edp指向的地址(main函数栈帧的起始地址)

接下来的 move 和 call 指令我们先暂不关注,call 指令是函数调用,并存储下一条指令的地址,部分编译器没有这两条语句或执行方式不同,这两行代码主要与主函数创建有关,代表主函数正是创建成功,接下来可以开始执行C语言代码

三、c语言代码的汇编

1. int a = 10;

mov dword ptr [ebp-8],0Ah

将0Ah移入ebp - 8 的地址处,ebp - 8的地址就是main函数空间中距离ebp8个字节的地方

0Ah是十六进制数代表十进制数10

通过mov完成赋值

2. int b = 20; int c = 0;

mov dword ptr [ebp-14h],14h

mov dword ptr [ebp-20h],0

同理,进行赋值

3. c = Add(a, b);

mov eax,dword ptr [ebp-14h]

push eax

将 ebp - 14h处的值存入寄存器eax中并将eax压栈

这里也就是复制b的临时变量进行传参

mov ecx,dword ptr [ebp-8]

push ecx

同理,将ebp - 8处的值存入寄存器ecx中并将ecx压栈

这是复制a的临时变量进行传参

由此可见函数在传参的时候,是从右到左进行传参的

4. 调用Add()函数

call 009711B3

将call指令的下一条指令的地址压栈保存,然后进入Add()函数体内

进入函数体内之后可观察到函数栈帧的创建和main函数栈帧的创建是一样的

函数栈帧创建完毕之后再开始执行C语言代码

int z = 0;

mov dword ptr [ebp-8],0

移动赋值

5. 参数的运算

mov eax,dword ptr [ebp+8]

add eax,dword ptr [ebp+0Ch]

mov dword ptr [ebp-8],eax

由上图可得,ebp + 8的地址处是ecx,也就是a的临时变量10

将10移动赋值给eax,此处的eax是另一个寄存器,不再是main函数保存参数时压栈的eax寄存器

ebp + 0Ch的地址处是b的临时变量20,将10 与20 相加得 30,存入eax寄存器中

ebp + 8 和 ebp + 0Ch分别是参数x 和 y 的值

最后将eax的值移动赋值给ebp - 8的地址处,也就是z的值

6. 返回值

return z;

mov eax,dword ptr [ebp-8]

将ebp - 8地址处的值赋值到eax寄存器中,也就是z的值

红色框内的汇编代码代表了函数栈帧的销毁

pop edi

pop esi

pop ebx

add esp,0CCh

pop表示出栈,将元素弹出栈空间(销毁)

esp + 0CCh,代表esp指向更高地址的空间(指向ebp指向的地址,退出Add函数)

cmp ebp,esp

call 00971235

mov esp,ebp

这几条指令不关注,最后是将ebp的值给esp,也就是回收Add函数的栈帧空间

pop ebp

ebp出栈,之前Add函数栈帧创建的时候,最开始的那个push ebp 指令是将上一个ebp的地址压栈存储了,此时pop ebp,ebp将回到上一个ebp指向的地址

ret

ret是回到call指令下一条指令的地址,之前call的时候将call指令的下一条指令的地址也是进行了存储了的,也就是重新回到了主函数,并从call指令的下一条指令的位置继续执行

7. 变量得到返回值

add esp,8

mov dword ptr [ebp-20h],eax

esp + 8 ,代表回收参数的栈空间

将eax的值赋给 ebp - 20h 处,eax存储的是返回值z

加法函数调用结束,加法运算完成

之后的若主函数还有代码则继续执行,若没有代码了则回收主函数栈帧

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

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

相关文章

Springboot分布式事务

一、先了解什么是本地事务 1. 概念 本地事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器位于同一节点相同数据库上。 又称为传统事务。它是一个操作序列,这些操作要么都执行,要么都不执行,是一个不可分割的工作单位。例…

【LeetCode】HOT 100(16)

题单介绍: 精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

英特尔发布12Q CMOS量子芯片

光子盒研究院 今天,英特尔公司发布了一种在主流CMOS工艺技术上构建的具有12个量子比特的量子芯片——Tunnel Falls。 Tunnel Falls测试芯片栖息在指尖上 Tunnel Falls量子芯片由12个量子点(或单电子晶体管)构建,可配置4至12个基于…

嵌入式 QT usb camera库驱动摄像头

目录 前言 ​编辑 1. 交叉编译 ffmpeg 1.1 先拿到ffmpeg的压缩包 1.2 把ffmpeg源码复制到虚拟机,并解压压缩包 1.3 解压之后我们要进入到解压文件中进行编译成库 1.5 make 1.6 make install 2.usbcame库使用 2.1 获取usbcame库并解压 2.2 解压完成后我们…

zabbix-3-agent安装

1.CentOS release 5 1-1.centos5 32位 [rootLV zabbix]# cat /etc/redhat-release CentOS release 5 (Final) [rootLV zabbix]# uname -a Linux LV 2.6.18-53.el5xen #1 SMP Mon Nov 12 03:26:12 EST 2007 i686 i686 i386 GNU/Linux确定了系统centos5 32位rpm方式安装&#…

【深度学习】3-1 神经网络的学习- 学习基础/损失函数

学习基础 神经网络的学习。这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程。 神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指可以由数据自动决定权重参数的值。 数据驱动 数据是机器学习的命根子。从数据中寻找答案、从数据中发…

接口测试框架之APIAutoTest框架

目录 前言 框架简介 框架介绍 框架技术栈图 框架组件图 框架执行流程图 测试用例设计 测试报告 结语 前言 APIAutoTest框架是一款基于Python语言和unittest框架的API自动化测试框架。它可以帮助测试人员快速搭建API测试环境,并通过代码自动化实现API的测试…

每年降本100万元+!企业研发管理可以这样做....

随着市场的定制化需求越来越多,非标设计越来越多;订单交付周期要求短,导致设计人员的设计周期进一步压缩,设计准确率的重要性进一步提升,这些都对企业研发管理提出了更严峻的挑战。 本期干货内容分享 装备制造企业研发…

计算机网络基础学习指南

前言 计算机网络基础是研发/运维工程师都需掌握的知识,但往往会被忽略。 今天,我将对计算机网络基础学习进行详细阐述,涵盖 TCP / UDP协议、Http协议、Socket等,希望你们会喜欢。 1、计算机网络体系结构 1.1 简介 定义 计算机…

Linux基础学习之目录结构、ls命令

1、win系统可能有多个盘,那么就会对应多个文件树,但是Linux系统只有一个文件树,对应的也只有一个根目录,叫做 / 。 2、win与Linux表示层级关系的斜杠的方向不同,一个是斜杠,一个是反斜杠,Linux…

Three.js3D可视化介绍,以及本地搭建three.js官网

一、什么是Three.js three.js官网:https://threejs.org/ Three.js是一个基于WebGL的JavaScript 3D图形库,它可以轻松地在浏览器中创建3D场景和动画。同时,它支持外部模型和纹理的导入,让开发者可以更加便捷地创建出震撼的3D场景…

详细的聊一聊如何使用响应式图片,提升网页加载速度

开篇 确保图片在所有屏幕尺寸上都能良好显示是一项困难的任务,因为你需要考虑图片的大小、图片的放置位置、显示图片的比例、用户连接的速度等等众多因素。结果是,大多数开发者只会为所有屏幕尺寸使用同一张图片,并让浏览器调整图片的大小以适…

【SCI征稿】仅1个月22天录用,极速录用见刊,可接受智能交通,自动驾驶汽车,新型智能算法,智能交通系统,安全运输,交通拥堵等领域

智能算法类SCIE&EI ◆ 影响因子:4.0-5.0 ◆ 期刊分区:JCR2区,中科院3区 ◆ 检索情况:SCIE&EI 双检,正刊 ◆ 征稿领域:智能算法在智能交通中的应用,包括自动驾驶汽车、新型智能算法、…

20个ArcGIS Pro 提示和技巧

ArcGIS Pro是最通用的GIS软件在当今的行业中。为了帮助你充分利用ArcGIS Pro,我们整理了一份20个提示和技巧。 这些技巧包括从基本的定制选项到高级地理空间分析和数据可视化技巧。 链接地图视图 在ArcGIS Pro中链接视图有助于同步显示一个项目中的多个地图或场景…

java项目之汉服文化平台网站(ssm+vue)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的汉服文化平台网站。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者:风歌&…

2017年全国硕士研究生入学统一考试管理类专业学位联考写作试题

2017年1月真题 四、写作:第56~57小题,共65 分。其中论证有效性分析30 分,论说文35分。 56、论证有效性分析: 分析下述论证中存在的缺陷和漏洞,选择若干要点,写一篇600字左右的文章,对论证的有…

GPT提示词系统学习-第二课-使用GPT帮你“填表格”

开篇 前面我们说到了GPT的提示词使用的好不好对你可以得到精准的答案是至关重要的。今天我们来看看,GPT中如何使用提示词来帮助我们填一个表格。 参照样本让GPT制作可填表格 请阅读以下销售邮件。删除任何可用于识别个人身份的信息 (PII),并用相应的占位符替换它。 例如,…

BIO-NIO-AIO案例

BIO-NIO-AIO案例 1、BIO编程 BIO 有的称之为 basic(基本) IO,有的称之为 block(阻塞) IO,主要应用于文件 IO 和网络 IO, 这里不再说文件 IO, 大家对此都非常熟悉,本次课程主要讲解网络 IO。 在 JDK1.4 之前,我们建立网络连接的时…

endnotex9 在word中插入参考文献遇到的问题

添加超链接 在EndNote X9中点击如下按钮 勾选如图所示选项后确认即可 找到插入文献的上标,按住“Ctrl”后鼠标点击即可跳转到对应文献 修改文献添加位置 先使用endnote插入一篇文献,然后到达插入文献的位置,右键点击。 选择切换域代码 将其…

国内首个,Postcat 上线 AI 生成 API 功能,写接口动几下就行

近期AI风潮席卷全球,Postcat 作为新一代 API 生产力工具,从发布的第一天起就在思考如何通过AIAPI以及插件化架构来更好的满足开发者的需求。 今天我们很高兴的向大家宣布,Postcat.com 正式上线 AI 生成 API 的功能,并且是国内首个…