Eva*_*oll 3 linux kernel conventions assembly
我知道有一个syscall
约定,但是您在调用之前看到的调用约定是什么,int 80
而不是syscall
像这样调用。
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
Run Code Online (Sandbox Code Playgroud)
我在这里读到后面的参数rdx
是esi
, edi
, ebp
(或对于 x64 rsi
, rdi
, rbp
),我没有看到它记录在Wikipedia 的调用约定页面中,但是int80h似乎表明 Windows 也使用这个约定?
这是什么约定俗成的名字。我可以在 Linux 内核源代码中的哪个位置看到它的定义?并且,rax
当您调用时解析为过程的表在哪里int 0x80
?对于syscall
,sys_write
是rax=1
您的问题涵盖了许多主题,我将尽力解决所有问题。
我不确定系统调用的调用方式是否有一个单一的规范术语,对于调用系统调用的特定方式(中断 0x80 而不是SYSENTER
或SYSCALL
)更不用说。在X86-64,该文件系统调用接口,使用SYSCALL
,在系统V X86-64 ABI描述,但是这仅提供信息,不规范。同样,如果您将其称为“i386 Linux 内核 ABI”(将“i386”替换为您所谈论的任何架构),虽然大多数人会理解您在说什么,但这也可能会令人困惑,因为“内核 ABI”有另一个含义(在内核模块的上下文中),并且同样不限于中断 0x80。
在实践中,大多数人无论如何都不应该关注这种细节级别的细节,特别是因为它们可以进化:SYSCALL
如您所提到的中断 0x80等,但还有引入其自身微妙之处并且是首选入口点的 vDSO对于现在 x86 上的所有系统调用......当然,这并不意味着不能有一个术语来指代特定的调用约定,但我不确定它是否有用。
Windows 也支持为其系统调用接口 0x2E 使用中断,但它的“调用约定”完全不同:参数被压入堆栈,请求的系统调用由 EAX 给出,EBX 指向堆栈上的参数。
当前的 x86 内核定义了以下系统调用接口arch/x86/entry
:entry_32.S
包含 i386 接口、entry_64.S
x86-32 和 x86-64 接口、entry_64_compat.S
32 位 x86-64 接口(为了向后兼容)、syscalls/syscall_32.tbl
i386 系统调用表、syscalls/syscall_64.tbl
x86-32 和x86-64 系统调用表。
这些文件中的注释记录了接口,特别是如何传递参数:对于 32 位调用,EAX 包含系统调用号,其参数放置在 EBX、ECX、EDX、ESI、EDI 和 EBP(参数本身 for SYSENTER
,指向包含中断 0x80 参数的用户堆栈的指针);对于 64 位调用,RAX 包含系统调用号,其参数放置在 RDI、RSI、RDX、R10、R8 和 R9(另请参阅为什么系统调用寄存器和顺序从 Intel 32bit 更改为 64bit?) . 有一个很好的总结,里面有图表calling.h
。
作为旁注,历史比较通常是指主要使用中断 0x21的 MS-DOS 调用接口;它还包括多路中断0x2F,它提供了一种用于添加系统服务的可扩展机制(通常涉及 TSR;设备驱动程序大多使用不同的接口)。