Системный вызов в Linux
Небольшая справка по реализации системного вызова на разных платформах в Linux.
Aссемблерная инструкция
- intel x86 int $0x80
- intel x86-64 syscall
- armv71 svc 0x0
Номер вызова
- intel x86 регистр EAX
- intel x86-64 регистр RAX
- armv71 регистр r7
Передача параметров
Менее 6 параметров:- intel x86 регистры EBX, ECX, EDX, ESI, EDI, EBP
- intel x86-64 регистры RDI, RSI, RDX, R10, R8, R9
- armv71 регистры r0, r1, r2, r3, r4, r5, r6
- intel x86 указатель на область памяти через регистр EBX
- intel x86-64 запрещено
Возврат результата
- intel x86 регистр EAX
- intel x86-64 регистр RAX
- armv71 регистр r0
Примеры
Реализация на C:
#include <sys/syscall.h>
int main(void)
{
syscall(SYS_write, 1, "Hello, world\n", 14);
return 0;
}
intel x86:
#include <asm/unistd.h>
#include <syscall.h>
.global _start
.text
message:
.string "Hello, world\n"
_start:
# syscall SYS_write
mov $SYS_write, %eax
mov $1, %ebx # stdout
mov $message, %ecx
mov $14, %edx # length
int $0x80
# exit 0
mov $SYS_exit, %eax
mov $0, %ebx
int $0x80
intel x86-64:
#include <asm/unistd.h>
#include <syscall.h>
.global _start
.text
message:
.string "Hello, world\n"
_start:
# syscall SYS_write
movl $SYS_write, %eax
movl $1, %edi # stdout
movl $message, %esi
movl $14, %edx # length
syscall
# exit 0
movl $0, %edi
movl $SYS_exit, %eax
syscall
armv71:
message:
.ascii "Hello, world\012\000"
.text
.align 2
.global _start
_start:
mov r7, #4
mov r0, #1
movw r1, #:lower16:message
movt r1, #:upper16:message
movl r2, #14
svc 0x0
# exit 0
mov r7, #1
mov r0, #0
svc 0x0
Для компиляции
$ gcc -c -o hello.o hello.S
$ ld -o hello hello.o