繁体   English   中英

是否保存了rdi和rsi呼叫者或被呼叫者保存的寄存器?

[英]Are rdi and rsi caller saved or callee saved registers?

从Wikipedia x86调用约定中可以看出,对于Microsoft x64调用约定:

寄存器RBX,RBP, RDI,RSI ,RSP,R12,R13,R14和R15被认为是非易失性的(被调用者保存)。

但对于System V AMD64 ABI:

如果被叫方希望使用寄存器RBX,RBP和R12-R15,则必须在将控制权返回给调用方之前恢复其原始值。

它没有提及有关rdi和rsi的任何内容。

我还读到%rax,%rcx,%rdx, %rdi,%rsi ,%rsp和%r8-r11被视为调用方保存寄存器 (来自pdf)

我的问题是,在不同平台上调用约定是否有所不同?(我尝试在unix环境下的asm中编写一些libc函数)

我找不到任何讨论此主题的文章,该主题的资源也将有所帮助。 我想知道这些约定的优点和缺点。

是的,在我所知道的所有函数调用约定中,传递arg的寄存器都被调用了。 (除了系统调用的调用约定,而正常情况下所有的REG被保留,除了一个返回值,包括ARG传递。除x86-64的syscall破坏RCX和R11 ...)

特别是在x86-64系统V中,除RBX,RBP,RSP和R12-R15之外的所有寄存器都被称为呼叫簇。 (其中包括xmm0-15,x87 / mmx寄存器以及AVX512 zmm0-31和k0-k7掩码寄存器。)

通过linux x86-64函数调用保留的寄存器显示了ABI doc中的表


调用约定/ ABI将寄存器的状态定义为保留呼叫或保留呼叫的状态。 不同的约定可以做出不同的选择。

是的,Microsoft Windows选择了与其他所有人不同的调用约定: 为什么Windows64使用与x86-64上所有其他操作系统不同的调用约定? 在Windows x64中,RDI是保留呼叫的,就像大多数32位调用约定一样。

但是在x86-64 System V中,设计人员从头开始选择寄存器,并且(如我对这个链接问题的回答所示)发现,对于前2个args使用RDI和RSI可以节省指令(在使用早期x86-64端口构建SPECint时)的gcc)。 可能是因为当时gcc喜欢使用rep stosd内联memsetmemcpy ,或者库实现使用了它。

(说RDI 本质上是调用集群的,这是没有道理的,x86-64 ISA并未对此进行定义。这取决于每个平台来选择。)


术语:

我讨厌“保存呼叫者”与“保存被呼叫者”这两个术语:从两种不同的角度(呼叫者和被呼叫者)进行思考是令人困惑的,并且错误地暗示每个寄存器确实在每次call 都保存在某个位置。 而且,名称之间仅相差1个字母,因此在阅读时在视觉上不是很明显。

“保留”或“断断续续”很棒; 他们从任何一个角度工作。 (被呼叫者将对您的注册表执行的操作,或者被允许对呼叫者的注册表执行的操作。)此外,它们是不言自明的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM