从汇编看函数调用
文章目录
- 函数调用流程
- 栈相关寄存器及的作用简介
- 寄存器功能
- 指令功能
- 栈
- 函数的括号{}
- 正括号
- 反括号
- 参数传递
- 传值,变量不可改
- 传指针,变量可改
- C++ 传引用
- 函数调用实例
函数调用流程
目标:函数调用前后栈保持不变

- 保存main函数的寄存器上下文
- 移动栈指针,到新栈
- 调用新函数:新函数会开辟内存然后操作
- 恢复栈指针
栈相关寄存器及的作用简介
寄存器功能
ESP/RSP:堆栈指针寄存器,指向栈顶。栈顶指针
EBP/RBP:栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量
rax:通常用于存储函数调用返回值
rdi:第一个入参
rsi:第二个入参
rdx:第三个入参
rcx:第四个入参
r8:第五个入参
r9:第六个入参
寄存器ebp作为当前函数的“栈帧”基地址,配合一定的偏移,就可以读、写函数体的临时变量。如果一个变量是通过ebp寄存器间接访问的,那么它往往是临时变量,也叫“栈”变量。
指令功能


push rbp 保存上下文,保存rbp值
1.rbp里面的值放到当前rsp指向的位置,保存当前栈底指针的值
2. 然后rsp–,栈顶指针向上移动
pop eax 恢复栈帧
1. 栈顶指针向下移动,这里的值保存的是原函数的栈底位置
2. ebp指向esp里面值的位置,移动栈底指针到原函数位置

call
1. 会把call指令的下一条指令压入栈,把下一条指令的地址,也就是函数func的返回地址(0x401105e)压入堆栈
2.CPU跳转到函数func的首地址。


栈
栈是存储临时数据的区域,在普通内存中,它的特点是通过push指令和pop指令进行数据的存储和读出。往栈中存储数据称为“入栈”,从栈中读出数据称为“出栈”。32位x86系列的CPU中,进行1次push或pop,即可处理32位(4字节)的数据。push指令和pop指令中只有一个操作数。该操作数表示的是“push的是什么及pop的是什么”,而不需要指定“对哪一个地址编号的内存进行push或pop”。
这是因为,对栈进行读写的内存地址是由esp寄存器(栈指针)进行管理的。push指令和pop指令运行后,esp寄存器的值会自动进行更新(push指令是-4, pop命令是+4),因而程序员就没有必要指定内存地址了。
栈是由大地址向小地址递减,而堆和普通内存是小地址到大地址递增
操作系统会为每个任务(进程或线程)分配一段内存当作任务“堆栈”;CPU则提供两个寄存器esp、ebp,用来标识当前函数对“堆栈”的使用情况。随着函数的逐层调用,函数的“栈帧”会逐次堆叠,互不重合;随着函数的逐层返回,函数的“栈帧”会被就地放弃,但不会清理内存
函数的括号{}
其实函数的调用主要部分就是正反括号的内容。
正负括号都对应两条指令。

正括号
先看正括号,三条指令,作用是保存原栈,并分配新的栈空间
- push rbp : push指令把寄存器ebp的值压入“栈顶”,然后将“栈顶”红色水位线(CPU寄存器esp)上移,扩大栈空间。至此,main函数的“栈帧”保护工作完成!
- 然后通过mov指令,更新一下“栈帧”基准线,让ebp指向esp,这里就是新的func的栈了

反括号
然后看反括号两条指令:反括号作用是恢复栈
- pop, 把事先压入“栈顶”的ebp值返还给CPU寄存器ebp。这样蓝色基准线就恢复到了最开始的位置。然后esp红色水位线也随之下降。esp和ebp的值就都恢复了。
- ret指令,把“栈顶”处的返回值传给CPU寄存器rip,这样,CPU就可以跳转到主调函数main被打断的地方0x401105e继续执行了。
参数传递
先看下传递参数的汇编:

- 传值调用和传指针其实都是将值传递到函数中,只不过这个值含义不同指针是一个地址的值。
- 还可以看出用作传参的寄存器是哪几个。
传值,变量不可改
我们接着看函数中,对参数赋值的汇编:
1. 这里会将参数寄存器中的值,放入栈中。然后释放参数寄存器。
2. 然后将内存地址数据赋值。
3. 这也就说明原来参数的值被复制了一份到内存中,修改当前形参的值,实际是修改栈中内存的值,原变量不会被修改
传指针,变量可改

- 首先还是将参数的值放入内存中,释放寄存器
- 然后将参数x的内存地址传给寄存器,寄存器当前存储的是该地址
- 然后向该寄存器中存储的地址中,写入0.
这也就直接修改了内存中原变量的值,这里的寄存器rax起到了一个中间过渡作用。
Q:为什么传递参数是通过CPU寄存器,而不是直接压入堆栈呢?
A:传递参数,也可以不通过CPU寄存器,而通过压入堆栈的方式,一些老版本的编译器,也是如此操作的。但通过寄存器传递,可以避免一些内存操作,一定程度上有利于提高函数的执行效率。
C++ 传引用
C++ 传引用和传指针的汇编相同,所以传引用只是一个语法糖

函数调用实例

