Win64 和 Linux-x86_64 调用约定未使用的寄存器修改与否

Win64 and Linux-x86_64 Calling Convention Unused registers modified or not

我有一些关于 linux-x86_64 和 win64 中调用约定的重​​要问题。 我搜索了太多地方,但我没有找到问题的答案! 我认为我的问题没有重复,所以请先阅读。

在linux-x86_64中我们使用系统调用...
linux-x86_64 系统调用调用约定为:

RDI -> first parameter
RSI -> second parameter
RDX -> third parameter
R10 -> fourth parameter
R8  -> fifth parameter
R9  -> sixth parameter
R11 -> ... (for all syscalls)
RCX -> ... (for all syscalls)
RAX -> return

现在,我关于 linux-x86_64 的问题:

问题1:如果一个系统调用(例如,'sys_write')需要3个参数(RDI,RSI,RDX),那么其他参数寄存器呢?是的,这个系统调用只有 3 个参数,但它是否也会使用其他参数寄存器(用于其他用途,如内部进程和...)?我的意思是,如果我调用 sys_write 并且我在 R10 寄存器中有一些东西,那么 R10 值在系统调用之后会保持 100% 不变吗?这个系统调用没有第四个参数,所以我认为 R10 或 R8 或 R9 中的所有内容都将保持不变……对吗?我说得对吗?

问题2:比如sys_mkdir ...如果我要调用sys_mkdir3次(一个接一个),是这样的正确吗?

mov eax, 83
mov rdi, .filename
mov esi, 0766o
syscall

mov eax, 83
mov rdi, .filename2
syscall            ; no (mov esi, 0766o) anymore because ESI is equal to 0766o from last syscall

mov eax, 83
mov rdi, .filename3
syscall            ; no (mov esi, 0766o) anymore because ESI is equal to 0766o from last syscall

在这里,我只是不再更新 ESI ... 因为我认为 syscall 保持参数寄存器不变。我说的对吗?


现在Win64,Win64调用约定为:

RCX -> first parameter
RDX -> second parameter
R8  -> third parameter
R9  -> fourth parameter
... (Stack)

问题1:这里,我关于win64调用约定的问题与第一个关于linux-x86_64的问题相同。例如,如果我只用 1 个参数调用 Some 函数,(例如 ExitProcess)...其他参数寄存器值会保持不变吗?或者 windows 也将使用其他参数寄存器并且我在其中的值会改变?

A 的注册状态 call-preserved or call-clobbered 从不依赖于调用者实际传递的参数数量 and/or 被调用者期望的,在我看过的任何 ISA 的任何调用约定中,并且当然不是 x86 上的任何标准。

但是是的,原始系统调用的调用约定与函数的调用约定不同,即使对于可能的薄包装函数也是如此。

所有标准用户-space 函数调用约定都将所有参数传递寄存器(和堆栈槽)作为调用破坏。因此,如果您的 asm 使用 call,这就是您所需要的。

主流操作系统的系统调用约定保留所有寄存器(return 值除外)。 (但在 x86-64 上,只有在 syscall 本身覆盖 RCX 和 R11 之后,。)如果你直接使用 syscallint 0x80 或其他任何东西,这就是你应该期望的.

请注意 Windows 而不是 具有跨内核版本的稳定系统调用 ABI,并且不记录原始系统调用,因此在正常情况下 Windows 代码,你总是在进行 DLL 函数调用,而不是原始系统调用。 People have reverse-engineered the system calls for different Windows versions, though.

MacOS 也官方 没有 stable/documented 系统调用 ABI,但实际上 Darwin 基本上有,至少对于正常 POSIX open/read/write/close/exit 玩具程序使用的调用。