[英]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
内联memset
或memcpy
,或者库实现使用了它。
(说RDI 本质上是调用集群的,这是没有道理的,x86-64 ISA并未对此进行定义。这取决于每个平台来选择。)
术语:
我讨厌“保存呼叫者”与“保存被呼叫者”这两个术语:从两种不同的角度(呼叫者和被呼叫者)进行思考是令人困惑的,并且错误地暗示每个寄存器确实在每次call
中都保存在某个位置。 而且,名称之间仅相差1个字母,因此在阅读时在视觉上不是很明显。
“保留”或“断断续续”很棒; 他们从任何一个角度工作。 (被呼叫者将对您的注册表执行的操作,或者被允许对呼叫者的注册表执行的操作。)此外,它们是不言自明的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.