
Я знаю, что есть 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
Я читаюздесьчто аргументы после rdx
, esi
, edi
( ebp
или для x64 rsi
, rdi
, rbp
), я не вижу, чтобы это было задокументировано вСтраница Википедии о соглашениях по вызову, ноint80hпохоже, это указывает на то, что Windows также использует это соглашение?
Как это условно названо. Где в исходном коде ядра Linux я могу увидеть его определение? И где находится таблица, которая разрешается rax
в процедуры, когда вы вызываете int 0x80
? Для syscall
, sys_write
этоrax=1
решение1
Ваш вопрос охватывает ряд тем, и я постараюсь рассмотреть их все.
Я не уверен, что существует единый канонический термин для способа, которым вызываются системные вызовы, и еще меньше для конкретного способа, которым вызываются системные вызовы (прерывание 0x80 в отличие от
SYSENTER
илиSYSCALL
). На x86-64,задокументированоинтерфейс системного вызова, использующийSYSCALL
, описан в System V x86-64 ABI, но это только информативно, а не нормативно. Аналогично, хотя большинство людей поймут, о чем вы говорите, если вы назовете это «i386 Linux kernel ABI» (заменив «i386» на любую архитектуру, о которой вы говорите), это тоже может сбивать с толку, поскольку «kernel ABI» имеет другое значение (в контексте модулей ядра), и опять же, это не ограничивается прерыванием 0x80.На практике большинство людей вообще не должны беспокоиться о деталях вплоть до этого уровня детализации, особенно с учетом того, что они могут развиваться: прерывание 0x80
SYSCALL
и т. д., как вы упомянули, а также 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 (сам параметр для
SYSENTER
, указатель на пользовательский стек, содержащий параметр для прерывания 0x80); для 64-битных вызовов RAX содержит номер системного вызова, а его параметры помещаются в RDI, RSI, RDX, R10, R8 и R9 (см. такжеПочему регистры и порядок системных вызовов изменились с Intel 32bit на 64bit?). Есть хорошее резюме с диаграммами вcalling.h
.
В качестве примечания: исторические сравнения часто ссылаются на интерфейс вызова MS-DOS, который в основном использовалсяпрерывание 0x21; он также включал в себя мультиплексное прерывание,0x2F, который предоставилрасширяемый механизмдля добавления системных служб (обычно с использованием TSR; драйверы устройств в основном использовали другой интерфейс).