【发布时间】:2013-03-13 23:36:18
【问题描述】:
从 MS‑DOS 开始,我就知道使用中断进行系统调用。在旧论文中,我看到引用 int 80h 在 Linux 上调用系统函数。很长一段时间以来,我知道 int 80h 已被弃用,取而代之的是 syscall 指令。但我无法让它在我的 32 位机器上运行。
问题
syscall 指令是否只能在 64 位平台上使用? 32位Linux不使用syscall吗?
样本测试
在我的 32 位 Linux (Ubuntu Precise) 上,该程序以核心转储终止:
global _start
_start:
mov eax, 4 ; 4 is write
mov ebx, 1 ; 1 is stdout
mov ecx, message ; address of string
mov edx, length ; number of bytes
syscall
mov eax, 1 ; 1 is exit
xor ebx, ebx ; return code 0
syscall
message:
db 10,"Hello, World",10,10
length equ $ - message
我尝试使用 sysenter 而不是 syscall,但它以同样的方式崩溃。
【问题讨论】:
-
确实有一些相关的东西,here,但它没有回答这个问题。他说
syscall在 Intel CPU 的 32 位模式下不可用,但汇编程序以 32 位模式编译它;断言要么不清楚,要么是错误的。然后,由于一条非法指令,我得到了核心转储,但这条指令在从 Pentium II 开始的所有 Intel CPU 上都可用,而我的远不止于此。他提到了sysenter,我尝试了同样的结果。无论如何,我从未在 Linux ABI 中看到任何提及sysenter,只有int 80h或syscall。 -
嗯,根据“System Calls (wiki.osdev.org)”,
syscall相当于 AMD 的 Intelsysenter。它说“在 Intel CPU 上,从 Pentium II 开始,出现了一个新的指令对 sysenter/sysexit。通过限制更改模式的开销,它可以更快地从用户模式切换到内核模式。 AMD 创建了一个类似的指令对:Syscall/Sysret。但是这些指令的行为与 Intel 的不同。” -
供参考,int 0x80 一直是 Linux 的东西。 Windows 和 MS-DOS 使用 int 0x2E
-
对于操作系统内核开发人员的建议是二选一。然后他们的选择成为 ABI 的一部分,如果您正在为某个操作系统开发,您必须尊重该 ABI。例如,Linux/i386 使用 int 0x80 并在寄存器中传递参数,而 MirBSD/i386 使用 int 0x80 并在堆栈上传递参数,中间有一个帧指针(这意味着使用 cdecl 时用户空间没有设置成本)。跨度>
标签: linux assembly 32-bit system-calls sysenter