函数调用的机器级表示

news2024/12/23 17:28:23

文章目录

  • 1.Call和ret指令
  • 2. 如何访问栈帧里面的数据
    • 为什么栈底放在上面,栈顶放在下面
    • X86中的寄存器
    • EBP、ESP寄存器
    • push 、pop 指令
    • mov 指令
    • 总结如何访问栈帧
  • 3. 如何切换栈帧
    • 函数调用时
    • 函数返回时
  • 4. 完整的函数调用过程
    • 1. 一个函数的栈帧内包含哪些内容
    • 2. 汇编代码实战
    • 3. 内容拓展
  • 5. 大总结

1.Call和ret指令

在这里插入图片描述

除了main函数外,在栈底还会保存一些和硬件以及系统相关的其他的一些信息
调用函数的时候就压栈,
函数执行完成,return的时候就出栈
当前执行的函数永远都是在栈顶的位置!

在这里插入图片描述

如何保证函数调用的时候能够过得去,还能回得来呢?

当CPU正在执行Call指令的时候,
IP寄存器应该是指向下一条mov指令
那么执行call指令的第一个作用就是把当前IP寄存器的值【mov指令的地址】给他压栈保存,把他压到栈顶的位置。
接下来会让IP寄存器指向新的位置【add函数的第一条指令】,同时add函数压栈
执行完add函数之后【return之前的指令】,add函数就会出栈,
接下来CPU执行add函数的return指令。
return指令的作用就是从函数函数栈中的顶部找到IP旧值,并且把他写到IP寄存器当中,这样的话,IP寄存器的值就会回到call指令的后一条指令

2. 如何访问栈帧里面的数据

在这里插入图片描述

为什么栈底放在上面,栈顶放在下面

对应一个32的操作系统来说,系统会为每一个进程分配4GB的虚拟地址空间,也就是虚拟内存,地址的范围从0x0000 0000~0xFFFF FFFF,一共4GB,
高地址的1GB是操作系统的内核区
低地址的3GB可以由用户进程使用
那我们之前提到的函数调用栈的栈底在0xC000 0000这个位置,而栈顶是在地址变小的这个方向,
因此大多数情况下,会把栈底画在上面(高地址),栈顶画在下面(低地址)

在这3GB的用户区当中,除了用户栈(又名函数调用栈)之外,还会被划分成其他的区域,用于存储不同的数据

X86中的寄存器

在这里插入图片描述
在X86的CPU里面,有这样一些常见的寄存器
其中EBP和ESP和我们的函数调用栈息息相关
注意在一个CPU内部,只有一个EBP和一个ESP

EBP、ESP寄存器

在这里插入图片描述

push 、pop 指令

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

mov 指令

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结如何访问栈帧

在这里插入图片描述

3. 如何切换栈帧

在这里插入图片描述

CPU内有有EBP和ESP两个寄存器
这两个寄存器标记了当前正在执行的函数他的栈帧的范围
当发生函数调用的时候,需要修改EBP和ESP的值
让他们指向新的被调用函数的底部和顶部
而且当被调用的函数执行完毕之后,
我们还需要把EBP和ESP重新让他指回上一层函数的栈帧

函数调用时

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

当CPU执行call这条指令的时候
IP寄存器应该指向下一条指令【mov】,
这时候需要push IP,把IP的值压入栈顶,也就是保存外层函数的下一条应该执行指令的地址。
同时,IP指向add函数的第一条指令
发现,add函数的第一条指令是push ebp,此时的EBP指向的还是上一层函数的栈底,这条指令会把上一层函数的栈底压栈。方便之后返回的时候重新指向上层函数的栈底
add函数的第二条指令是mov ebp,esp。意思是把ESP栈顶的值复制到EBP当中,换句话说就是让EBP指向当前这个函数【add函数】的基地址【0XA00F 0010】
我们发现每一个函数的栈帧,他的底部一定是存储了它上一层函数的基地址【add函数他的栈帧底部存储了caller函数的基地址0xA00F 0030】
这样做的好处就是,当一层函数执行完毕,要返回到上一层函数的之前,我们总能在当前函数的栈帧底部找到上一层函数的基地址,这样我们就可以恢复EBP寄存器的值。


接下来我们可以给这个新的函数栈帧进行一系列逻辑操作

函数返回时

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

  1. 把EBP的值复制一份给ESP。换句话说就是让ESP和EBP都指向当前栈帧的底部
  2. pop ebp,把当前ESP所指的栈顶元素出栈,写入EBP中,也就是让EBP的值重新指回了栈帧底部0xA00F 0030这个位置。同时ESP+4,指向0xA00F 0014这个位置

return指令,让程序的执行流回到Call指令的后面这条指令,继续往后执行