相关文章:
从汇编看函数调用
文章目录 函数调用流程栈相关寄存器及的作用简介寄存器功能指令功能 栈函数的括号{}正括号反括号 参数传递传值,变量不可改传指针,变量可改C 传引用 函数调用实例 函数调用流程 目标:函数调用前后栈保持不变 保存main函数的寄存器上下文移…...
node.js的错误处理
当我打开一个不存在的文件时,错误如下: 在读取文件里面写入console.log(err),在控制台中可以看到我的错误代码类型:文件不存在的错误代码 ENOENT。见更多错误代码---打开node.js官方API文档Error 错误 | N…...
shell的编写
文章目录 1.框架2.命令行3.获取用户命令字符串4.命令行字符串分割5.执行命令和内建命令6.完整代码: 1.框架 我们知道shell是一直存在的,所以首先我们第一步就是要搭建一个框架,使其一直存在。 那么也很简单,一个while循环就可以完…...
css心跳动画
图标引入 <img class"icon" src"heart.svg" alt"" srcset""> CSS代码 <style>.icon {animation:bpm 1s linear,pulse 0.75s 1s linear infinite;}keyframes pulse {from,75%,to {transform: scale(1);}25% {transform:…...
在 Amazon Timestream 上通过时序数据机器学习进行预测分析
由于不断变化的需求和现代化基础设施的动态性质,为大型应用程序规划容量可能会非常困难。例如,传统的反应式方法依赖于某些 DevOps 指标(如 CPU 和内存)的静态阈值,而这些指标在这样的环境中并不足以解决问题。在这篇文…...
【智能排班系统】快速消费线程池
文章目录 线程池介绍线程池核心参数核心线程数(Core Pool Size)最大线程数(Maximum Pool Size)队列(Queue)线程空闲超时时间(KeepAliveTime)拒绝策略(RejectedExecutionH…...
C语言——内存函数
前言: C语言中除了字符串函数和字符函数外,还有一些函数可以直接对内存进行操作,这些函数被称为内存函数,这些函数与字符串函数都属于<string.h>这个头文件中。 一.memcpy()函数 memcpy是C语言中的…...
ideaSSM图书借阅管理系统VS开发mysql数据库web结构java编程计算机网页源码maven项目
一、源码特点 SSM 图书借阅管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码 和数据库,系统主…...
普联一面4.2面试记录
普联一面4.2面试记录 文章目录 普联一面4.2面试记录1.jdk和jre的区别2.java的容器有哪些3.list set map的区别4.get和post的区别5.哪个更安全6.java哪些集合类是线程安全的7.创建线程有哪几种方式8.线程的状态有哪几种9.线程的run和start的区别10.什么是java序列化11.redis的优…...
SQLite的架构(十一)
返回:SQLite—系列文章目录 上一篇:SQLite下一代查询规划器(十) 下一篇:SQLite—系列文章目录 介绍 本文档介绍SQLite库的架构。 这里的信息对那些想要了解或 修改SQLite的内部工作原理。 接口SQL 命令处理器虚拟机B-树…...
Vue2电商前台项目(一):项目前的初始化及搭建
一、项目初始化 创建项目:sudo vue create app 1.项目配置 (1)浏览器自动打开 在package.json文件中,serve后面加上 --open "scripts": {"serve": "vue-cli-service serve --open","buil…...
4.6 offset指令,jmp short指令,far,dword ptr各种跳转指令
4.6 offset指令,jmp short指令,far,dword ptr各种跳转指令 可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括的讲,转移指令就是可以控制CPU执行内存中某处代码的指令 1. 转移指令 1.1 8086CPU的转移行为有以…...
【WEEK5】 【DAY5】DML语言【中文版】
2024.3.29 Friday 目录 3.DML语言3.1.外键(了解)3.1.1.概念3.1.2.作用3.1.3.添加(书写)外键的几种方法3.1.3.1.创建表时直接在主动引用的表里写(被引用的表的被引用的部分)3.1.3.2.先创建表后修改表以添加…...
媒体偏见从何而来?--- 美国MRC(媒体评级委员会)为何而生?
每天当我们打开淘宝,京东,步入超市,逛街或者逛展会,各种广告铺天盖地而来。从原来的平面广告,到多媒体广告,到今天融合AR和VR技术的数字广告,还有元宇宙虚拟世界,还有大模型加持的智…...
Solana 线下活动回顾|多方创新实践,引领 Solana“文艺复兴”新浪潮
Solana 作为在过去一年里实现突破式飞跃的头部公链,究竟是如何与 Web3 行业共振,带来全新的技术发展与生态亮点的呢?在 3 月 24 日刚结束的「TinTin Destination Moon」活动现场,来自 Solana 生态的的专家大咖和 Web3 行业的资深人…...
CSS3 实现文本与图片横向无限滚动动画
文章目录 1. 实现效果2.html结构3. css代码 1. 实现效果 gif录屏比较卡,实际很湿滑,因为是css动画实现的 2.html结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"…...
Android 性能优化之黑科技开道(一)
1. 缘起 在开发电视版智家 App9.0 项目的时候,发现了一个性能问题。电视系统原本剩余的可用资源就少,而随着 9.0 功能的进一步增多,特别是门铃、门锁、多路视频同屏监控后等功能的增加,开始出现了卡顿情况。 经过调研分析发现有…...
Successive Convex Approximation算法的学习笔记
文章目录 一、代码debug二、原理 本文主要参考了CSDN上的 另一篇文章,但规范了公式的推导过程和修缮了部分代码 一、代码debug 首先,我们将所有的代码放到MATLAB中,很快在命令行中出现了错误信息 很显然有问题,但是我不知道发生…...
IoT数采平台2:文档
IoT数采平台1:开篇IoT数采平台2:文档IoT数采平台3:功能IoT数采平台4:测试 【平台功能】 基础配置、 实时监控、 规则引擎、 告警列表、 系统配置 消息通知:Websocket 设备上线、设备下线、 数据变化、 告警信息、 实时…...
Vue监听器watch的基本用法
文章目录 1. 作用2. 格式3. 示例3.1 value 值为字符串3.2 value 值为函数3.3 value 值为对象 4. 与计算属性对比 1. 作用 监视数据变化,执行一些业务逻辑或异步操作。 2. 格式 监听器 watch 内部以 key :value 的形式定义,key 是 data 中的…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
