函数栈帧的创建和销毁 - 局部变量|函数传参|函数调用|函数返回|图文详解

目录

1.寄存器EBP和ESP

2.函数栈帧的创建

3.函数的调用

4. 函数栈帧的销毁


函数栈帧(function stack frame)是在函数调用期间在上分配的内存区域,用于存储函数的局部变量、参数、以及用于函数调用和返回的相关信息。每当函数被调用时,都会创建一个新的栈帧,函数执行结束后,该栈帧会被销毁。

1.寄存器EBP和ESP

寄存器是位于CPU内部的一组用于存储和处理数据的小型临时存储器。它们被设计用于执行指令、进行算术和逻辑运算、控制程序流程等任务。寄存器通常比内存访问速度更快,因为它们直接集成在CPU内部,而不需要通过外部总线进行访问。

EBP和ESP是 x86 架构下的寄存器,用于在函数调用过程中维护被调用的函数的栈帧。

EBP是扩展基址寄存器(栈底指针),通常用来指向当前函数的栈帧的基址(高地址处)。ESP是栈指针寄存器(栈顶指针),指向当前栈顶的位置(低地址处)

每当函数调用时时,都要在栈区上创建一个空间,并且将栈区的地址分别交由寄存器EBP和ESP来来维护。正在调用的是哪个函数,这两个寄存器就维护哪个函数的栈帧。

2.函数栈帧的创建

接下来通过一个简单求和函数来了解函数栈帧的创建过程

#include<stdio.h>int Add(int x, int y)
{int z = 0;z = x + y;return z;
}int main()
{int a = 2;int b = 1;int c = Add(a, b);return 0;
}

再来看这段反汇编代码:

可以看到,在进入main函数的时候有一系列的反汇编指令,它们是什么意思?干了什么事情?

下面是一个内存演示图 :在进入main函数之前,ebp和esp分别指向调用main函数的函数的栈底和栈顶。


push ebp(压栈):执行这一条语句后,将ebp的值放在esp的位置,esp维护栈顶位置,所以esp向高地址走一步(值减小)


mov ebp,esp:将esp的值给ebp 


sub esp,0E4h:esp向上低地址处移动,现在ebp与esp之间的空间就是为main函数开辟的栈帧空间


push  ebx , push esi, push sdi:把ebx,esi,edi分别压入栈


lea  edi,[ebp-24h]:ebp的值减去24(十六进制)的偏移量,然后将结果储存在edi中。这样做是为了将edi指向要填充的内存区域的起始地址

mov ecx,9:存储到ecx中。这个值表示要填充的内存区域的大小,单位为dword(Double Word 即4字节).

mov eax,0cccccccch:将0xcccccccc 存储到eax中.

rep stos dword ptr es:[edi]  :一个重复(rep)操作,它会将eax中的值(0xcccccccc)存储到edi所指向的内存地址处,存储的长度为ecx中的值(9 dword)


3.函数的调用

到这里为止,调用main函数的准备工作才算结束,接下来才刚开始执行我们写的代码:

 mov  eax,dword ptr [a]:写入数据到a的位置。这里的b其实就是ebp - 8 的位置

后面的mov都是写入数据,只是写入的位置逐渐向低地址处移动。


终于来到调用函数Add的部分,首先我们进行函数的参数传递

mov eax,dword ptr [b]:将ptr[b]放到eax里去

push eaxeax入栈

mov eax,dword ptr [b]:将ptr[a]放到eax里去

push eaxeax入栈

注意,由上面的四条指令可以看出:虽然形参的顺序是先a后b,但是实际压入栈的顺序是先b后a

call  _Add (03410B9h) :调用函数Add,其中03410B9h是函数的地址。并且把call指令的下一条指令压入栈,使Add函数执行完后知道下一条该执行的指令。


现在来到Add函数里面:

可以发现前面部分跟在调用main函数的时候是相似的,即为Add函数创建栈并初始化。

要注意的时,现在的ebp,esp已经由维护main函数的栈帧变为维护Add函数,因为此时我们已经开始创建Add的栈帧了。

mov eax,dword ptr[x]:这里其实就是找到刚刚压入Add函数的值,即ptr[x]位置的eax,值为1

add eax,dword ptr[y]:将ptr[x]位置的eax,值为2,和prt[x]相加,得到3

mov dword ptr[z],eax把3放入eax,即得到z=3

