为什么 x86-64 System V 调用约定在寄存器中传递参数而不是仅在堆栈中传递参数?

2024-03-23

为什么 32 位 C 将所有函数参数直接压入堆栈,而 64 位 C 将前 6 个参数放入寄存器,其余参数压入堆栈?

所以 32 位堆栈看起来像:

...
arg2
arg1
return address
old %rbp

虽然 64 位堆栈看起来像:

...
arg8
arg7
return address
old %rbp
arg6
arg5
arg4
arg3
arg2
arg1

那么为什么 64 位 C 会这样做呢?将所有内容压入堆栈,而不是将前 6 个参数放入寄存器中,然后将它们移动到函数序言中的堆栈上,不是更容易吗?


而不是将前 6 个参数放入寄存器中只是为了将它们移动到函数序言中的堆栈上?

我正在查看 gcc 生成的一些代码,这就是它总是做的事情。

然后你忘了启用优化. gcc -O0 将一切都溢出到内存中 https://stackoverflow.com/questions/53366394/why-does-clang-produce-inefficient-asm-with-o0-for-this-simple-floating-point因此您可以在单步执行时使用调试器修改它们。这对于性能来说显然是可怕的,所以编译器不会这样做,除非你通过编译来强制它们这样做-O0.

x86-64 System V 允许int add(int x, int y) { return x+y; }编译为
lea eax, [rdi + rsi] / ret,这就是编译器实际执行的操作,如您所见Godbolt 编译器浏览器 https://godbolt.org/z/rG7VTF.

Stack-args 调用约定缓慢且过时。 RISC 机器在 x86-64 存在之前就一直在使用寄存器参数调用约定,并且在仍然关心 32 位 x86 的操作系统(即 Windows)上,有更好的调用约定,例如__vectorcall传递寄存器中的前 2 个整数参数。

i386 System V 尚未被取代,因为人们大多不太关心其他操作系统上的 32 位性能;我们只是使用 64 位代码和精心设计的 x86-64 System V 调用约定。

有关调用约定设计中寄存器参数和调用保留寄存器与调用破坏寄存器之间的权衡的更多信息,请参阅为什么不将函数参数存储在 XMM 向量寄存器中? https://stackoverflow.com/questions/33707228/why-not-store-function-parameters-in-float-registers,并且为什么 Windows64 使用与 x86-64 上所有其他操作系统不同的调用约定? https://stackoverflow.com/questions/4429398/why-does-windows64-use-a-different-calling-convention-from-all-other-oses-on-x86/35619528#35619528.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 x86-64 System V 调用约定在寄存器中传递参数而不是仅在堆栈中传递参数? 的相关文章

  • 在 OllyDbg 和 Assembler 中,EBP+8 是什么意思?

    我正在学习 OllyDbg 中的汇编和调试技巧 以便学习如何使用未记录的函数 现在我遇到以下问题 我有以下代码部分 来自 OllyDbg MOV EDI EDI PUSH EBP MOV EBP ESP MOV EAX DWORD PTR
  • x86-64 AMD 上 CALL 指令的操作数生成

    以下是示例程序 objdump 的输出 080483b4
  • gcc:对 -static -shared -fPIE -fPIC -Wl,-pie 感到困惑

    我正在尝试构建 clang 所有库都静态链接 这样我就可以在具有古老 GCC 4 4 版本的 CentOS 6 上运行它 首先 我想添加选项 static通过打开 LLVM BUILD STATIC 就足够了 但到了链接阶段 就出错了 生成
  • MinGW:与 -nostdlib 链接会产生无效的可执行文件

    我花了过去几个小时尝试链接一个简单的 x86 汇编程序 而无需any使用 MinGW 的 CRT 初始化代码 我希望可执行文件只包含 main下面列出的方法和一次导入ExitProcess核函数 在反汇编程序中打开各种生成的文件表明 mai
  • elf 文件中的 `.rodata.str1.8` 部分意味着什么

    我知道 rodata节将常量数据存储在 ELF 文件中 然而 当我转储内核模块的 ELF 时 我注意到有两个额外的部分 名为rodata str1 8 and rodata str1 1 看起来这两个部分也存储常量变量和字符串 但这三者到底
  • 如何在 C 中使用 google 模拟?

    我正在维护一个用 C 编写的遗留项目 并且无法使用 C 编译器运行它 由于代码是交叉编译的 因此可以在主机环境中运行单元测试或类似测试 因此 也可以与 C 主机编译器交互并使用 google test 和 google mock googl
  • Olve Maudal 的 C++ 测验背后的解释(别名模板)

    以下代码来自http www pvv org oma PubQuiz ACCU Apr2014 pdf http www pvv org oma PubQuiz ACCU Apr2014 pdf 6 第 34 页的解决方案 目标是猜测以下的
  • 为什么 GCC 不自动矢量化这个循环?

    我正在尝试优化一个占用程序大量计算时间的循环 但是 当我使用 O3 ffast math ftree vectorizer verbose 6 GCC 输出打开自动矢量化时 它无法对循环进行矢量化 我正在使用海湾合作委员会4 4 5 代码
  • OSX - 将 gcc 版本 4.2.1 替换为通过 Homebrew 安装的 4.9

    这已经困扰我一段时间了 我正在尝试编译一个巨大的 C 文件 我知道它可以工作 因为它在我工作的 Arch Linux 计算机上工作得很好 当我在 mac 上检查 GCC 版本时 它返回以下内容 Configured with prefix
  • 为什么静态数组的大小不能可变?

    相关但不完全重复 因为它讨论了 C 我们可以给静态数组的大小一个变量吗 https stackoverflow com questions 7696591 can we give size of static array a variabl
  • 针对 openpose 将 GCC 9.3.0 降级到 7 后,cuda_compile_1_ generated_batch_norm_layer.cu.o.Release.cmake 出现 CMake 错误

    你知道我该如何解决以下错误吗 这是在我使用以下命令从 GCC 9 3 0 降级到 7 后发生的 使用以前版本的 GCC 我收到此错误 CMake 不支持的 GNU 版本 不支持高于 8 的 gcc 版本 https stackoverflo
  • gcc 使用 c++11 标准,即使 98 明确指定

    我收到一个奇怪的错误 我怀疑与我的系统配置有关 我正在使用 g version 编译 链接一个简单的 C 程序g Ubuntu 5 4 0 6ubuntu1 16 04 4 5 4 0 20160609 默认语言标准记录为 c 98 但即使
  • 从 GP regs 加载 xmm

    假设您的价值观是rax and rdx你想加载到xmm登记 一种方法是 movq xmm0 rax pinsrq xmm0 rdx 1 虽然速度相当慢 有没有更好的办法 在最近的 Intel 或 AMD 上 你不会在延迟或 uop 计数方面
  • 如何在 MacOS 上的 MARS 中打开保存的 .asm 文件

    我是 MIPS 的新手 我找不到如何打开我保存的文件 我在下载文件夹下保存了 asm 文件 但是当我尝试在 MARS 中打开文件并导航到同一下载文件夹时 asm 文件不会出现 我在 MacOS 上使用 MARS 如上所述 您需要在 macO
  • GCC -fstack-check 选项在 C 中引发什么异常

    根据 gcc 文档 fstack check 生成代码以验证您没有超出堆栈边界 请注意 此开关实际上并不导致检查完成 而是执行检查 操作系统必须这样做 该切换会导致代码生成 以确保操作系统看到正在扩展的堆栈 我的假设是这个额外的代码将生成异
  • .so 文件的 objdump?需要帮助来理解消息

    我正在开发一个与流相关的本机应用程序 我在我的 c 模块中遇到了一些问题 我收到的是来自 Logcat 的一些消息 这是 Logcat 消息 INFO DEBUG 28 Build fingerprint generic sdk gener
  • 32 位 x86 汇编中堆栈对齐的职责

    我试图清楚地了解谁 调用者或被调用者 负责堆栈对齐 64 位汇编的情况相当清楚 它是由caller 请参阅系统 V AMD64 ABI 第 3 2 2 节栈帧 输入参数区域的末尾应按 16 对齐 32 如果 m256 在堆栈 字节边界上传递
  • 将 32 位值加载到 Arm 汇编中的寄存器中

    我想使用arm汇编将1个32位十六进制直接加载到寄存器中 mov r1 0x6c617669 这不能使用 因为从该指令我们只能加载 8 位值 所以我直接从内存加载32位值 那么如何将32位值存储在内存中并使用arm汇编将其直接加载到寄存器中
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良

