使用汇编语言x86-64时,用于存储计算值的寄存器顺序是否有约定?

问题描述 投票:0回答:1

我知道这个问题已经提交了很多次,但我还没有找到任何明确的答案,所以很抱歉,但我仍然有疑问。

在用汇编语言编程时,出于个人问题,不一定要与外部库链接,但想遵守书面或非书面约定,我应该使用哪些寄存器以及按什么顺序?

我想过使用函数参数(RDI、RSI、RDX、RCX、R8、R9)使用的相同寄存器来存储值(如果我需要的话)。另外,如果我需要更多,我会从 R10-R15 开始,但我不确定这是否是惯例。

还有,寄存器之前选择栈的标准是什么?

PS。再次抱歉,我问了一个已经提交到网站几次的问题,但我只想“正确”地做。谢谢。

assembly coding-style x86-64 cpu-registers conventions
1个回答
0
投票

在任何调用约定中,请在调用保留的寄存器之前使用调用破坏的寄存器,但您希望在函数调用中保留的值除外。我对该链接问答的回答涵盖了您所询问的有关如何/何时使用寄存器的很多内容。

对于 Windows 以外的操作系统上的 x86-64,请参阅 通过 linux x86-64 函数调用保留哪些寄存器,了解调用约定详细信息,例如哪些寄存器被调用破坏。 (不是 R12-R15)。


在 x86-64 上的调用破坏寄存器中,它们在大多数用途上都是等效的,尽管许多指令对 AL 或 EAX 的编码较小,分别具有 8 位或 32 位立即数。 (在其他条件相同的情况下,机器代码大小通常越小越好,以获得更好的 I 缓存密度和前端解码吞吐量。)

请注意,使用标准 3 字节

add eax, 4
编码时,
add r/m32, imm8
是最短的,而不是 5 字节
add eax, imm32
。 8 位立即数操作的 AL 总是节省空间,但 32 或 64 位操作的 EAX 只为不适合 imm32 的常量节省空间。或者对于
test eax, immediate
因为没有
test r/m, imm8
编码。当然,如果您想要低位,您可以随时使用
test al, 1
代替
test eax, 1
;你唯一失去的就是像
test eax, -128
这样的东西来检查除低 7 位以外的所有内容,并带有负数的符号扩展。

另请参阅为什么 RBP 和 RSP 被称为通用寄存器?了解涉及某些寄存器(以 RBP、R12 和 R13 为基址)的某些寻址模式的额外代码大小的详细信息。

RBP/RSP Q&A 还提到了这样一个事实,即大多数“传统”寄存器(不是 R8-R15)都有一些隐式使用它们的特殊指令。就像 RCX(特别是 CL)是可变计数移位计数的唯一寄存器一样,如

shr edx, cl
,除非您有 BMI2
shrx edx, eax, esi
(代码大小很大,但在 Intel 上效率更高,是单微操作。)

另一种情况,其他一切都不相同:哪个 Intel 微架构引入了 ADC reg,0 单微指令特殊情况? - 即使在 Skylake 上,

adc al, 0
短格式编码也是 2 微指令,没有明显的原因,只是固定在阿尔德湖。

© www.soinside.com 2019 - 2024. All rights reserved.