从这里可以看出,当我们真正进入函数调用两个数相加时,形参根本不是在Add中创建的,而是在Add中找到刚刚调用函数时压入的空间所存放的数据,即图中所示的空间:

所以,这样就能很明确的知道:形参是实参的一份临时拷贝 

mov  eax,dword ptr [z]:将z的值放入eax中,因为z会随着函数的结束而被销毁,要想返回一个值需要用eax这样一个寄存器来保留,因为寄存器是不会随着函数的结束而被销毁的。


4. 函数栈帧的销毁

pop edi、pop esi、pop ebx:弹出edi,,esi,,ebx,同时每次弹出时esp也向高地址处移动

mov esp,ebp:将esp指向ebp的位置

pop ebp:弹出ebp,此时ebp回到main函数中ebp原本的位置,esp由于这一次pop也向高地址处移动1偏移量,指向刚刚保存call的下一条指令的位置,准备执行下一条指令。1

add esp,8:将esp向高地址处移动两个偏移量,此时用于保存之前压入Add函数的两个形参的eax就被释放了

mov dword ptr [c],eax:把刚刚保留c的那个eax复制给c


到这里整个过程就介绍的差不多了,从中我们可以的出许多结论比如:

1.释放栈帧所占用的内存空间,是通过移动栈帧指针,从而允许后续操作直接覆盖数据来实现的

2.函数调用后还能找到下一条执行的语句是因为在调用函数之前,当前函数的上下文需要被保存到栈中,以便在函数执行完毕后能够正确返回到调用函数。

3.函数传参时是将函数调用时传递的参数复制到栈帧中的相应位置,以便函数内部能够访问这些参数。

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

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

相关文章

ros小问题之差速轮式机器人轮子不显示(rviz gazebo)

在rviz及gazebo练习差速轮式机器人时&#xff0c;很奇怪&#xff0c;只有个机器人的底板及底部的两个万向轮&#xff0c;如下图&#xff0c; 后来查看相关.xacro文件&#xff0c;里面是引用包含了轮子的xacro文件&#xff0c;只需传入不同的参数即可调用生成不同位置的轮子&…

1058:求一元二次方程

【题目描述】 利用公式 求一元二次方程axbxc0的根&#xff0c;其中a不等于0。结果要求精确到小数点后5位。 【输入】 输入一行&#xff0c;包含三个浮点数a,b,c&#xff08;它们之间以一个空格分开&#xff09;&#xff0c;分别表示方程axbxc0的系数。 【输出】 输出一行&…

航顺车规级SoC全新亮相,助推汽车智能化发展

受益于汽车电动化、智能化和网联化的推进&#xff0c;汽车车身域和座舱域MCU市场规模持续扩大。据统计&#xff0c;2021年中国车载芯片MCU市场规模达30.01亿美元&#xff0c;同比增长13.59%&#xff0c;预计2025年市场规模将达42.74亿美元。 在技术要求方面&#xff0c;对…

MyBatisPlus 之四:MP 的乐观锁和逻辑删除、分组、排序、链式的实现步骤

乐观锁 乐观锁是相对悲观锁而言的&#xff0c;乐观锁假设数据一般情况不会造成冲突&#xff0c;所以在数据进行提交更新的时候&#xff0c;才会正式对数据的冲突与否进行检测&#xff0c;如果冲突&#xff0c;则返回给用户异常信息&#xff0c;让用户决定如何去做。 乐观锁适用…

[Qt学习笔记]QT下获取Halcon图形窗口鼠标事件并执行相应操作

目录 1、背景2、参考信息3、目标4、步骤4.1 Halcon库的配置4.2 读取图像&#xff0c;并实现图像自适应窗体控件大小4.3 主要的图形绘制和贴图操作见如下代码&#xff0c;其中重点为全局函数的创建来实现选择Select、拖拽Drag和尺寸Resize事件响应。 5、总结 1、背景 在视觉项目…

3.19作业

1、思维导图 2、模拟面试题 1&#xff09;TCP通信中的三次握手和四次挥手 答&#xff1a;三次握手 客户端向服务器发送连接请求 服务器向客户端回复应答并向客户端发送连接请求 客户端回复服务端&#xff0c;并建立联系 四次挥手 进程a向进程b发送断开连接请求…

3.20作业

1、思维导图 2、 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&am…