随机推荐

  • python 使用 for 循环将用户输入添加到空列表中

    所以我想使用此代码将用户输入添加到空列表中 no of num int input enter the number of numbers you would like to add n this will store the number
  • 在经典ASP页面调用存储过程

    我一整天都在努力从经典 ASP 页面调用存储过程 我有一些基本的菜鸟问题 首先 这是向我的命令添加参数的最佳方法吗 cmd Parameters Append cmd CreateParameter SubmissionDate adDBT
  • 如何使用 cmp 将排序从 python 2 转换为 python 3?

    我正在尝试将用 python 2 编写的代码转换为 python 3 nums 30 31 num sort cmp lambda x y cmp y x x y 不知道如何在 python 3 中做到这一点 因为 cmp 被删除了 我相信
  • 测试 Dart 值是否实际上是一个函数?

    是否可以测试一个值是否是一个可以调用的函数 我可以轻松测试 null 但之后我不知道如何确保传入的参数实际上是一个函数 void myMethod funcParam if funcParam null How to test if fun
  • 检查 VSTS 中以前的构建信息(VSTS API)

    在执行 VSTS 构建期间是否可以访问以前的构建变量 例如 我可以获得先前构建的 Build SourceVersion 或 Build QueuedBy 吗 我可以通过 Build SourceVersion 等构建变量获取当前构建信息
  • 使用 LDAP 用户名作为实体名称

    我正在使用 Hashicorp Vault 1 9 0 并且启用了 LDAP 身份验证方法 该方法按预期正常工作 但有一个问题 LDAP 是我们独特的身份验证方法 当然 除了令牌之外 并且 LDAP 用户不是提前在 Vault 中创建的 因
  • 在 PHP 中搜索并获得双重结果

    这是我的 PHP 代码 我用它从 PHPMyAdmin 的数据库 Mysql 中进行搜索 但是当我得到结果时 它显示双倍 我不明白为什么是双的 如果它是 for foreach 循环 那么我将使用什么来代替它 请帮我解决代码
  • Python (CherryPy) Web 应用程序部署在本地,但在 Intranet 上不可见

    我使用 CherryPy 创建了一个 Python Web 应用程序 并部署在我的本地计算机上 当我尝试从家里的另一台计算机上查看它时 没有任何结果 但是 如果我创建一个简单的 html 文件 并使用以下命令部署它 python m Sim
  • 如何将 SAP .txt 提取转换为 .csv 文件

    我有一个 txt 文件 如下面报告的示例所示 我想将其转换为 csv 表 但我没有取得太大成功 Mack3 Line Item Journal Time 14 22 33 Date 03 10 2015 Panteni Ledger 1L
  • Jquery随机单词不重复

    我需要在 div 中显示随机单词而不重复该单词 随机单词将每隔随机秒 3 5 秒 附加一个 div 如果数组中的所有值都显示在 div 中 则会发出警报 例子 b a c d ALERT DONE Not b a b c d d a a c
  • 无法聚焦 Web 元素来发送密钥

    我有一组测试 需要登录然后执行搜索 我的应用程序是 Angular JS 我正在起诉 Protractor 事实上 我的测试工作正常 直到我收到我的应用程序的新套件 并且此时我的所有测试都失败了 element by id mainGlob
  • C# 访问另一个用户的注册表

    我当前使用的 Windows 服务有问题 基本上 我将一些值存储在HKCU注册表 来自以管理员身份运行的 GUI 工具 并从该 GUI 中启动一项服务 该服务使用SYSTEM帐户来运行 我相信这是我的问题 我无法访问服务中使用 GUI 工具
  • 从命令行将 JAR 依赖项与可执行 JAR (Über JAR) 捆绑在一起

    我正在尝试从命令行创建可执行 jar JAR 中的主类具有我已打包到另一个普通 JAR 文件中的依赖项 我想将依赖项 JAR 与可执行 JAR 打包在一起 以便提供单个 JAR 文件 到目前为止我已经尝试过以下内容 依赖Hello clas
  • C++ 和抽象类中的继承

    我在正确处理存在抽象类的方法重写时遇到问题 在我的类层次结构中 我会尝试解释一下 class AbstractClass public virtual void anyMethod 0 class A public AbstractClas
  • 使用 WinSCP .NET 未找到方法异常 (EventWaitHandle..ctor)

    我正在尝试使用 PowerShell 和 WinSCP NET 程序集连接到 SFTP 服务器 代码无法打开会话 session Open sessionOptions 在我发现的日志中 Exception System MissingMe
  • 每个版本的 IE 在新窗口中打开链接

    我一直在设计一个网站 并使用 Safari 和 Chrome 进行大部分测试 我刚刚尝试测试 Firefox 也很顺利 让 IE 来解决吧 由于某种原因 对于从 IE 6 到 IE 10 的每个版本 每个链接都会打开一个新窗口 在 IE 1
  • 将文本包裹在圆形 div 内[重复]

    这个问题在这里已经有答案了 我想完成这样的事情 我尝试创建一个 div 并给它一个border radius of 50 问题是文本溢出了圆角 我怎样才能做到这一点 以便整个圆圈可以被填满而不溢出 那这个呢 div border 1px s
  • XML 在 python 中行走[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我是 python 新手 想了解解析
  • Python 多处理作业到 Celery 任务但 AttributeError

    我做了一个像这样的多处理函数 import multiprocessing import pandas as pd import numpy as np def apply df args df func kwargs args retur
  • 为什么 x86-64 System V 调用约定在寄存器中传递参数而不是仅在堆栈中传递参数?

    为什么 32 位 C 将所有函数参数直接压入堆栈 而 64 位 C 将前 6 个参数放入寄存器 其余参数压入堆栈 所以 32 位堆栈看起来像 arg2 arg1 return address old rbp 虽然 64 位堆栈看起来像 ar