Langage d'assemblage - Syntaxe de base
Ce chapitre présente la structure de base, les règles de syntaxe et les conventions d'écriture des programmes en assembleur NASM, vous aidant à comprendre le squelette du code assembleur.
Structure de base d'un programme en assembleur
Un programme en assembleur NASM complet se compose généralement des parties suivantes :
Exemple
; Exemple de structure de base d'un programme NASM
section .data ; Section de données : stocke les données initialisées
; Définir les variables et les constantes ici
msg db 'Hello, EXAMPLE!', 0xA
len equ $ - msg
section .bss ; section BSS : stocke les données non initialisées
; Réserver de l'espace mémoire ici
buffer resb 64 ; Réserver un tampon de 64 octets
section .text ; section code : stocke les instructions exécutables
global _start
_start:
; Écrire la logique du programme ici
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
| Section | Objectif | Caractéristiques |
|---|---|---|
.data | Stocke les variables globales initialisées et les constantes | Taille et contenu déterminés au moment de la compilation, stockés dans le fichier exécutable |
.bss | Stocke les variables globales non initialisées | L'espace est alloué uniquement à l'exécution, n'occupe pas la taille du fichier exécutable |
.text | Stocke les instructions machine exécutables | En lecture seule, contient tout le code logique du programme |
Au moins
.textDes sections sont requises pour former un programme en assembleur valide. S'il n'y a pas de données, on peut omettre la.dataet.bsssection.
Format d'instruction en assembleur
Le format général de chaque instruction en assembleur est :
[标签:] 指令助记符 [操作数1 [, 操作数2 [, 操作数3]]] [; 注释]
Explication de chaque partie :
| Partie | Obligatoire ? | Description |
|---|---|---|
| Étiquette | Optional | Un nom symbolique représentant une adresse mémoire, se terminant par un deux-points |
| Mnémonique de l'instruction | Requis | Comme mov, add, sub, etc., indique au processeur ce qu'il doit faire |
| Opérande | Facultatif (certaines instructions n'ont pas d'opérande) | L'objet de données manipulé par l'instruction peut être un registre, une adresse mémoire ou une valeur immédiate |
| Commentaire | Optional | Commence par un point-virgule et continue jusqu'à la fin de la ligne |
Exemple
; Instruction seule, sans opérande
ret ; Retour d'un sous-programme
; Instruction + un seul opérande
push eax ; Empiler la valeur de eax sur la pile
inc ecx ; Ajouter 1 à ecx
; Instruction + deux opérandes (le plus courant)
mov eax, 42 ; Copier 42 dans le registre eax
add ebx, ecx ; ebx = ebx + ecx
; Avec une étiquette
loop_start: ; Étiquette : marque le début de la boucle
dec ecx ; Soustraire 1 à ecx
jnz loop_start ; Si ecx n'est pas 0, sauter en arrière vers loop_start
Conventions de commentaires
NASM utilisele point-virgule (;)pour indiquer des commentaires ; le contenu à partir du point-virgule jusqu’à la fin de la ligne est ignoré par l’assembleur.
Exemple
; Calculer la somme de deux nombres et afficher le résultat
mov eax, 10 ; Commentaire en ligne : mettre 10 dans eax
add eax, 20 ; Commentaire en ligne : ajouter 20 à eax, maintenant eax = 30
Les commentaires sont extrêmement importants dans le code assembleur. Sans commentaires, même l’auteur peut ne pas comprendre le code assembleur après quelques semaines. Prenez l’habitude d’écrire un commentaire pour chaque instruction.
Règles de nommage des identifiants
Les identifiants (étiquettes, noms de variables, noms de constantes, etc.) doivent respecter les règles suivantes :
| Règle | Description |
|---|---|
| Caractères de composition | Lettres, chiffres, trait de soulignement _, point ., point d’interrogation ?, @, $, #, etc. |
| Caractère initial | Doit commencer par une lettre, un tiret bas, un point ou un point d'interrogation ; ne peut pas commencer par un chiffre. |
| Sensibilité à la casse | Sensible à la casse par défaut (modifiable via les options de compilation) |
| Mots réservés | Ne peut pas avoir le même nom que les mnémoniques d'instruction, les noms de registres ou les mots-clés NASM. |
Exemple
my_variable: ; Commence par une lettre + un tiret bas
.loop_start: ; Commence par un point (étiquette locale)
?error_handler: ; Commence par un point d'interrogation
counter2: ; Lettre + chiffre
; Identifiants non valides (pour référence uniquement, ne pas utiliser)
; 1st_value: ; Erreur : ne peut pas commencer par un chiffre
; mov: ; Erreur : mov est un mot réservé
; my-variable: ; Erreur : le trait d'union n'est pas un caractère autorisé
Pseudo-instructions (Directives)
DirectivesSont des commandes adressées à l'assembleur, et non des instructions destinées au CPU ; elles contrôlent le processus d'assemblage et définissent des structures de données.
| Directives | Objectif | Exemple |
|---|---|---|
db | Définir un octet (1 octet) | byte_val db 0x55 |
dw | Définir un mot (2 octets) | word_val dw 0x1234 |
dd | Définir un double mot (4 octets) | dword_val dd 0x12345678 |
equ | Définir une constante | MAX_SIZE equ 256 |
resb | Réserver un espace d'octet | buffer resb 128 |
resw | Réserver un espace de mot | wbuf resw 64 |
resd | Réserver un espace de double mot | dbuf resd 32 |
%define | Constante définie par macro | %define COUNT 10 |
Conventions de casse
NASM, par défaut, pour les étiquettes et les identifiants,est sensible à la casse.:
Exemple
section .data
msg db 'EXAMPLE', 0 ; Définir la variable msg
section .text
global _start
_start:
mov eax, MSG ; Erreur : MSG et msg sont différents (sauf si le mode insensible à la casse est activé)
mov eax, msg ; Correct : msg correspond exactement à la définition
MOV EAX, 42 ; Syntaxiquement correct : les mnémoniques d'instruction sont insensibles à la casse
mov eax, 42 ; Style recommandé : utiliser des minuscules pour une meilleure lisibilité
Les mnémoniques d'instruction et les noms de registres sont insensibles à la casse (
MOV、Mov、movmême effet), mais le style recommandé est uniformément en minuscules.
Représentation numérique
NASM prend en charge la représentation numérique dans plusieurs bases :
Exemple
mov eax, 42 ; Décimal : écrire le nombre directement
mov eax, 0x2A ; Hexadécimal : préfixe 0x (style recommandé)
mov eax, 2Ah ; Hexadécimal : suffixe h
mov eax, 0o52 ; Octal : préfixe 0o
mov eax, 52o ; Octal : suffixe o
mov eax, 101010b ; Binaire : suffixe b
mov eax, 0b101010 ; Binaire : préfixe 0b
Recommandé :
0xutilisez le préfixe pour l'hexadécimal (par exemple,0x2A), il est donc moins susceptible d'être confondu avec des étiquettes.
Un exemple complet de syntaxe
Le programme suivant utilise de manière exhaustive les éléments de syntaxe ci-dessus pour calculer la somme de 1 à 10 et l'afficher :
Exemple
; Calculer 1+2+...+10 et afficher le caractère résultant
section .data
result db 0 ; Stocker le résultat du calcul (1 octet)
newline db 0xA ; Caractère de saut de ligne
section .text
global _start
_start:
; Initialiser les registres et les variables
mov ecx, 10 ; Compteur de boucle : décompte à partir de 10
mov eax, 0 ; eax stocke la somme accumulée, initialement 0
sum_loop: ; Étiquette de début de boucle
add eax, ecx ; eax = eax + ecx
dec ecx ; ecx décrémenté de 1
jnz sum_loop ; Si ecx != 0, continuer la boucle
; À ce stade, eax = 55 (10+9+...+1)
add eax, '0' ; Convertir le nombre en caractère ASCII ('0'=48, 55+48=103='g', incorrect)
; La démonstration réelle nécessite une conversion plus complexe, voir les chapitres suivants
; Ici, on affiche seulement le résultat (démonstration simplifiée)
mov [result], al ; Stocker le résultat accumulé dans result
; Quitter le programme
mov eax, 1
mov ebx, 0
int 0x80
Autres extensionsRemarque : dans l'exemple ci-dessus, ajouter directement '0' n'est correct que lorsque le nombre se trouve dans la plage 0-9. La conversion des nombres à deux chiffres ou plus sera expliquée en détail dans les chapitres suivants.