探究栈帧的奥妙

news2024/11/20 11:30:49

目录

探究栈帧的奥妙

引言

浅浅说一下栈

问问自己几个问题

什么是栈帧

栈帧的维护

汇编预备知识

小例子

访问栈帧里的数据

例子

栈帧是如何切换的

栈帧是如何处理参数和返回值的


探究栈帧的奥妙

作者申明:

文中有些名词可能不太官方,大部分是作者自己的理解,只是为了方便理解,所以用了一些不太专业的词汇,如果有错误,欢迎各位佬指正!

引言

本文我们要讲解的是栈帧,为了较好的引入它,本文使用的C语言函数作为载体,默认看文章的大家C语言函数的基本使用都没有问题啊,如何检测自己的C语言有没有问题呢?可以看看下面的代码,如何还行的话,那表示这篇文章对你是大有帮助的(只要不是太小白都可以的)。注意:需要读者知道内存分配栈区的概念!这很重要

#include <stdio.h>
​
int Add(int x, int y)
{
    int sum = x + y;
    return sum;
}
​
int main()
{
    int a = 10;
    int b = 20;
    int sum = Add(a, b);
    printf("sum=%d\n", sum);
    
    return 0;
}

十分简单的一段程序对吧,OK,那么现在就以这一小段函数为例来讲解一下栈帧

浅浅说一下栈

使用的内存是有分区的:

  • OS区

  • 栈区

  • 堆区

  • 全局区

  • 共享区

  • 代码区

  • 数据区

针对本文,只需了解栈区即可,我们分配的空间是有地址的,地址是有大小的,而栈区的特点是从高地址向低地址开始分配内存,即对于栈区来说,高地址是栈底,低地址是栈顶

堆栈相对而生,箭头是资源申请的方向

如图

问问自己几个问题

  • 函数是如何调用的

  • 参数是如何传入的

  • 函数是如何返回的

  • 函数返回后是怎么找到之前调用的地方的

如何你能回答上来,那么你的高度可能在这篇文之上,回答不上来,相信看了这篇文章就可以回答上来了,哈哈哈

什么是栈帧

在我们进行函数调用的时候,编译器都会在栈区为这个函数维护一个栈帧,即每一个函数对应着一个栈帧,这是概念,那么我们通俗的来讲讲什么事栈帧。首先明确一点,我们在进行变量创建的时候,编译器是给这个变量分配了对应的虚拟内存的,即创建变量时,需要一定的开销,而这个开销一部分就是体现在内存占用上,那么回到函数调用这里来,和创建变量类似,函数也是一个类型,在进行调用的时候同样也需要一定的内存开销,这个函数占用的内存空间就是这个函数的栈帧,即栈帧=占用内存。

栈帧的维护

介绍了什么是栈帧,系统是如何来得知这个函数的栈帧大小和所在栈区的位置呢,系统使用了两个寄存器来维护栈帧的范围:

  • EBP(extended base pointer) 基址指针寄存器,存放当前栈帧的底部地址

  • ESP(extended stack pointer) 栈指针寄存器,存放当前栈帧的顶部地址

注意:这两个寄存器的内容是动态变化的,同一时刻只会调用一个函数,即同一时刻只会一一个栈帧,用上面的例子来看,最开始是调用的main函数,此时ebp和esp里面存放的就是main函数的栈帧,之后调用了Add函数,这时ebp和esp里面存放的是Add函数的栈帧,Add返回main后,esp和esp又重新开始维护main函数的栈帧。

这里有几个细节,栈帧是如何创建的,ebp和esp在main和Add之间切换栈帧的时候,如何切换的,ebp和esp又是如何再一次的维护main栈帧的,这些都是值得探讨的问题。

汇编预备知识

  • mov:eax, ebx 将ebx的值赋值给eax

  • push:xxx 将xxx压入栈,esp-4

  • pop:xxx 将栈顶元素出栈,写入xxx,再让esp+4

  • call:函数名 将IP旧值压栈保存(栈顶低地址处),设置IP新值,新函数的指令执行地址

  • ret:从函数的栈帧顶部找到IP旧值,将其出栈并恢复IP寄存器

补充:IP寄存器存放的是程序下一次要执行的指令的地址

小例子

push eax:#将寄存器eax的值压栈
push 985:#将立即数985压栈
push [ebp+8]:#将主存地址[ebp+8]里的数据压栈
    
pop eax:#栈顶元素出栈,写入寄存器eax
pop [ebp+8]:#栈顶元素出栈,写入主存地址[ebp+8]

访问栈帧里的数据

