“int 0x80”背后的调用约定是什么?

“int 0x80”背后的调用约定是什么?

我知道有一个约定,但是当您调用 to而不是 时syscall,您将其前面的调用约定称为什么,就像这样。int 80syscall

mov  rax,4     ; system call number (sys_write)
mov  rbx,1     ; file descriptor (stdout)
mov  rcx,hello ; message to write
mov  rdx,12    ; message length
int  0x80      ; call kernel

我读这里之后的参数rdxesi, edi, ebp(或对于 x64 rsi, rdi, rbp),我没有看到它记录在维基百科的调用约定页面, 但整数80小时似乎表明 Windows 也使用此约定?

这个约定叫什么名字。在 Linux 内核源代码中的哪里可以看到它的定义?并且,rax当您调用时解析过程的表在哪里int 0x80?对于syscallsys_writerax=1

答案1

您的问题涵盖了很多主题,我将尽力解决所有主题。

  1. 我不确定调用系统调用的方式有一个单一的规范术语,更不用说调用系统调用的特定方式(中断 0x80 而不是SYSENTERor SYSCALL)。在 x86-64 上,记录在案System V x86-64 ABI 中描述了使用 的系统调用接口SYSCALL,但这只是提供信息,而不是规范性的。同样,虽然如果您将其称为“i386 Linux 内核 ABI”(用您正在谈论的任何架构替换“i386”),大多数人都会理解您在说什么,但这也可能会令人困惑,因为“内核 ABI”有另一个含义(在内核模块的上下文中),并且这不仅限于中断 0x80。

    在实践中,大多数人无论如何都不应该关心这种细节级别的细节,特别是因为它们可以演变:中断 0x80SYSCALL等,正如您提到的,而且 vDSO 也引入了自己的微妙之处,并且是首选的入口点对于现在 x86 上的所有系统调用...当然,这并不意味着不能有一个术语来指代特定的调用约定,但我不确定它是否会有那么有用。

  2. Windows 还支持使用中断作为其系统调用接口 0x2E,但其“调用约定”是很不一样:参数被压入堆栈,请求的系统调用由EAX给出,EBX指向堆栈上的参数。

  3. 当前的 x86 内核定义了系统调用接口arch/x86/entryentry_32.S包含 i386 接口,entry_64.Sx86-32 和 x86-64 接口,entry_64_compat.S32 位 x86-64 接口(用于向后兼容),syscalls/syscall_32.tbli386系统调用表,syscalls/syscall_64.tblx86-32 和 x86-64 系统调用表。

    这些文件中的注释记录了接口,特别是如何传递参数:对于 32 位调用,EAX 包含系统调用号,其参数放置在 EBX、ECX、EDX、ESI、EDI 和 EBP 中(参数本身为SYSENTER,指向包含中断参数 0x80 的用户堆栈的指针);对于 64 位调用,RAX 包含系统调用号,其参数放在 RDI、RSI、RDX、R10、R8 和 R9 中(另请参阅为什么系统调用寄存器和顺序从Intel 32位变为64位?)。有一个很好的总结,里面有图表calling.h

附带说明一下,历史比较通常参考 MS-DOS 调用接口,该接口主要使用中断0x21;它还包括多路复用中断,0x2F,其中提供了可扩展的机制用于添加系统服务(通常涉及 TSR;设备驱动程序大多使用不同的接口)。

相关内容