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

大纲

  • 小于等于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.mzph.cn/bicheng/45702.shtml

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

相关文章

FFmpeg开发环境搭建

FFmpeg是音视频开发必备的库&#xff0c;也是唯一的库。本文主要讲解在ubuntu22和macOS14环境下的编译安装。 为什么要自己编译呢&#xff1f;其中一个很重要的原因就是ffmpeg在编译时可以加入很多插件&#xff0c;这种特定的库网络上可能找不到编译好的版本&#xff0c;另外如…

在自定义总线下注册设备

1、自定义总线下注册设备 //my_bus_dev.c #include<linux/module.h> #include<linux/init.h> #include<linux/kernel.h> #include<linux/kobject.h> #include<linux/slab.h> #include<linux/sysfs.h> #include<linux/device.h> #in…

solidity实战练习3——荷兰拍卖

//SPDX-License-Identifier:MIT pragma solidity ^0.8.24; interface IERC721{function transFrom(address _from,address _to,uint nftid) external ; }contract DutchAuction { address payable immutable seller;//卖方uint immutable startTime;//拍卖开始时间uint immut…

属于马云的时代结束了

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 马云突然回国了&#xff0c;还出现在阿里巴巴的大厦里。大家都非常激动&#xff0c;阿里沸腾了&#xff0c;整个杭州&#xff0c;甚至全网都沸腾了&#xff0c;日本慌了&#xff0c;美国坐不住了&#xff0c;欧洲陷…

CSS技巧专栏:一日一例 5-纯CSS实现背景色从四周向中心填充的按钮特效

特此说明 本专题专注于讲解如何使用CSS制作按钮特效。前置的准备工作和按钮的基本样式,都在本专栏第一篇文章中又详细说明。自本专栏第四篇文章起,本专栏都将直接跳过前面的内容,不再重复复制,需要了解按钮基础样式的同学,请移步:《CSS技巧 - 一日一例 (1):会讨好的热…

关键路径-matlab

路径上边的数目称为路径长度 图的基本知识 求最短路径&#xff08;Dijkstra算法&#xff09; 2. 待继续尝试 ①Dijkstra ②floyd_all.m 一 二 ③ LeetCode [329. 矩阵中的最长递增路径]

SpringCloud---zuul路由网关

zuul网关 zuul网关定义 Zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet(filter)应用。Zuul 在云平台上提供动态路由&#xff0c;监控&#xff0c;弹性&#xff0c;安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的…

Kithara与OpenCV (二)

Kithara使用OpenCV QT 进行特征检测 目录 Kithara使用OpenCV QT 进行特征检测OpenCV 特征检测简介Qt应用框架简介项目说明关键代码抖动测试测试平台&#xff1a;测试结果&#xff1a;结论 OpenCV 特征检测简介 OpenCV是一个开源的计算机视觉库&#xff0c;提供了各种图像处理…

一图展示免费开源的分布式版本控制系统​Git

文章目录 前言一、安装Git二、Git配置三、git命令 前言 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 一、安装Git Windows操作系统…

如何更好的优化 ListView 控件的性能

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD&#xff0c;日常还会涉及Android开发工作。 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起…

MongoDB教程(四):mongoDB索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

windows查看局域网所有设备ip

windows如何查看局域网所有设备ip 操作方法 一 . 在搜索栏里输入cmd 二 .在命令行黑窗口输入arp -a 三 . 最上面显示的动态地址就是所有设备ip

IOS上微信小程序密码框光标离开提示存储密码解决方案

问题&#xff1a; ios密码框输入密码光标离开之后会提示存储密码的弹窗 解决方案 1、在苹果手机上面把 “自动填充密码”关闭&#xff0c;但是苹果这个默认开启&#xff0c;而且大部分客户也不会去自己关闭。 2、欺骗苹果手机&#xff0c;代码实现。 先说解决思路&#xf…

80. UE5 RPG 实现UI显示技能冷却进度功能

在上一篇文章里&#xff0c;我们实现了通过GE给技能增加资源消耗和技能冷却功能。UI也能够显示角色能够使用的技能的UI&#xff0c;现在还有一个问题&#xff0c;我们希望在技能释放进去冷却时&#xff0c;技能变成灰色&#xff0c;并在技能冷却完成&#xff0c;技能可以再次使…

在Anaconda环境中安装TensorFlow+启动jupyter notebook

1.打开cmd&#xff0c;输入C:\Users\xy>conda create -n tensorflow python3.7 这是在环境中创建了一个名为tensorflow的环境&#xff0c;具体会显示以下信息&#xff1a; C:\Users\xy>conda create -n tensorflow python3.7 Retrieving notices: ...working... done Co…

Python实战Elasticsearch的核心技巧详解

概要 Elasticsearch 是一个分布式的搜索引擎,可以用于全文搜索、结构化搜索、分析等多种场景。它基于Lucene构建,提供了强大的搜索功能和数据分析能力。本文将详细介绍如何使用Python实现与Elasticsearch的交互,包括安装、配置、基本操作和实际应用示例。 安装和配置 安装…

centos单机配置多个内网IP地址

centos单机配置多个内网IP地址 引配置1. 查看当前网络IP配置2. 打开网络配置目录3. 设置静态IP4. 编辑ifcfg-eno1:15. 重启网络配置 引 同一个局域网&#xff0c;但是对接的多个子系统使用了不同的网段&#xff0c;如一个系统主机IP地址是192.168.10.1&#xff0c;另一个系统主…

基于B站视频评论的文本分析,采用包括文本聚类分析、LDA主题分析、网络语义分析

研究主题 本研究旨在通过对B站视频评论数据进行文本分析&#xff0c;揭示用户评论的主题、情感倾向和语义结构&#xff0c;助力商业决策。主要技术手段包括Python爬虫、LDA主题分析、聚类分析和语义网络分析。首先&#xff0c;利用Python爬虫采集大量评论数据并进行预处理。运…

npm发布的包如何快速在cnpm上使用

npm发布的包如何快速在cnpm上使用 解决方案 前往淘宝npm镜像官网 搜索插件库并点击同步 等待一分钟即可查看最新版本

linux进程周边知识——内核对硬件的管理——计算机世界的管理

前言&#xff1a;本节主要讲解内核也就是操作系统对于硬件的管理&#xff0c; 本节内容同样为进程的周边知识。 主要是关于软件方面&#xff0c; 和我的上一篇——冯诺依曼体系结构可以说是兄弟文章&#xff0c; 这篇文章主要是关于硬件方面。 两篇文章都是为学习进程做准备。但…