我们知道esp&ebp分别指向栈顶和栈底,那么我们可以直接通过mov指令来访问栈帧里面的数据,只需有esp和ebp分别+/-就可以获得栈帧中的地址

例子

sub esp,12  #栈顶指针-12
mov [esp+8],eax #将eax的值复制到主存[esp+8]

栈帧是如何切换的

这里要探讨的问题是,栈帧是如何切换的,也就是如何从main函数突然就执行Add函数的

main:
push ebp
mov ebp,esp
...... #省略不重要的部分
call Add #将当前IP值压栈,重新设置IP值
......
​
Add:
push ebp     #把ebp的值压栈到栈顶
mov ebp,esp  #将esp的值复制给ebp  这两个指令等价于enter指令
......
leave        #等价于 mov esp, ebp \ pop ebp
ret
int add(int x, int y)
{
    return x + y;
}

int main()
{
    int x = 10;
    int y = 20;

    add(x, y);

    return 0;
}

当执行add(x, y)时,底层汇编翻译的指令是

call add

当add即将返回时,底层汇编翻译的指令是

leave

ret

上面main和add的栈帧切换,当执行call add的时候,会先将当前的IP寄存器的值压入栈帧,然后再设置IP的值,使其下一次执行的指令跳到add函数栈帧中,再将main函数栈帧的ebp寄存器值压入栈帧,再将esp的值复制给ebp,再依次执行add函数体中指令,就完成了栈帧切换。

add函数执行完后,会执行leave指令将ebp的值复制给esp,然后在Pop ebp,即将栈顶元素出栈,再将其出栈的内容复制给ebp,而这里的内容刚好是main函数栈帧的基地址,然后再执行ret指令将IP的值恢复到原来的值,这样就完成了栈帧的切换。

栈帧是如何处理参数和返回值的

返回值处理,一般返回值只有一个,所以处理的时候,一般是用一个通用寄存器(eax)来临时记录一下值,然后再复值给需要的变量。

将栈帧划分为几个区域,分别负责存放函数中的局部变量,函数体的指令,函数的参数

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

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

相关文章

UEditor配置后端上传图片

&#x1f525;博客主页&#xff1a; 破浪前进 &#x1f516;系列专栏&#xff1a; Vue、React、PHP ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 后端框架&#xff1a;Fastadmin 目录结构&#xff1a; 代码&#xff1a; {"imageActionName": "uploadimage&q…

样式迁移 - Style Transfer

所谓风格迁移&#xff0c;其实就是提供一幅画(Reference style image)&#xff0c;将任意一张照片转化成这个风格&#xff0c;并尽量保留原照的内容(Content)。 将样式图片中的样式迁移到内容图片上&#xff0c;得到合成图片。 基于CNN的样式迁移 奠基性工作&#xff1a; 首先…

优先队列PriorityQueue

前言 PriorityQueue这个队列不知道大家使用过吗&#xff0c;反正我用的很少&#xff0c;主要对它不是很了解&#xff0c;今天我带领大家剖析下PriorityQueue这个优先级队列。 PriorityQueue介绍 顾名思义&#xff0c;PriorityQueue是优先队列的意思。优先队列的作用是能保证每…

基于SpringBoot的疫苗发布和接种预约系统

目录 前言 一、技术栈 二、系统功能介绍 管理员功能实现 疫苗信息管理 医院信息管理 医生管理 医生功能实现 预约接种管理 疫苗信息查看 医院信息查看 用户功能实现 在线论坛 疫苗信息 医院信息 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 如…

Java高并发应对策略:探索解决秒杀问题的几种成功方案

01 什么是高并发&#xff1f; 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一&#xff0c;它通常是指&#xff0c;通过设计保证系统能够同时并行处理很多请求。高并发相关常用的一些指标有响应时间(Response Time)&#xff0c;吞吐量(Throughput)&a…

上下相机对位,上下贴合,上下相机映射对位场景案例

场景描述 适用场景&#xff1a;上下相机映射对位场景&#xff0c;机械手在固定上料位置取料&#xff0c;然后放置到料盘内/贴合 到目标位置&#xff1b;当上料与料盘位置都会出现偏差时可采用上下相机映射对位。 案例场景目标&#xff1a; 位置目标&#xff1a;将图 1 中物料的…

Linux 基本语句_9_C语言_生产者消费者

完整版生产者代码&#xff1a; #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <sys/file.h> #include <string.h>#define MAXLE…

钢琴培训答题服务预约小程序的效果怎样

很多家长都会从小培养孩子的兴趣&#xff0c;钢琴便是其中热度较高的一种&#xff0c;而各城市也不乏线下教育培训机构&#xff0c;除了青少年也有成年人参加培训&#xff0c;市场教育高需求下&#xff0c;需要商家不断拓展客户和转化。 那么通过【雨科】平台制作钢琴培训服务…

