是否保存了rdi和rsi调用者或被调用者保存的寄存器?

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

从维基百科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)

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

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

assembly x86-64 nasm calling-convention
1个回答
2
投票

是的,在我所知道的所有函数调用约定中,arg传递寄存器是call-clobbered。 (除了系统调用约定,通常所有的reg都被保留,除了返回值,包括arg传递。除了x86-64 syscall破坏RCX和R11 ......)

特别是在x86-64 System V中,除RBX,RBP,RSP和R12-R15之外的所有寄存器都被调用破坏。 (包括xmm0-15,x87 / mmx寄存器和AVX512 zmm0-31和k0-k7掩码寄存器。)

What registers are preserved through a linux x86-64 function call显示了ABI文档中的表格。


调用约定/ ABI将寄存器的状态定义为call-preserved或call-clobbered。不同的约定可以做出不同的选择

是的,Microsoft Windows从其他所有人那里选择了不同的调用约定:Why does Windows64 use a different calling convention from all other OSes on x86-64?在Windows x64中,RDI是调用保留的,就像在大多数32位调用约定中一样。

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

(没有必要说RDI本质上是调用破坏的,x86-64 ISA没有定义它。由每个平台来决定。)


术语:

我讨厌“调用者保存”与“被调用者保存”术语:从2个不同的角度(调用者和被调用者)进行思考是令人困惑的,并且错误地暗示每个寄存器确实在每个call上保存。此外,名称仅相差1个字母,因此在阅读时视觉上并不十分明显。

“保存”或“破坏”是伟大的;他们从任何角度工作。 (被调用者将对您的注册表做什么,或者您允许对调用者的注册表执行什么操作。)此外,它们是不言自明的。

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