4. 完整的函数调用过程

1. 一个函数的栈帧内包含哪些内容

在这里插入图片描述在这里插入图片描述

2. 汇编代码实战

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在调用含参的方法之前,要把外层函数的两个参数放入外层函数栈帧的顶部位置

注意:mov指令不支持两个操作数都来自主存,所以要把temp2的值传到距离栈顶的倒数第二个位置,必须先把temp2放入当一个寄存器,再从寄存器中将数据写入到esp+4

在这里插入图片描述

执行call add函数,IP指向下一条指令【mov】,这时先将IP的值压入栈中,然后IP指向add函数的第一条指令。

在这里插入图片描述
在这里插入图片描述add函数中如何访问到上层函数的两个参数?

caller函数中,已经把两个参数值存入到靠近栈顶的两个位置,访问这两个参数只需要用【ebp+8】访问第一个参数,【ebp+12】访问第二个参数

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

caller函数给上一层函数返回值的时候,把这个返回值写入到eax寄存器中,这样,上一层函数只需要从eax寄存器中取这个值就可以获得函数的返回结果了。

在这里插入图片描述

假设在发生函数调用的时候,这个调用者他有一些运算结果被存在了一些寄存器当中,比如edx、ecx、eax。那么当函数调用发生的时候,被调用者也有可能使用到这几个寄存器,那就有可能吧调用者的这几个中间结果给覆盖掉,就有可能导致数据的丢失。那如何解决这个问题呢?

办法:如果有必要的话,在发起函数调用之前,我把我需要的这些寄存器值压栈保存,在函数调用返回之后,再把这些寄存器值从栈恢复到寄存器,这样就可以保证寄存器中的数据不会丢失

3. 内容拓展

在这里插入图片描述
在这里插入图片描述

5. 大总结

在这里插入图片描述

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

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

相关文章

配置数据库

🌳🌳🌳前言:下载数据库,安装配置数据库,连接Navicat 又又又重新配置数据库害。 目录 一、下载数据库 二、安装 三、解决3306端口占用 四、验证 五、连接Navicat 一、下载数据库 官方链接:M…

Glibc——堆利用机制[拓展]

目录 1、什么是堆 2、使用动态分配的内存 3、系统调用brk和mmap 3.1 brk() 3.2 mmap() 4、多线程与Arena 5、维护多个堆 1、什么是堆 堆是每个程序被分配到的一块内存区域,和栈的区别主要在于堆内存是动态分配的。也就是说,程序可以从“heap“段请…

LPC1114 - AD采集

一、基础知识 1.1位操作 对寄存器的bit5写0&#xff1a; 寄存器&~&#xff08;1<<5&#xff09;&#xff1b; 现在运用你的C语言知识分析一下&#xff0c;把十进制的1写成二进制32位数就是&#xff1a; 00000000000000000000000000000001 &#xff08;1<<5&…

微服务下如何选择OAuth2授权之四种模式

OAuth2.0是一个授权框架&#xff0c;他规定了客户从授权服务器获取令牌Token的规则。 一、OAuth2的组成部分 1.OAuth2.0需要解决的问题 要理解OAuth2.0&#xff0c;先要知道为什么会有这个东西产生&#xff0c;或者说他能帮我们解决什么问题&#xff0c;其实简单说他就是帮我…

【解决】跨设备访问Ubuntu接口文档,请求超时,ping不通问题

文章目录 一、问题描述二、系统环境三、问题原理说明1. 常见问题原因2. 说说IP 地址和子网掩码不匹配问题 四、有风险的解决方法1. 一般的解决方法&#xff1a;2. 我们的解决方法&#xff1a;第一&#xff1a;第二&#xff1a; 选择网络适配器第三&#xff1a;桥接模式第四&…

js常用的一些技巧【一行】

前言 总结一些常用的&#xff0c;但是一时可能想不起来的一些js小技巧&#xff0c;方便CV 数组 生成数组 当你需要要生成一个0-99的数组 方案1 const createArr (n) > Array.from(new Array(n), (v, i) > i) const arr createArr(100) // 0 - 99 数组方案2 const c…

相同性能和体积的磁体,吸力是一样的吗?

很多小伙伴可能都会有这样一个疑问&#xff0c;相同性能和体积的磁体&#xff0c;它们的吸力一样吗&#xff1f;网上有说钕铁硼磁铁的吸力是自身重量的640倍&#xff0c;这可信吗&#xff1f; 这个问题其实可以发散开&#xff0c;那就是磁铁的吸力与哪些因素有关。首先需要明确…

【已解决】qt4安装包下载含下载链接(完全版)

