为什么 BSD 系统在执行系统调用时需要 sub esp,4?
Why do BSD systems need to sub esp,4 when performing a system call?
我正在 OS X(32 位)上执行系统调用,如下所示:
push 123
mov eax, 1
sub esp, 4
int 0x80
而且我不太明白 sub esp, 4
差距。
我在某处读到说 BSD 及其衍生产品总是有这个差距,但找不到原因的解释。
我的第一个想法是堆栈对齐,但事实并非如此,因为随处可见该行,而且据我所知OS X 需要 16 字节堆栈对齐(这不是'这里也不是这种情况)。
您知道需要做什么的背后隐藏着什么吗?sub esp, 4
或者可以为我指出正确描述它的资源吗?
(社区维基因为我只是总结评论)
BSD 这样做是为了使系统调用的 libc 包装函数更高效,因为它们可以只执行 int 0x80
而无需复制参数。它为 CALL 推送到包装函数的 return 地址留出了空间。
在 Unix/Linux 系统中,像 read(2)
这样的系统调用实际上是围绕内核调用的库包装函数,而不是扩展为内联 asm 的宏。
Linux 以不同的方式解决了这个问题:通过在寄存器中传递所有系统调用参数。我想这意味着 32 位包装函数必须从堆栈加载所有 args,但至少它们不必由内核存储和重新读取。
x86-64 系统调用 ABI 与函数调用约定更加兼容:只需要一个 mov r10, rcx
,因为 System V 函数调用约定在寄存器中传递参数(以及系统调用寄存器被选择尽可能匹配它,除了 the SYSCALL instruction itself destroys RCX and R11, so the kernel can't see the original values.)
请参阅 x86 标签 wiki,了解有关实际调用约定的更多信息,以及指向 ABI 的链接。
我正在 OS X(32 位)上执行系统调用,如下所示:
push 123
mov eax, 1
sub esp, 4
int 0x80
而且我不太明白 sub esp, 4
差距。
我在某处读到说 BSD 及其衍生产品总是有这个差距,但找不到原因的解释。
我的第一个想法是堆栈对齐,但事实并非如此,因为随处可见该行,而且据我所知OS X 需要 16 字节堆栈对齐(这不是'这里也不是这种情况)。
您知道需要做什么的背后隐藏着什么吗?sub esp, 4
或者可以为我指出正确描述它的资源吗?
(社区维基因为我只是总结评论)
BSD 这样做是为了使系统调用的 libc 包装函数更高效,因为它们可以只执行 int 0x80
而无需复制参数。它为 CALL 推送到包装函数的 return 地址留出了空间。
在 Unix/Linux 系统中,像 read(2)
这样的系统调用实际上是围绕内核调用的库包装函数,而不是扩展为内联 asm 的宏。
Linux 以不同的方式解决了这个问题:通过在寄存器中传递所有系统调用参数。我想这意味着 32 位包装函数必须从堆栈加载所有 args,但至少它们不必由内核存储和重新读取。
x86-64 系统调用 ABI 与函数调用约定更加兼容:只需要一个 mov r10, rcx
,因为 System V 函数调用约定在寄存器中传递参数(以及系统调用寄存器被选择尽可能匹配它,除了 the SYSCALL instruction itself destroys RCX and R11, so the kernel can't see the original values.)
请参阅 x86 标签 wiki,了解有关实际调用约定的更多信息,以及指向 ABI 的链接。