踏“时间”与“空间”前来探寻复杂度的奥妙(Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

校园综合能效平台建设的意义

彭姝麟 Acrelpsl 一 高校用能分析 当前高校用能普遍存在以下点问题&#xff1a; 一是用能需求日益增加&#xff1a;随着高校的快速发展&#xff0c;校园用能人数、用能设备、建筑面积等逐年增加&#xff0c;用能需求也相应攀升。日益增长的能耗需求与节能降耗任务之间的客观矛…

一文读懂什么是序列 (sequence)

sequence 序列 sequence(序列)是一组有顺序的元素的集合 (严格的说&#xff0c;是对象的集合&#xff0c;但鉴于我们还没有引入“对象”概念&#xff0c;暂时说元素) 序列可以包含一个或多个元素&#xff0c;也可以没有任何元素。 我们之前所说的基本数据类型&#xff0c;都…

蓝桥杯练习03个人博客

个人博客 介绍 很多人都有自己的博客&#xff0c;在博客上面用自己的方式去书写文章&#xff0c;用来记录生活&#xff0c;分享技术等。下面是蓝桥云课的博客&#xff0c;但是上面还缺少一些样式&#xff0c;需要大家去完善。 准备 开始答题前&#xff0c;需要先打开本题的…

物业社区人行通道闸如何选择,这6点一定要考虑!

社区是居民的共同家园&#xff0c;一个安全、便捷且和谐的社区环境对于提升居民的生活质量至关重要。人行通道闸不仅仅是一道简单的进出关卡&#xff0c;它是守护社区人员通行安全的坚实屏障&#xff0c;是提升社区管理效率的智能工具&#xff0c;更是增强业主满意度的关键因素…

C# 部署ICE框架以及用例(VS2019)

使用Windows 10环境&#xff0c;VS2019进行ICE用例开发 用例结构&#xff1a;客户端和服务端 关键技术&#xff1a;集成ICE环境&#xff0c;可以创建ice文件并自动生成对应的cs文件 1.环境安装 ICE Build插件安装。安装以后&#xff0c;就可以在项目中插入ice文件 2.代码实…

放大镜效果

放大镜效果 摘要 利用css和js来实现图片放大效果 HTML <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

Go——切片

1. 特点 slice并不是数组或数组指针。它通过内部指针和相关属性引用数组片段&#xff0c;以实现变长方案。 切片&#xff1a;切片是数组的一个引用&#xff0c;因此切片是引用类型。但自身是结构体&#xff0c;值拷贝传递。切片的长度可以改变&#xff0c;因此&#xff0c;切片…

Elasticsearch实战:索引阻塞 —— 数据保护的终极武器

文章目录 1、索引阻塞的种类2、什么时候使用阻塞&#xff1f;场景1&#xff1a;进行系统维护场景。场景2&#xff1a;保护数据不被随意更改场景。场景3&#xff1a;优化资源使用的场景。场景4&#xff1a;遵守安全规则场景。 3、添加索引阻塞API4、解除设置 API5、小结6、参考 …

Transformer位置编码(Position Embedding)理解

本文主要介绍4种位置编码&#xff0c;分别是NLP发源的transformer、ViT、Sw-Transformer、MAE的Position Embedding 一、NLP transformer 使用的是1d的绝对位置编码&#xff0c;使用sincos将每个token编码为一个向量【硬编码】 Attention Is All You Need 在语言中&#xff0…

RPG Maker MV 踩坑八 仿新仙剑战斗物品指令菜单

仿新仙剑战斗物品指令菜单 遇到的坑坑一坑二解决方法 遇到的坑 上次做的额外战斗指令菜单和物品战斗指令菜单&#xff0c;突然发现一个大问题&#xff0c;漏风了&#xff01;&#xff01;&#xff01; 其实就是将底部漏出来了&#xff0c;这样整个UI就不完整了&#xff0c;算是…

微服务day04(上)-- RabbitMQ学习与入门

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;但…

深度学习 | 神经网络

一、神经网络原理 1、神经元模型 虽然叫个神经元&#xff0c;但骨子里还是线性模型。 2、神经网络结构 顾名思义就是由很多个神经元结点前后相连组成的一个网络。虽然长相上是个网络&#xff0c;但是本质上是多个线性模型的模块化组合。 在早期也被称为 多层感知机 Multi-Layer…