总所周知&#xff0c;c qt4.8是一个稳定版本&#xff0c;而qt4.8去网上找的我好辛苦&#xff0c;而且官网时而挂机一样&#xff0c;网站崩溃一样&#xff0c;即使找到了&#xff0c;它们也会让你下载qt4.8版本&#xff0c;而那些&#xff0c;比如这里就会显得手足无措。 问题…

爱创科技闪“药”亮相第62届全国制药机械博览会!

2023年5月28日-30日&#xff0c;第62届&#xff08;2023年春季&#xff09;全国制药机械博览会暨2023中国国际制药机械博览会在青岛国际世界博览城完美收官。全国药机展是业界公认的专业化、国际化、规模大、展品全、观众多&#xff0c;集贸易、研讨于一体的制药装备行业交流平…

FPGA实战开发-基于的ddr图像缓存设计(上)

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 本文主要基于DDR的图像缓存设计 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 先用图像产生模块产生一个1080P60Hz的测试图像&#xff0c;然…

内网程序配置外网访问方案

该方案可解决客户公司没有固定IP&#xff0c;内网IIS程序配置外网访问。如果有固定IP&#xff0c;可以直接在公司主路由器上映射端口即可。 一、申请一个公司域名和云服务器 二、在申请的公司一级域名下&#xff0c;解析一个二级域名&#xff0c;使用泛域名方式&#xff0c;解…

Mysql版本升级教程【5.x到8.x】

目录 0.查看当前版本1.备份导出原数据2.停止Mysql服务3.卸载Mysql相关组件4.删除Mysql安装目录5.删除Mysql数据目录6.官网下载新版安装包7.安装新版Mysql8.配置环境变量 0.查看当前版本 1.备份导出原数据 可以在Navicat里将相关数据库存到.sql文件中&#xff0c;到时候直接导入…

阿里面试太为难我了,阿里面试了7轮(拿下P7岗offer)

前言 今年的大环境非常差&#xff0c;互联网企业裁员的现象比往年更严重了&#xff0c;可今年刚好是我的第一个“五年计划”截止的时间点&#xff0c;说什么也不能够耽搁了&#xff0c;所以早早准备的跳槽也在疫情好转之后开始进行了。但是&#xff0c;不得不说&#xff0c;这…

准备跳槽的兄弟可以看看...

八股文为什么这么火爆&#xff1f; 因为只要大家技术和能力过关&#xff0c;八股文能帮助大家在面试时有很好的表现和稳定的发挥&#xff0c;让面试官预估到你能带来的价值&#xff0c;从而实现薪资高涨幅。 总结了一些小伙伴的面试经验&#xff0c;和我自己多年的资料库存&a…

Zabbix“专家坐诊”第194期问答汇总

问题一 Q&#xff1a;请问一下&#xff0c;我这个监控上了光交和V7000通过trap&#xff0c;mib文件也上传了&#xff0c;usr/snmp/mibs/V7000目录&#xff0c;是创建的监控项调用此文件夹下的mib文件&#xff0c;还是自动找呢&#xff1f; A&#xff1a;mib文件只用于mib内容…

深度学习架构-Tensorflow

深度学习基本概念 人工智能是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的目的 就是让计算机能够像人一样思考。 强人工智能&#xff1a;就是要使机器学习人的理解、学习和执行任务的能力。 弱人工智能&#xff1a;指用…

计算机网络安全的主要内容是什么?CISP题库分享

在技术上&#xff0c;网络安全包括物理安全、运行安全、信息安全和安全保证四个方面: 物理安全 包括环境安全、设备安全和记录介质安全。环境安全涉及中心机房和通信线路的安全保护问题&#xff1b;设备安全涉及设备的防盗和防毁、设备的安全使用等问题&#xff1b;记录介质安…

linux-docker备份数据库

利用计划任务和批处理从docker容器中备份数据库文件到宿主机指定目录 如何创建定时任务 创建计划任务&#xff08;定时任务&#xff09;&#xff1a; crontab -e打开后是VI编辑器&#xff0c;将自己计划任务的内容写到里边然后wq&#xff08;保存并退出&#xff09;就行了 查…

当涉及到嵌入式开发时

以下是一些建议和关键要点&#xff0c;可以帮助您进行有效的开发&#xff1a; 硬件选择&#xff1a;根据项目需求选择合适的硬件平台和组件&#xff0c;包括处理器、存储器、传感器和通信接口等。考虑功耗、性能、可靠性和成本等因素。 软件开发环境&#xff1a;选择适合嵌入式…

3.1 增加多进程执行playwright

增加了多进程的方式执行测试代码&#xff0c;对代码改动比较大 1、case case目录依然是自动生成 2、config dir_collection.py新增了配置 mkdir_collections [case,log,img, ] del_collections [results,report ] del_regex temp3、data/img/log/resource/video data/im…