Aller au contenu principal
Aller au contenu principal
← retour au blog

Les appels système (syscalls) sous Linux en assembleur x86-64

Convention de registres System V ABI, tableau des numéros et Hello World autonome sans libc en assembleur x86-64.

Écrire en assembleur x86-64 sur GNU/Linux implique de dialoguer directement avec le noyau via des appels système (syscalls), sans passer par la bibliothèque C standard (libc).

Chaque appel système possède un numéro unique placé dans le registre rax, des arguments transmis dans un ordre strict via des registres dédiés, puis l'instruction syscall déclenche la transition vers l'espace noyau.

La convention d'appel System V AMD64 ABI

Sous Linux 64 bits (x86-64), la convention de passage des registres pour un appel système est la suivante :

Rôle Registre Description
Numéro du syscall rax Identifiant de la fonction noyau à exécuter
Argument 1 rdi Premier argument
Argument 2 rsi Deuxième argument
Argument 3 rdx Troisième argument
Argument 4 r10 Quatrième argument (attention : rcx en fonction standard C, mais r10 pour syscall)
Argument 5 r8 Cinquième argument
Argument 6 r9 Sixième argument
Valeur de retour rax Résultat de l'opération (si négatif entre -1 et -4095, il s'agit de -errno)

Attention aux registres écrasés : L'instruction processeur syscall modifie systématiquement les registres rcx (qui sauvegarde l'adresse de retour RIP) et r11 (qui sauvegarde les drapeaux RFLAGS).

Tableau des principaux appels système x86-64

%rax Nom du Syscall %rdi (arg1) %rsi (arg2) %rdx (arg3) %r10 (arg4) %r8 (arg5) Description
0 sys_read fd buf count - - Lit des octets depuis un descripteur de fichier
1 sys_write fd buf count - - Écrit des octets vers un descripteur de fichier
2 sys_open filename flags mode - - Ouvre un fichier et retourne un descripteur
3 sys_close fd - - - - Ferme un descripteur de fichier ouvert
4 sys_stat filename statbuf - - - Récupère les métadonnées d'un fichier par son chemin
5 sys_fstat fd statbuf - - - Récupère les métadonnées d'un fichier par son fd
8 sys_lseek fd offset whence - - Déplace le curseur de lecture/écriture
9 sys_mmap addr length prot flags fd Mappe des fichiers ou de la mémoire anonyme
10 sys_mprotect addr length prot - - Modifie les permissions d'une zone mémoire
11 sys_munmap addr length - - - Libère une zone mémoire mappée
12 sys_brk brk - - - - Ajuste la fin du segment de données (heap)
39 sys_getpid - - - - - Retourne le PID du processus courant
41 sys_socket family type protocol - - Crée un point de communication réseau
42 sys_connect fd uservaddr addrlen - - Établit une connexion vers une adresse distante
43 sys_accept fd upeer_sockaddr upeer_addrlen - - Accepte une connexion réseau entrante
57 sys_fork - - - - - Crée un nouveau processus fils
59 sys_execve filename argv envp - - Exécute un nouveau programme
60 sys_exit error_code - - - - Termine immédiatement le processus
62 sys_kill pid sig - - - Envoie un signal à un processus

Exemple complet : Hello World sans libc en NASM

Voici un exemple minimaliste et autonome qui n'utilise aucune bibliothèque externe :

section .data
    msg db "Bonjour le monde en assembleur x86-64 !", 0x0A
    len equ $ - msg

section .text
    global _start

_start:
    ; 1. Appel sys_write (rax = 1, rdi = 1 (stdout), rsi = msg, rdx = len)
    mov rax, 1          ; Numéro du syscall sys_write
    mov rdi, 1          ; Descripteur de fichier : 1 = stdout
    mov rsi, msg        ; Pointeur vers la chaîne
    mov rdx, len        ; Longueur du message
    syscall             ; Déclenche l'appel système

    ; 2. Appel sys_exit (rax = 60, rdi = 0 (code de retour succès))
    mov rax, 60         ; Numéro du syscall sys_exit
    xor rdi, rdi        ; Code de retour 0
    syscall

Compilation et exécution :

# Assembler le fichier objet en 64 bits ELF
nasm -f elf64 hello.asm -o hello.o

# Lier le binaire sans libc
ld hello.o -o hello

# Exécuter
./hello

En résumé

  • Sous Linux x86-64, le numéro de syscall va toujours dans rax et l'exécution se déclenche avec syscall.
  • La convention passe les arguments dans l'ordre : rdi, rsi, rdx, r10, r8, r9.
  • La valeur de retour est renvoyée dans rax (les codes d'erreurs étant négatifs entre -1 et -4095) ;)