Linux x64:为什么r10来自系统调用中的r8和r9?

Mon*_*n45 6 linux 64-bit assembly

前几天我决定在组装时采取行动,我一直在玩基本的东西,比如从argv到stdout的打印.我找到了这个带有参数和所有内容的linux系统调用号码的绝佳列表,我很好奇为什么r10之前r8和之前用于参数r9.我已经找到各种奇怪的约定,关于什么可以用于什么和何时,如循环计数器如何进入rcx.有什么特别的原因r10被提升了吗?它更方便吗?

我可能也应该提到我出于好奇而对此感兴趣,而不是因为它引起了我的问题.

编辑:我发现这个问题很接近,引用第124页的x64 ABI文档,其中注意到用户级应用程序使用的问题rdi, rsi, rdx, rcx, r8, r9.另一方面,内核使用r10而不是rcx破坏rcxr11.这可能解释了如何r10在那里结束,但那么为什么要交换呢?

Rus*_*lan 6

RCX与指令一起使用R11,被syscall指令立即销毁.因此,这些寄存器不仅不会在系统调用之后保存,而且甚至不能用于参数传递.因此R10选择替换不可RCX用以传递第四个参数.

有关如何使用这些寄存器的更多信息,请参见此答案syscall.

参考:英特尔指令集参考,寻找SYSCALL.


Jam*_*mes 2

请参阅x86-64.orgs abi 文档 page 124

  1. 用户级应用程序用作整数寄存器来传递序列 %rdi、%rsi、%rdx、%rcx、%r8 和 %r9。内核接口使用%rdi、%rsi、%rdx、%r10、%r8 和%r9。

  2. 系统调用是通过 syscall 指令完成的。内核销毁寄存器%rcx 和%r11。

这就是说,当您使用系统调用指令时,内核会破坏,%rcx因此您需要使用%r10它。


@technosaurus 的评论还解释说,内核用于%rcx存储入口点,以防系统调用期间发生中断。