我正在学习 x86 汇编,想知道是否有人可以帮助我理解为什么文档告诉我的事情与我在实践中看到的完全不同?
为了调用系统调用,我使用int 80h
软件中断。我将参数放在、、寄存器中的前 3 个寄存器中,rbx
并将rcx
系统rdx
调用的编号放在中rax
。这样就可以了,例如,读取系统调用可以工作,我可以看到数据进入内存中的所需位置。但是,如果我读取man syscall
它说我应该将系统调用的参数放在 rdi
、、、、中,按照rsi
x86_64的 1-6 顺序排列。rdx
这样做不起作用也似乎有点疯狂,我在网上看到一些资源建议对系统调用参数使用相同的寄存器。这只是文档中的错误吗?r10
r8
r9
同样的问题是关于系统调用号。网上有人建议看一下,/usr/include/x86_64-linux-gnu/asm/unistd_64.h
但那里的读取号是 0,而且不起作用,使用 3 则如书中建议的那样有效,这是为什么呢?
答案1
好的,我明白了。我会在这里发布答案,以防有人在阅读 Jeff Duntemann 的 Assembly 书籍时遇到类似的问题。
因此,即使您可以使用 NASM 将汇编转换为 64 位,但特定指令int 080h
似乎以某种方式调用了 32 位模式。不确定 R 寄存器如何在 32 位模式下使用,但显然它们可以或其他机制将其解释为 32 位程序。这就是为什么系统调用号完全不同(它们列在 中/usr/include/x86_64-linux-gnu/asm/unistd_32.h
)。因此程序退出在 32 位中是 #1,在 64 位中是 #60。
应该使用syscall
不带任何参数的指令。这样文档中的所有内容都是正确且有效的。从 a、b、c、d 开始的 strand 命名约定很奇怪,但可以解释一下。rdi
,,是寄存器rsi
6-5-4 rdx
,所以基本上是反向顺序,寄存器rcx
在系统调用后被销毁(文档中也是这么说的r11
),因此它被替换r10
,然后从头开始使用其他 R 寄存器。