函数的栈帧

前言:

1.请使用vs2013调试,我使用vs2019被恶心到了,封装严重,不利于观察。 

2.函数栈帧:函数就是程序,程序就需要空间来运行,所以我们要为他分配空间,分配的空间用ebp esp维护,前者在底后者在顶,至于具体什么是ebp esp,我只能说他们是32-bit的寄存器,具体请看:

esp is the stack pointer. ebp is for a stack frame so that when you enter a function, ebp can get a copy of esp at that point. Everything already on the stack, the return address, passed-in parameters, etc. and things that are global for that function (local variables) will now be a static distance away from the stack frame pointer for the duration of the function. esp is now free to wander about as the compiler desires and can be used when nesting to other functions (each needs to preserve the ebp naturally).

It is a lazy way to manage the stack. It makes compiler debugging and understanding compiler-generated code easier, but it uses a register that could have been otherwise general-purpose.

//https://stackoverflow.com/questions/21718397/what-are-the-esp-and-the-ebp-registers

翻译并理解一下就是: 

ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向内存中的栈区的最上面一个栈帧的栈顶。

EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向内存中的栈区的一个栈帧的底部。

这句话很抽象,你就记着:一个函数中可以一直调用其他的函数,形成一种嵌套的关系,但是一个CPU只有一个ESP EBP,所以他俩必须保存当前正在执行代码的栈帧。

当你进入一个函数时,ebp原来的值push到栈上,然后ebp被用esp的值覆盖掉,这相当于ebp 会保存esp 的值,然后此时esp会进行SUB操作,也就是跳到更低的地址去,相当于开了空间。

这种方式被认为是一种相对懒惰的栈管理方式。它虽然简化了编译器调试和理解编译器生成的代码的过程,但也使用了一个本可以作为通用目的的寄存器。

如果你还要详细了解,那就要看看汇编语言课程了,也可以看看这个链接

4.vs的反汇编代码中显示的是十六进制,比如A代表十进制的10

5.dword ptr [ebp-14h]这一句相当于将ebp中的值减去20也就是5个框,即上移5个框,dword操作的是四字节量级,也就是一个框。

6.用文章来演示这个动态的过程稍显累赘,应该直接调试来的直观。

7.每次pop都是从esp那里pop,人家是栈顶指针,不要以为哪里有数据你就从哪里pop。

8.每push一次,esp的值都要减,相当于图中的往上移。

9.

esp是32-bit的register(寄存器),也就是四个字节,我们用一个框代表四个字节,esp指向箭头这里,表明它里面的值放的是8ca040h 

10.图示:

写好源代码:

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

观察方法:

main函数也是被其他函数调用的,所以esp ebp 早早已经有了值,所以我们进入main函数前栈区的函数栈帧是这样的:

esp ebp存储的是调用我们main函数的那个函数(VS中有两层调用,mainCRTStartup()和另一个函数 )的栈帧的顶、底地址。 

按下F11,启动程序,转到反汇编,去掉符号名(红框)。 

我们看到在正式执行我们的main函数代码之前,程序还做了不少事情,比如将之前(调用main将函数的那个函数)的ebp在栈上存起来(其实就是push到栈上即可),然后将ebp esp更新为计算的main函数的栈帧大小,也就是为main函数开辟栈帧并用0CCCCCCCh刷新赋值。

 执行完后,此时栈区结构变为:

然后到了下述三行代码: 

 

执行完上述代码将: 

 

 然后到了:

 

此时执行前两行后:
 

再执行第3-4行:
 

注意这几步都是Add这一句引发的动作,他要两个参数,我们得给他准备,相当于把 a b(实参)的值拷贝(假设叫做a' b'(形参的值))了一份放在了栈上,我们可以预料到Add函数中会通过偏移来找到 a' b'。

注意:这就是我们常说的形参是实参的拷贝,你修改后者不影响前者的本质体现。

此时我们的代码到了:

 好了,我们准备执行最后一行call,按下F11:

我们发现栈上被push了一个值,定情一看,竟然是call的下一个语句的地址:

