从汇编层看64位程序运行——参数传递的底层实现

news2024/9/23 5:27:50

大纲

  • 小于等于6个参数
    • 一个参数
      • 总结
    • 两个参数
      • 总结
    • 三个参数
      • 总结
    • 四个参数
      • 总结
    • 五个参数
      • 总结
    • 六个参数
      • 总结
  • 大于6个参数
    • 七个参数
    • 总结

在32位系统中,参数的传递主要依靠栈来进行。那么64位系统上,是否依旧符合这个规则呢?答案是“不是”。64位系统使用了寄存器和栈结合的方案。当参数比较少的时候,使用寄存器传递参数;当参数比较多时,前几个参数仍然采用寄存器传递,但是后几个参数会采用栈传递。
本文我们将探测从1到10个参数传递的汇编实现。
我们在main函数中准备10个栈上变量

int main() {
    int a = 10;
    int b = 20;
    int c = 30;
    int d = 40;
    int e = 50;
    int f = 60;
    int g = 70;
    int h = 80;
    int i = 90;
    int j = 100;

每个int型占4个字节,所以一共需要40个字节,即0x28。但是编译器为了让内存对齐,多分配了8个字节。于是我们看到编译器直接通过下面的语句表达栈上变量空间是0x30(即栈增长了0x30)。

0x000000000000135a <+8>:     sub    $0x30,%rsp

在这里插入图片描述
离rbp最远的是a变量的地址,即-0x28(%rbp)。它表达的是该地址是%rbp-0x28。使用减法的原因是,栈的增长方向是向地址空间低的方向。具体这块知识见《从汇编层看64位程序运行——程序中的栈(Stack)结构及其产生的历史原因》。
在这里插入图片描述

小于等于6个参数

如果参数的个数小于等于6个,则采用寄存器传递。

一个参数

void foo1(int a) {
    a = a + 5;
}

调用foo1处的汇编如下
在这里插入图片描述
它会将栈中a变量的值放到eax寄存器中,然后将eax寄存器的值放到edi寄存器中。edi就充当了参数传递的“使者”。
在这里插入图片描述
我们在foo1的汇编代码处可以看到,它将edi寄存器中的值保存到它的栈帧的地址空间中(rbp-0x04),然后才可开始做计算。
可能有人注意到,为什么调用处要先将变量值保存到eax,然后再保存到edi中,而不是直接保存到edi中呢?在这个案例中,的确是没有必要的。但是后面涉及栈传递参数时,这种设计就很有必要了。

总结

一个参数时直接使用edi寄存器传递参数。

两个参数

void foo2(int a, int b)

在这里插入图片描述
a(-0x28(%rbp))被先保存到eax寄存器中,然后eax寄存器的值保存到edi寄存器中;
b(-0x24(%rbp))被先保存到edx寄存器中,然后edx寄存器的值保存到esi寄存器中;
这意味着a的值被保存到edi,b的值被保存到esi中,然后借用这两个寄存器进行参数传递。
在这里插入图片描述

总结

两个参数时,参数分别通过edi、esi寄存器传递。

三个参数

void foo3(int a, int b, int c) 

在这里插入图片描述
第一个参数a和之前的规则一样,先保存到eax,然后再保存到edi中。
但是这次由于edx寄存器要参与参数传递,即foo3函数要使用edx寄存器。于是第二个参数值先被保存到ecx寄存器中,然后再传递给esi寄存器。
在这里插入图片描述

总结

三个参数时,参数分别通过edi、esi和edx寄存器传递。

四个参数

void foo4(int a, int b, int c, int d)

在这里插入图片描述
第一个参数a和之前的规则一样,先保存到eax,然后再保存到edi中。
而这次由于ecx也要参与参数传递,于是b(-0x24(%rbp))被直接保存到esi中、c(-0x20(%rbp))被直接保存到edx中、d(-0x1c(%rbp))被直接保存到ecx中。这次参数的传递没有经过太多中间寄存器,相对高效。
在这里插入图片描述

总结

四个参数时,参数分别通过edi、esi、edx和ecx寄存器传递。

五个参数

void foo5(int a, int b, int c, int d, int e)

在这里插入图片描述
这次针对第五个参数e,它会先被保存到edi寄存器中,然后edi寄存器的值会保存到r8d寄存器。这就意味着e被保存到r8d寄存器中。由于edi寄存器最终要传递第一个参数a,于是在调用foo5前,会将临时存储a的eax寄存器的值设置到edi寄存器中。
我们发现edi寄存器被频繁使用,而它又被当做帮助第一个参数传递的寄存器,于是编译器会先见第一个参数保存到其他寄存器中,然后在调用函数之前在将临时存储第一个参数的寄存器的值保存到edi中。
在这里插入图片描述

总结

五个参数时,参数分别通过edi、esi、edx、ecx和r8d寄存器传递。

六个参数

void foo6(int a, int b, int c, int d, int e, int f)

在这里插入图片描述
具体的方式和之前类似,只是r8d和edi都作为临时寄存器保存栈上数据,然后在调用foo6函数前,将它们还原成它们理应要去代表的参数。
在这里插入图片描述

总结

六个参数时,参数分别通过edi、esi、edx、ecx、r8d和r9d寄存器传递。

大于6个参数

如果参数的个数大于6个,则前6个仍然采用寄存器传递,后面的使用栈传递。

七个参数

void foo7(int a, int b, int c, int d, int e, int f, int g)

在这里插入图片描述
前6个参数使用edi、esi、edx、ecx、r8d和r9d寄存器传递到子函数。
第7个参数g(-0x10(%rbp))被先保存到edi(32位,属于64位rdi),然后被push到栈中。
在这里插入图片描述
在foo7函数中,栈上的变量会直接参与计算,而不用再拷贝到foo7的栈帧中。
在这里插入图片描述
8,9,10个参数和7个参数是类似的,过程就不写了。

总结

  • 参数不超过6个时,参数按需使用edi、esi、edx、ecx、r8d和r9d寄存器传递到子函数。
  • 参数超过6个参数时,前6个参数使用edi、esi、edx、ecx、r8d和r9d寄存器传递到子函数;从第7个参数起,后面的参数都通过栈传递。

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

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

相关文章

Objective-C 自定义渐变色Slider

文章目录 一、前情概要二、具体实现 一、前情概要 系统提供UISlider&#xff0c;但在开发过程中经常需要自定义&#xff0c;本次需求内容是实现一个拥有渐变色的滑动条&#xff0c;且渐变色随着手指touch的位置不同改变区域&#xff0c;类似如下 可以使用CAGradientLayer实现渐…

【Linux】Linux操作系统

Linux基本指令 os概念与定位 本节内容&#xff1a; Linux操作系统讲解 os概念与定位 操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;是管理和控制计算机硬件与软件资源的计算机程序。总的来讲&#xff0c;操作系统是一款做软硬件管理的软件。 了解操作…

springBoot(若依)集成camunda

1、下图为项目结构 2、最外层 pom引入依赖 <properties><!--camunda 标明版本&#xff0c;注意要个自己的Spring 版本匹配&#xff0c;匹配关系自行查询官网--><camunda.version>7.18.0</camunda.version> </properties> 3、common模块引入依赖 …

安卓14中Zygote初始化流程及源码分析

文章目录 日志抓取结合日志与源码分析systemServer zygote创建时序图一般应用 zygote 创建时序图向 zygote socket 发送数据时序图 本文首发地址 https://h89.cn/archives/298.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 本文主要结合日志和代码看安卓 14 中 Zy…

抗量子密码算法:保障未来信息安全的新盾牌

随着量子计算的迅猛发展&#xff0c;传统加密算法正面临着前所未有的挑战。量子计算机利用量子比特的特殊性质&#xff0c;能在极短时间内破解目前广泛使用的公钥加密体系&#xff0c;如RSA、ECC等。这使得我国及全球的信息安全体系遭受严重威胁。为了应对这一挑战&#xff0c;…

知识图谱入门笔记

自学参考&#xff1a; 视频&#xff1a;斯坦福CS520 | 知识图谱 最全知识图谱综述 详解知识图谱的构建全流程 知识图谱构建&#xff08;概念&#xff0c;工具&#xff0c;实例调研&#xff09; 一、基本概念 知识图谱&#xff08;Knowledge graph&#xff09;&#xff1a;由结…

基于LSTM的局部特征提取网络算法原理

目录 一、LSTM的基本原理与结构 1. LSTM的核心结构 2. LSTM的工作原理 二、基于LSTM的局部特征提取 1. 输入处理与序列表示 2. LSTM层处理与特征提取 3. 特征提取的优势与应用 三、实现细节与注意事项 1. 数据预处理 2. 网络结构与参数选择 3. 训练策略与正则化 4.…

Chapter 1:数据结构前言

在数字化的世界里&#xff0c;我们每天都在与数据打交道。然而&#xff0c;你是否曾想过&#xff0c;这些数据是如何被组织、存储和处理的&#xff1f;这就是数据结构的魅力所在。 数据结构&#xff0c;简单来说&#xff0c;就是数据的组织方式。它决定了我们如何高效地访问和操…

【游戏客户端】大话slg玩法架构(三)建筑控件

【游戏客户端】大话slg玩法架构&#xff08;三&#xff09;建筑控件 大家好&#xff0c;我是Lampard家杰~~ 今天我们继续给大家分享SLG玩法的实现架构&#xff0c;关于SLG玩法的介绍可以参考这篇上一篇文章&#xff1a;【游戏客户端】制作率土之滨Like玩法 PS&#xff1a;和之前…

JVM系列 | 垃圾收集算法

JVM系列 | 垃圾收集算法 文章目录 前言如何判断对象已"死"&#xff1f;引用计数法可达性分析算法可达性分析2.0版 | 引用的增强对象的消亡过程回收方法区主要回收目标&#xff1a;回收操作 垃圾收集算法分代收集理论 与 跨代引用假说分代收集理论跨带引用假说 垃圾收…

Oracle数据库加密与安全

Wallet简介&#xff1a; Oracle Wallet(即内部加密技术TDE( Transparent DataEncryption&#xff09; TDE是 Oracle10gR2中推出的一个新功能,使用时要保证Oracle版本是在10gR2或者以上 Wallet配置&#xff1a; 1.创建一个新目录&#xff0c;并指定为Wallet目录 /home/oracle…

论文翻译:Large Language Models for Education: A Survey and Outlook

https://arxiv.org/abs/2403.18105 目录 教育领域的大型语言模型&#xff1a;一项调查和展望摘要1. 引言2. 教育应用中的LLM2.1 概述2.2 学习辅助2.2.1 问题解决&#xff08;QS&#xff09; 2.2.2 错误纠正&#xff08;EC&#xff09;2.2.3 困惑助手&#xff08;CH&#xff09;…

ExcelToDB2:批量导入Excel到IBM DB2数据库的自动化工具

ExcelToDB2&#xff1a;批量导入Excel到IBM DB2数据库的自动化工具 简介 ExcelToDB2是一个可以批量导入Excel到IBM DB2数据库的自动化工具。支持将xls/xlsx/xlsm/xlsb/csv/txt/xml格式的Excel文件导入到IBM DB2等多种原生及国产数据库。自动化是其最大的特点&#xff0c;因为它…

Python爬虫教程第5篇-使用BeautifulSoup查找html元素几种常用方法

文章目录 简介find()和find_all()字符串通过id查找通过属性查找通过.方式查找通过CSS选择器查找通过xpath查找正则表达自定义方法总结 简介 上一篇详细的介绍了如何使用Beautiful Soup的使用方法&#xff0c;但是最常用的还是如何解析html元素&#xff0c;这里再汇总介绍下查询…

数据分析——Python网络爬虫(四){正则表达式}

爬虫库的使用 爬虫的步骤正则表达式正则表达式的流程正则表达式的使用括号的使用管道匹配问号匹配星号匹配加号匹配花括号匹配用点-星匹配所有字符跨行匹配findall方法其他常用字符匹配 例子正则表达式在线测试 爬虫的步骤 #mermaid-svg-zSQSbTxUEex051NQ {font-family:"t…

Web开发 —— 放大镜效果(HTML、CSS、JavaScript)

目录 一、需求描述 二、实现效果 三、完整代码 四、实现过程 1、HTML 页面结构 2、CSS 元素样式 3、JavaScript动态控制 &#xff08;1&#xff09;获取元素 &#xff08;2&#xff09;控制大图和遮罩层的显隐性 &#xff08;3&#xff09;遮罩层跟随鼠标移动 &…

【电脑应用技巧】如何寻找电脑应用的安装包华为电脑、平板和手机资源交换共享

电脑的初学者可能会直接用【百度】搜索电脑应用程序的安装包&#xff0c;但是这样找到的电脑应用程序安装包经常会被加入木马或者强制捆绑一些不需要的应用装入电脑。 今天告诉大家一个得到干净电脑应用程序安装包的方法&#xff0c;就是用【联想的应用商店】。联想电脑我是一点…

使用Lego进行证书的申请和更新

姊妹篇: 使用Let’s Encrypt 申请通配符证书 关于acme 协议 ACME是自动证书管理环境&#xff08;Automatic Certificate Management Environment&#xff09;的缩写&#xff0c;是一个由IETF&#xff08;Internet Engineering Task Force&#xff09;制定的协议标准&#xff0c…

gd32F470串口重定义

c代码&#xff1a; /** Author: Bleaach008* Date: 2024-07-10 17:31:01* LastEditTime: 2024-07-11 09:42:06* FilePath: \MDK-ARMd:\Code\GD32\GD01_UART\MyApplication\Public.c* Description:** Copyright (c) 2024 by 008, All Rights Reserved.*/ /* Includes ----------…

QFileDialog的简单了解

ps&#xff1a;写了点垃圾&#xff08;哈哈哈&#xff09; 现在感觉Qt库应该是调用了Windows提供的这块的接口了。 它继承自QDialog 这是Windows自己的文件夹 这是两者的对比图&#xff1a; 通过看QFileDialog的源码&#xff0c;来分析它是怎么实现这样的效果的。 源码组成…