编写 AMD64 SysV 程序集时哪些寄存器用作临时寄存器?

Which registers to use as temporaries when writing AMD64 SysV assembly?

我正在根据 AMD64 SysV ABI 在汇编中使用 cpuid 实现一个函数。我需要在函数本身中使用 2 个临时寄存器:第一个用于累积 return 值,第二个用作计数器。

我的函数目前看起来是:

;zero argument function
some_cpuid_fun:
  push rbx

  xor r10d, r10d ;counter initial value
  xor r11d, r11d ;return value accumulator initial value
  some_cpuid_fun_loop:
  ;...
  cpuid
  ;update r10d and r11d according to the result


  mov eax, r11d
  pop rbx
  ret

因为 cpuid 破坏了 eaxebxecxedx 我不能在不同的 cpuid 执行中使用它们。如 AMD64 SysV ABI 中所述:

r10    temporary register, used for passing a function’s
       static chain pointer

r11    temporary register

只有一个严格的临时寄存器r11r10似乎有不同的用途(而且它作为循环计数器的用法不是一个,我显然没有传递任何静态链指针).

问题: some_cpuid_fun 函数实现 AMD64 SysV ABI 兼容吗?如果没有,如何重写它以保持与 ABI 兼容?

在您确定了所有用于参数的寄存器后,none 在这种情况下,您只需要关心寄存器是否是易失性的(不在调用之间保留)。

总之,看图3.4的最后一栏(r10的用法出处): not preserved,所以可以用它而不恢复它。
Usage 列仅告诉您在何处查找参数 if expected 以及在何处放置 return 值。
如果你不在输入中使用静态链指针,你可以根据需要尽快覆盖r10

所以是的,使用 r10 作为临时寄存器是 ABI 兼容的。

供参考:

This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling function and the called function is required to preserve their values. In other words, a called function must preserve these registers’ values for its caller. Remaining registers “belong” to the called function. 5 If a calling function wants to preserve such a register value across a function call, it must save the value in its local stack frame.