即:00C21450,那说明call这个汇编就做了这个事。看起来我们待会儿要用这个地址,也就是去执行这个地址的语句,确实是这样,我们从call走,回来时不能再原地踏步了,确实应该执行下一句,人家已经提前存储起来了,厉害。

call也将代码带到了Add函数这里:

我们可以看到,int z = 0是Add的第一行代码,但是在这之前我们仍然做了不少事,为它分配栈帧.....

我们一直执行到int z = 0之前;栈区结构如下(用0CCCCCCh刷新我没有标出): 

 

 然后,一直执行完:
 

 到了这里:

看起来他把30这个加后的结果放在了eax寄存器里。

来到这里:

 

三个pop就是把这三个值分别放在对应的寄存器中。这不重要。

然后来到了倒数第三行, 一口气执行两行,剩下最后一行ret了:

执行ret其实本质是pop栈顶的一个值,然后把程序跳到那个值对应的语句去:
所以我们的代码来到了:
 

也就是call的下一个语句,我们早早就存起来它的地址了。

 此时我们执行红框,让esp朝着高地址偏移两个框(8字节),然后把eax也就是我们要的30放在[ebp-20h]也就是c那里去。

看起来是:我们是先把形参抛掉,然后把装在eax寄存器中的我们要的结果赋值给c。

其他的语句不再重要了。

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

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

相关文章

机器学习基础04

目录 1.朴素贝叶斯-分类 1.1贝叶斯分类理论 1.2条件概率 1.3全概率公式 1.4贝叶斯推断 1.5朴素贝叶斯推断 1.6拉普拉斯平滑系数 1.7API 2.决策树-分类 2.1决策树 2.2基于信息增益的决策树建立 2.2.1信息熵 2.2.2信息增益 2.2.3信息增益决策树建立步骤 2.3基于基…

如何解决IDE添加错误GitHub token后无法连接GitHub的问题

背景 当初学者首次使用IDE(IDEA、Xcode等)对GitHub仓库进行操作(push、fetch)时,会提示输入GitHub账户和token,如果这时候你一不小心输入了错误的token,之后你就叫天天不应叫地地不灵了&#xf…

PPT技巧:如何合并PPT文件?

在工作与学习中,PPT(PowerPoint)演示文稿已成为信息传递、项目汇报、教育培训等领域不可或缺的工具。随着任务的累积,我们往往会积累大量单独的PPT文件,每个文件可能包含特定章节、项目阶段或是不同主题的内容。为了更…

安全见闻1-5

涵盖了编程语言、软件程序类型、操作系统、网络通讯、硬件设备、web前后端、脚本语言、病毒种类、服务器程序、人工智能等基本知识,有助于全面了解计算机科学和网络技术的各个方面。 安全见闻1 1.编程语言简要概述 C语言:面向过程,适用于系统…

k-近邻算法(K-Nearest Neighbors, KNN)详解:机器学习中的经典算法

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

LeetCode297.二叉树的序列化和反序列化

题目要求 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序…

蓝牙5.0模块助力闹钟升级,开启智能生活第一步

随着智能家居产业的快速发展,智能闹钟作为其中一个重要的品类,逐渐从单一的时间提醒功能演变为集音频播放、语音交互、智能控制等多种功能于一体的智能设备。而在这些功能的实现中,蓝牙音频模组扮演着核心角色。 1、蓝牙音频模组的功能概述 …

自己动手写Qt Creator插件

文章目录 前言一、环境准备1.先看自己的Qt Creator IDE的版本2.下载源码 二、使用步骤1.参考原本的插件2.编写自定义插件1.cmakelist增加一个模块2.同理,qbs文件也增加一个3.插件源码 三、效果总结 前言 就目前而言,Qt Creator这个IDE,插件比…

力扣经典面试题

1.本题的目标是判断字符串ransomNote是否由字符串magazine中的字符构成,且由magazine中的每个字符只能在ransomNote中使用一次 2.采用的方法是通过一个字典cahr_countl来统计magazine字符串中每个字符出现的次数 3.然后遍历ransomNote字符串,对于其中的…