机器狗装上 ChatGPT 大脑当导游;AI 正在学习「超人的说服力」丨 RTE 开发者日报 Vol.73

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

C++进阶语法——智能指针【学习笔记(五)】

文章目录 1、智能指针简介1.1 原始指针&#xff08;raw pointer&#xff09;的⼀些问题1.2 智能指针&#xff08;smart pointers&#xff09; 2、智能指针&#xff08;smart pointers&#xff09;——unique_ptr2.1 unique_ptr 的声明2.2 unique_ptr 的函数2.3 ⾃定义类型使⽤ …

需要下微信视频号视频的小伙伴们看过来~

随着视频号的热度越来越大&#xff0c;下载视频号视频的需求也开始增加啦&#xff0c;今天给大家给分享几个简单实用的下载方法&#xff0c;总有一个你能用上的&#xff01; 一、犀牛视频下载 犀牛视频下载器可以直接解析并下载视频号短视频。您只需转发视频到机器人即可下载。…

中科驭数受邀亮相两场重要行业盛会,摘得2023“璀璨技术奖”奖项

近日&#xff0c;中科驭数作为DPU算力基础设施领军企业&#xff0c;受邀参与2023信息技术应用创新专题研讨会暨第二届集成电路产业发展创新大会、以及2023AI网络创新大会。在两大行业盛会上&#xff0c;中科驭数与行业知名专家和企业代表齐聚一堂&#xff0c;分享了DPU在集成电…

蓝凌EIS智慧协同平台saveImg接口存在任意文件上传漏洞

蓝凌EIS智慧协同平台saveImg接口存在任意文件上传漏洞 一、蓝凌EIS简介二、漏洞描述三、影响版本四、fofa查询语句五、漏洞复现六、深度复现1、发送如花2、哥斯拉直连 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者…

拿下国家级信创认证 中科驭数KPU SWIFT-2200N成为国内首款满足金融业严苛要求的DPU产品

近日&#xff0c;中科驭数KPU SWIFT-2200N低时延DPU卡&#xff0c;在中国人民银行旗下金融信创生态实验室完成测试并取得测试报告&#xff0c;这意味着中科驭数低时延网络代表性产品的应用领域从证券进一步拓展到了银行业&#xff0c;成为国内首款满足金融行业严苛要求的DPU产品…

vue2+antd——实现动态菜单路由功能——基础积累

vue2antd——实现动态菜单路由功能——基础积累 实现的需求&#xff1a;效果图&#xff1a;登录接口处添加以下代码loadRoutes方法内容如下&#xff1a; 最近在写后台管理系统&#xff0c;遇到一个需求就是要将之前的静态路由改为动态路由&#xff0c;使用的后台框架是&#xf…

#智能小车项目(六)麦克纳姆轮x型运动学分析

麦伦介绍 瑞典麦克那姆公司发明的一种全方位移动轮式结构&#xff0c;由基于主体轮辋和一组均匀排布在轮毂周围的回转辊子组成且辊子轴线与轮毂轴线呈一定角度(一般为 45)&#xff0c;小辊子的母线是等速螺旋线或椭圆弧近似而成&#xff0c;当轮子绕着轮毂轴线转动时&#xff…

css画一条虚线,用到background-image:linear-gradient线性渐变的属性

CSS实现虚线的方法_css 虚线_saltlike的博客-CSDN博客 渐变属性(background-image)全解析_background-image linear_大聪明码农徐的博客-CSDN博客 Background:linear-gradient()详解_background: linear-gradient_小白白中之白的博客-CSDN博客 注意&#xff1a; 必须要写高…

QMI8658A_QMC5883L(9轴)-EVB 评估板

1. 描述 QMI8658A_QMC5883L(9轴)-EVB 评估板是一款功能强大的9轴IMU传感器&#xff0c;它利用了QMA8658A 内置的3轴加速度计和3轴陀螺仪&#xff0c;同时结合QMC5883L的3轴地磁数据&#xff0c;来测量物体在三维空间中的角速度和加速度&#xff08;严格意义上的IMU只为用户提供…

在MDP环境下训练强化学习智能体

目录 1.创建MDP环境 2.创建Q-learning智能体 3. 训练Q-learning智能体 4.验证Q-learning结果 本文示例展示了如何训练Q-learning智能体来解决一般的马尔可夫决策过程(MDP)环境。有关这些智能体的更多信息&#xff0c;请参阅Q-Learning智能体。 MDP环境如下图&#xff1a; …