Retour à l'accueil

Retour des structures x86-64 : Registres et ABI MEMORY

L'article décompose les mécanismes de retour des types fondamentaux et des structures des fonctions en x86-64 selon l'ABI System V. Décrit les règles de classification INTEGER et MEMORY, l'utilisation des registres rax/rdx et de l'argument rdi caché. Exemples en assembleur sans optimisations.

x86-64 : comment retourner des structures via rax, rdx et rdi
Advertisement 728x90

Comment x86-64 retourne les valeurs selon l'ABI System V

Le compilateur x86-64 sous l'ABI System V utilise les registres rax et rdx pour renvoyer les deux premières valeurs entières. Pour les structures, des règles de classification s'appliquent : INTEGER pour les petites tailles, MEMORY pour les plus grandes. Cela détermine si la valeur est retournée directement ou via un pointeur caché passé dans rdi.

Examinons le cas de base du retour d'un int :

one_plus_one():
  mov DWORD PTR [rbp-4], 2
  mov eax, DWORD PTR [rbp-4]
  ret

La valeur est chargée dans eax (les 32 bits inférieurs de rax). De même, pour les types 64 bits, l'ensemble du registre rax est utilisé.

Google AdInline article slot

Structures petites jusqu'à 16 octets : retour par registres

Les petites structures sont renvoyées directement dans rax et rdx. Prenons une structure de 16 octets :

struct nums {
    std::int64_t first{};
    std::int64_t second{};
};
nums construct() {
    nums ret{10, 120};
    return ret;
}

Assemblage généré :

construct():
  mov QWORD PTR [rbp-16], 10
  mov QWORD PTR [rbp-8], 120
  mov rax, QWORD PTR [rbp-16]
  mov rdx, QWORD PTR [rbp-8]
  ret

Les champs sont disposés séquentiellement : first va dans rax, second dans rdx. La disposition mémoire suit l'ordre little-endian, avec la pile qui grandit vers le bas.

Google AdInline article slot
  • Classification INTEGER : jusqu’à deux champs de 64 bits tiennent dans les registres.
  • Alignement : les champs sont alignés sur des limites de 8 octets.
  • Limite : la taille totale doit être ≤16 octets pour un retour direct.

Structures grandes : argument caché dans rdi

Les structures de plus de 16 octets sont classées comme MEMORY. L'appelant alloue la mémoire et passe son adresse dans rdi comme premier argument caché.

Exemple : une structure de 32 octets :

struct many_nums {
    std::int64_t first{};
    std::int64_t second{};
    std::int64_t third{};
    std::int64_t fourth{};
};
many_nums construct_scary() {
    many_nums temp{10, 20, 30, 40};
    return temp;
}

Dans construct_scary :

Google AdInline article slot
construct_scary():
  mov QWORD PTR [rbp-8], rdi
  mov rax, QWORD PTR [rbp-8]
  mov QWORD PTR [rax], 10
  mov QWORD PTR [rax+8], 20
  mov QWORD PTR [rax+16], 30
  mov QWORD PTR [rax+24], 40
  ret

L'instruction mov rax, [rbp-8] répétée est un artefact de -O0. Le code optimisé utilise directement rdi.

Dans main :

main:
  sub rsp, 32
  lea rax, [rbp-32]
  mov rdi, rax
  call construct_scary
  ret
  • Allocation mémoire : effectuée via sub rsp, size ou sur le tas/la pile.
  • Passage d’adresse : l’adresse est passée dans rdi avant l’appel.
  • Classification MEMORY : utilisée par l’ABI System V pour les types >16 octets ou non-INTEGER.

Règles de classification des valeurs de retour

L’ABI System V définit trois catégories :

  • INTEGER : jusqu’à 16 octets, champs scalaires ou agrégés ≤2×64 bits → retournés dans rax/rdx.
  • MEMORY : >16 octets, types SSE >2×128 bits, ou non-INTEGER → argument caché rdi.
  • SSE : valeurs flottantes jusqu’à 128 bits → retournées dans xmm0 (non abordé ici).

Les compilateurs comme GCC et Clang génèrent du code selon ces règles. Utilisez -O0 en débogage pour voir clairement les étapes intermédiaires.

Points clés à retenir

  • Utilisez rax/rdx pour les retours entiers jusqu’à 16 octets.
  • Pour les types classifiés MEMORY, l’appelant fournit la mémoire via rdi.
  • L’ABI System V garantit un comportement cohérent sous Linux et macOS.
  • Les optimisations (-O2+) éliminent les instructions mov inutiles.
  • Vérifiez le code généré avec objdump -d ou Godbolt Compiler Explorer.

— Editorial Team

Advertisement 728x90

Lire ensuite