【发布时间】:2021-10-07 16:50:43
【问题描述】:
我有一些关于 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_mkdir 3次(一个接一个),这样是否正确?
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 个参数的某个函数,(例如 ExitProcess)... 其他参数寄存器的值会保持不变吗?或者windows也会使用其他参数寄存器,我里面的值会改变?
【问题讨论】:
-
对于 Linux,这是 stackoverflow.com/questions/2535989/… 的副本。
syscall覆盖rcx和r11,并将返回值保留在rax中。所有其他寄存器,包括您传递参数的寄存器,都保持不变。 Windows 部分确实是一个单独的问题,我认为它应该在单独的帖子中。 -
请注意(再次在 Linux 上)
syscall与普通函数调用有不同的约定,其中只有rbx, rbp, rsp, r12-r15保持不变,其他所有内容都可能被覆盖。 -
@NateEldredge 但是linux部分的第二个问题呢?
-
再次阅读我上面写的内容:“所有其他寄存器,包括您传递参数的寄存器,保持不变。”因此,在您的问题 2 中,
esi将在多个系统调用中保持值0766o。 (不过,您的代码的读者可能不记得这一点,所以添加 cmets 来指出它是明智的。) -
最好在两个单独的帖子中提出两个单独的问题 -- 更适合这种问答形式。
标签: assembly x86-64 system-calls calling-convention