Java开发人员从了学习ArkTs笔记(三)-数据结构与线程通信全解析

大家好,我是一名热爱Java开发的开发人员。目前,我正在学习ARKTS(Advanced Java Knowledge and Technology Stack),并将不断输出我的学习笔记。我将在这里分享我学习ARKTS的过程和心得,希望能够为其他开发人…

Java基础——预定义类/自定义类封装什么是Final类型

目录 预定义类——日历输出: 自定义类——在Java文件中: 什么是封装? 什么是final类型? 修饰变量: 修饰方法: 修饰类: 预定义类——日历输出: 例如:Math类、Date类…

spi 回环

///tx 极性0 (sclk信号线空闲时为低电平) /// 相位0 (在sclk信号线第一个跳变沿进行采样) timescale 1ns / 1ps//两个从机 8d01 8d02 module top(input clk ,input rst_n,input [7:0] addr ,input …

20241114软考架构-------软考案例16答案

每日打卡题案例16答案 16.【2017年真题】 难度:简单 阅读以下关于软件架构评估的叙述,在答题纸上回答问题1和问题2.(共25分) 【说明】 某单位为了建设健全的公路桥梁养护管理档案,拟开发一套公路桥梁在线管理系统。在系统的需求分析与架构设…

低成本出租屋5G CPE解决方案:ZX7981PG/ZX7981PM WIFI6千兆高速网络

刚搬进新租的房子,没有网络,开个热点?续航不太行。随身WIFI?大多是百兆级网络。找人拉宽带?太麻烦,退租的时候也不能带着走。5G CPE倒是个不错的选择,插入SIM卡就能直接连接5G网络,千…

Python学习小记3-传递任意数量的实参

1.形参名*toppings 中的星号让Python创建一个名为toppings 的空元组,不管调用语句提供了多少实参,这个形参会将它们统统收入囊中,即:无论几个小料 def make_pizza(size, *toppings):print(f"\n要制作一个{size}-inch的披萨&…

宝塔 docker 部署onlyoffice 服务

1.宝塔安装docker,直接下载安装就行 2.docker拉取onlyoffice镜像 docker pull onlyoffice/documentserver:5.3.1.26 5.4或更高的版本已经解决了连接数限制方法的Bug 3.创建容器 docker run -d --name onlyoffice --restartalways -p 暴露端口号:80 onlyoffice/documentserv…

【数据结构副本篇】顺序表 链表OJ

🏝️专栏:【数据结构实战篇】 🌅主页:f狐o狸x 学习其实和打游戏一样,当你觉得BOSS难打的时候就说明是你的等级和装备不够,此时就需要我们多去刷刷副本,增加一点经验,顺便爆点装备出…

论文笔记(五十六)VIPose: Real-time Visual-Inertial 6D Object Pose Tracking

VIPose: Real-time Visual-Inertial 6D Object Pose Tracking 文章概括摘要I. INTRODACTIONII. 相关工作III. APPROACHA. 姿态跟踪工作流程B. VIPose网络 文章概括 引用: inproceedings{ge2021vipose,title{Vipose: Real-time visual-inertial 6d object pose tra…

AI风向标|算力与通信的完美融合,SRM6690解锁端侧AI的智能密码

当前,5G技术已经成为推动数字经济和实体经济深度融合的关键驱动力,进入5G发展的下半场,5G与AI的融合正推动诸多行业的数字化转型和创新发展,终端侧AI和端云混合式AI将广泛应用于各类消费终端和各行各业。 在推动5G和AI与各行业场…

封装一个省市区的筛选组件

筛选功能&#xff1a;只能单选&#xff08;如需多选需要添加show-checkbox多选框属性&#xff09;&#xff0c;选中省传递省的ID&#xff0c;选中市传递省、市的ID&#xff0c; 选中区传递省市区的ID 父组件&#xff1a; <el-form-item><div style"width: 240px;…