为什么系统调用寄存器和顺序从Intel 32位变为64位?

为什么系统调用寄存器和顺序从Intel 32位变为64位?

我正在努力记住 Linux 系统调用的顺序,以便我可以更轻松地识别这一点。然后我发现这篇论文在这里,它说,

要在 32 位 Linux 中进行系统调用,请将系统调用号放入 中eax,然后将其参数按顺序放入ebxecxedxesiedi和 中ebp,然后调用 int 0x80。

进而,

要在 64 位 Linux 中进行系统调用,请将系统调用号放入 中rax,然后将其参数按顺序放入rdirsirdxr10r8和 中r9,然后调用 syscall。

为什么 64 位和 32 位之间的顺序会如此混乱?我知道这个问题可能是历史性的而不是技术性的。

这完全是内核决定的吧?是否有技术原因支持新的约定?

答案1

这很大程度上取决于内核,但是在 64 位 x86 上使用所选的调用约定有一个很好的理由:它与所选的用户空间约定相匹配。 Linux 使用的 System V x86-64 ABI,指定该函数使用寄存器%rdi%rsi%rdx%rcx%r8%r9来传递参数。系统调用约定与此非常接近:唯一的区别是它使用%r10代替%rcx,主要是因为SYSCALL用于调用系统调用的新 64 位指令需要%rcx用于其他目的。

答案2

编译代码中的寄存器顺序是Linux的一种调用约定,以方便生成和调试代码。

amd-64 架构比 32 位架构拥有更多的寄存器,并且使用新的调用约定来释放其他寄存器,以更好地优化代码。

如果您反汇编两种架构之间的代码,您还会注意到,在 amd-64 中,您经常会看到更多寄存器取代了函数中的局部整数变量。如果我没记错的话,rebp 用于优化在从函数返回之前使用局部变量堆栈生成的代码。

相关内容