函数调用的机器级表示

文章目录

  • 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.mfbz.cn/a/32835.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins 发送文件到远程服务器:Publish Over SSH 插件

Jenkins 发送文件到远程服务器:Publish Over SSH 插件 文章目录 Jenkins 发送文件到远程服务器:Publish Over SSH 插件一、Publish Over SSH 插件1、概述2、主要功能和特点3、插件主页4、安装 Publish Over SSH 插件5、配置远程主机 二、发送文件到远程主…

windows安装python开发工具pycharm

下载地址 PyCharm: the Python IDE for Professional Developers by JetBrains 点击下载 安装 双击exe安装等待安装完成即可 设置python环境 添加本地python环境 选择python.exe 所在路径即可,2.x版本和3.x版本都可,根据需要进行调整

【Spring】——Spring生命周期

前言 ❤️❤️❤️Spring专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️ Spring_冷兮雪的博客-CSDN博客 前面我们讲完了Spring中有关Bean的读和取,我们还没有好好去了解了解Bean对象,这篇 …

基于appnium+python+夜神模拟器的自动化

目录 1、安装夜神模拟器 2、定位元素 3、开始编码 首先搭好appnium环境!参考https://www.cnblogs.com/testlearn/p/11419797.html 1、安装夜神模拟器 下载安装夜神模拟器后,在cmd命令输入adb connect 127.0.0.1:62001,显示出设备则表示…

redis协议与异步方式学习笔记

目录 1 交互方式 pipline2 广播机制2.1 概念演示2.2 使用场景 3 redis事物3.1 概念3.2 使用场景3.3 解决的问题3.3.1 背景:多线程竞争出现问题3.3.2 事务3.3.3 安全性事务 3.4两种类型的“事务”3.4.1 watch ... multi exec3.4.2 lua 脚本实现“原子”执行&#xff…

再以汇编代码分析c++的右值引用

汇编分析c语言的执行结果最为准确。 可见,右值引用其实还是引用, bb 和 cc 都是对 aa 的引用,其内存里存储了 aa 的地址。 而且还有一个很奇特的现象,bb无法给cc赋值,右值引用无法给右值赋值。 同样是调用std:: move…

d2l_第七章学习_卷积神经网络

参考: d2l今日学习——卷积神经网络(CNN)https://blog.csdn.net/m0_61165991/article/details/124176077图像工程(上册)-图像处理傅里叶变换https://blog.csdn.net/qq_43369406/article/details/131350139CNN卷积神经网络基础知识…

STC15 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043

STC15 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043 Proteus仿真小实验: STM32 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043 功能: Protues版本:8.9 硬件组成:STC15W4K32S4单片机 LCD1602显示器DHT11…

基于深度学习的高精度推土机检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度推土机检测识别系统可用于日常生活中检测与定位推土机目标,利用深度学习算法可实现图片、视频、摄像头等方式的推土机目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训…

2023 node 接入腾讯云短信服务,实现发送短信功能

1、在 腾讯云开通短信服务,并申请签名和正文模板 腾讯云短信 https://console.cloud.tencent.com/smsv2 a、签名即是短信的开头。例如 【腾讯云短信】xxxxxxx; b、正文模板即短信内容, 变量部分使用{1}, 数字从1开始累推。例如&a…

深度学习-第T10周——数据增强

深度学习-第T10周——数据增强 深度学习-第T10周——数据增强一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、数…

软件工程实践总结

前言 这次我们学校花了很多心血在这次的课设上,真的是特别感动和感谢,当你遇到真心为你好对你好的老师的时候,真的是会觉得人间值得! 之前在学软件工程的时候我就会觉得这些理论的东西有什么用啊,什么UML,…

Scrapy框架之下载中间件(详解)

目录 Scrapy中下载中间件 概念 方法 process_request(self, request, spider) 参数: process_response(self, request, response, spider) 参数 基本步骤 示例代码 注意 Scrapy 中 Downloader 设置UA 开发UserAgent下载中间件 代码 三方模块 配置模块到Settin…

【js30天挑战】第四天:数组操作

总结 filter(筛选条件为true的项) map(你想要输出的东西),进来多少个 出去多少个 sort(),默认可排字母顺序。sort(compareFn(a, b))其中compareFn(a, b)返回的值若大于0则a在b的后面。 reduce(),最复杂。reduce(func(){上一轮计算出的结果…

Flink-SQL 写入PostgreSQL 问题汇总

​ 1.主键字段为空问题 错误信息 org.apache.flink.table.api.TableException: Column bus_no is NOT NULL, however, a null value is being written into it. You can set job configuration table.exec.sink.not-null-enforcerDROP to suppress this exception and drop …

罗技k380键盘教程

在智能手机和平板电脑上享受台式电脑般舒适便捷的输入体验。罗技蓝牙™ 多设备键盘 K380 是一款小巧独特的键盘,让您在家中任何地方都能使用个人设备进行沟通和创作。 借助便捷的易于切换™ 按钮,可以通过蓝牙™ 无线技术同时连接最多三台设备&#xff…

【实用技巧】使用USB数据线向亚马逊kindle导入电子书

一、内容简介 本文主要介绍如何使用USB数据线向亚马逊kindle阅读器导入电子书。 二、所需原料 笔记本电脑、Kindle阅读器、Kindle适配的USB-a数据线。 三、导入方法 1、使用USB-a数据线将Kindle阅读器与电脑连接。 2、找到Kindle文件夹-documents-Downloads-Items1目录。…

Django框架实现简单的接口开发

前提创建一个Django项目&#xff0c;目录如下&#xff1a; Django框架上进行GET请求接口开发示例: 1.在上面项目结构目录Template下&#xff0c;新建一个login.html页面&#xff0c;定义表单提交请求的方式为post&#xff0c;具体代码如下。 <!DOCTYPE HTML> <html …

freemarker 使用word模板赋值

1. 引包<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency>word文档工具类import freemarker.template.Configuration; import freemarker.template.…

快来看看Java在编程语言中的优势与特性吧

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 其他专栏&#xff1a;《系统解析C语言》《C语言》《C语言-语法篇》 内容分享&#xff1a…