Langage d'assemblage - Registres
Un registre est une unité de stockage à grande vitesse à l'intérieur du CPU, et est l'objet le plus fréquemment manipulé en programmation en assembleur. Comprendre les registres est la première étape clé pour bien apprendre le langage d'assemblage.
Qu'est-ce qu'un registre
Les registres sont intégrés à l'intérieur de la puce du CPUStockage mémoire petit et ultra-rapide, utilisés pour stocker temporairement des instructions, des données et des adresses.
Contrairement à la mémoire, les registres sont intégrés dans le CPU. Le CPU peut accéder aux registres avec une latence quasi nulle, tandis que l'accès à la mémoire nécessite des dizaines à des centaines de cycles d'horloge.
En langage d'assemblage, la grande majorité des opérations tournent autour des registres—les données sont chargées depuis la mémoire vers les registres, les opérations sont effectuées dans les registres, puis les résultats sont stockés à nouveau en mémoire.
Vous pouvez considérer les registres comme l'« établi » du CPU. Les outils sur l'établi sont disponibles à tout moment, tandis que la mémoire est comme un entrepôt vers lequel vous devez vous déplacer pour aller chercher et ranger des éléments.
Classification des registres x86 32 bits
L'architecture x86 32 bits fournit de nombreux types de registres, chacun ayant des usages différents. La figure suivante montre la classification complète des registres :
Ci-dessous, nous présentons en détail chaque type de registre :
Registres à usage général
Registres à usage généralCe sont les registres les plus couramment utilisés, servant à stocker des données d'opération et des résultats temporaires.
x86 fournit 8 registres généraux de 32 bits :
| 32 bits | 16 bits | 8 bits de poids faible | 8 bits de poids fort (des 16 bits de poids faible) | Objectif principal |
|---|---|---|---|---|
| EAX | AX | AL | AH | Accumulateur, stocke les valeurs de retour de fonction et les résultats des opérations arithmétiques |
| EBX | BX | BL | BH | Registre de base, souvent utilisé pour stocker les adresses de base mémoire |
| ECX | CX | CL | CH | Compteur, souvent utilisé pour le comptage de boucles et les décalages |
| EDX | DX | DL | DH | Registre de données, stocke les résultats de poids fort de la multiplication et de la division |
| ESI | SI | SIL | - | Registre d'index source, adresse source pour les opérations sur les chaînes |
| EDI | DI | DIL | - | Registre d'index de destination, adresse de destination pour les opérations sur chaînes |
| EBP | BP | BPL | - | Pointeur de base, pointe vers le bas du cadre de pile actuel |
| ESP | SP | SPL | - | Pointeur de pile, pointe toujours vers le sommet de la pile |
Convention de nommage : le préfixe E signifie Extended (étendu à 32 bits), et le suffixe X indique qu'il peut être divisé en octets haut et bas.
Exemple
; Démontrer l'accès aux différentes parties des registres
section .text
global _start
_start:
mov eax, 0x12345678 ; Registre 32 bits complet
; À ce stade : EAX = 0x12345678
; AX = 0x5678 (16 bits de poids faible)
; AH = 0x56 (8 bits de poids fort, c.-à-d. les 8 bits de poids fort de AX)
; AL = 0x78 (8 bits de poids faible)
mov ax, 0xAABB ; Modifier AX (16 bits de poids faible)
; À ce stade : EAX = 0x1234AABB (les 16 bits de poids fort restent inchangés !)
; AX = 0xAABB
; AL = 0xBB
mov al, 0xCC ; Modifier AL (les 8 bits les moins significatifs)
; À ce stade : EAX = 0x1234AACC (seuls les 8 bits de poids faible ont changé)
; AX = 0xAACC
; AL = 0xCC
mov eax, 1
mov ebx, 0
int 0x80
Lors de la modification des 16 bits de poids faible d'un registre 32 bits (tel que AX), les 16 bits de poids fort restent inchangés. Cependant, lorsqu'un registre 32 bits est utilisé comme opérande de destination, les 32 bits entiers sont écrasés. C'est une source fréquente d'erreurs pour les débutants.
Registres de segment
Les registres de segment servent à spécifier le segment de mémoire utilisé actuellement :
| Registre | Name | Objectif |
|---|---|---|
| CS | Registre de segment de code | Pointe vers le segment où se trouve l'instruction en cours |
| DS | Registre de segment de données | Pointe vers le segment où se trouvent les données |
| SS | Registre de segment de pile | Pointe vers le segment où se trouve la pile |
| ES | Registre de segment supplémentaire | Segment de données supplémentaire |
| FS | Registre de segment supplémentaire | Usage général, souvent utilisé pour le stockage local au thread |
| GS | Registre de segment supplémentaire | À usage général, couramment utilisé pour le stockage local au thread |
Lors de la programmation en mode protégé 32 bits, le système d'exploitation a déjà configuré les registres de segment, donc vous n'avez généralement pas besoin de les modifier manuellement.
Registres de pointeur et d'index
Ces registres sont principalement utilisés pour accéder à la mémoire et stocker des adresses mémoire :
| Registre | Nom complet | Objectif |
|---|---|---|
| EIP | Pointeur d'instruction | Pointe vers l'adresse de la prochaine instruction à exécuter par le CPU (non directement accessible) |
| ESP | Pointeur de pile | Pointe vers le sommet de la pile ; les instructions PUSH/POP l'ajustent automatiquement |
| EBP | Pointeur de base | Pointe vers le bas du cadre de pile de la fonction courante, utilisé pour accéder aux paramètres de fonction et aux variables locales |
| ESI | Index source | Adresse source pour les opérations sur chaînes/mémoire |
| EDI | Index destination | Adresse de destination pour les opérations sur chaînes/mémoire |
ESP et EBP ne peuvent pas être utilisés librement comme des registres généraux ordinaires. ESP pointe vers le sommet de la pile, et push/pop/call/ret le modifient tous ; EBP est essentiel pour accéder aux paramètres de fonction. Les modifier arbitrairement fera planter le programme.
Registre des drapeaux (EFLAGS)
EFLAGSIl s'agit d'un registre de 32 bits, chaque bit représente un drapeau d'état.
Vous ne pouvez pas lire ou écrire directement l'intégralité du registre EFLAGS, mais le CPU met automatiquement à jour ces bits de drapeau en fonction des résultats des opérations, et les instructions de saut conditionnel les utilisent pour décider si elles doivent sauter.
| Bit de drapeau | Name | Signification |
|---|---|---|
| CF | Drapeau de retenue | Mis à 1 lorsque l'arithmétique non signée produit une retenue/un emprunt |
| PF | Indicateur de parité | Mis à 1 lorsque le nombre de 1 dans les 8 bits de poids faible du résultat est pair |
| AF | Indicateur de retenue auxiliaire | Mis à 1 lorsqu'il y a une retenue/un emprunt des 4 bits de poids faible vers les 4 bits de poids fort |
| ZF | Indicateur zéro | Mis à 1 lorsque le résultat de l'opération est 0 |
| SF | Indicateur de signe | Mis à 1 lorsque le résultat de l'opération est négatif (égal au bit de poids fort du résultat) |
| OF | Indicateur de débordement | Mis à 1 lorsque l'arithmétique signée produit un débordement |
Exemple
; Illustre l'effet de l'arithmétique sur les bits d'indicateur
section .text
global _start
_start:
mov eax, 10
sub eax, 10 ; 10 - 10 = 0
; ZF = 1 (le résultat est zéro)
; SF = 0 (le résultat est non négatif)
; CF = 0 (pas d'emprunt)
mov eax, 0xFFFFFFFF
add eax, 1 ; 0xFFFFFFFF + 1 = 0x100000000 (dépasse 32 bits)
; ZF = 1 (le résultat sur 32 bits est 0)
; CF = 1 (retenue générée)
; OF = 0 (pas de débordement du point de vue signé)
mov eax, 1
mov ebx, 0
int 0x80
Conventions d'utilisation des registres
En programmation réelle, certains registres ont des usages conventionnels — appelésConvention d'appel:
| Registre | Rôle dans la convention d'appel |
|---|---|
| EAX | Stocker la valeur de retour de la fonction |
| ECX | Compteur (nombre de boucles) |
| EDX | Stocker la partie haute des résultats de division, étendre EAX |
| EBX、ESI、EDI、EBP | Sauvegardés par l'appelé : la fonction appelée doit les sauvegarder et les restaurer |
| EAX、ECX、EDX | Sauvegardés par l'appelant : l'appelant est responsable de la sauvegarde |
Autres extensionsLorsque vous écrivez vos propres programmes en assembleur, vous n'êtes pas obligé de suivre strictement la convention d'appel. Mais si vous mélangez avec du C, vous devez suivre la convention d'appel cdecl.