- Le langage assembleur organise ses instructions par objectif : transfert, calcul, contrôle de flux, etc.
- Chaque instruction se compose d'un opcode et d'opérandes, avec des formats différents selon l'architecture.
- Il existe plusieurs modes d'adressage pour accéder aux données, tels que l'immédiat, le direct et l'indirect.
Le langage assembleur est l’un des piliers fondamentaux du développement logiciel depuis le début de l’informatique. Bien que les langages de haut niveau dominent la scène aujourd'hui, l'assembleur reste largement utilisé et pertinent dans les environnements où le contrôle du matériel, l'optimisation ou les contraintes de ressources sont une priorité.
Dans cet article, nous explorerons les différents types d'instructions du langage assembleur, en analysant leur structure, leur fonction, leurs modes d'adressage et leur organisation selon les architectures. Vous trouverez également des exemples, des formats et une présentation complète qui vous permettront de comprendre pleinement la logique de ces instructions, qui interagissent étroitement avec le matériel.
Qu'est-ce qu'une instruction en langage assembleur ?
Une instruction assembleur est une commande que le processeur peut directement comprendre (une fois traduite en code machine par un programme assembleur). Chaque instruction a une fonction précise et se compose généralement d'un mnémonique représentant l'opération et d'un ou plusieurs opérandes indiquant où les données sont extraites et/ou où les résultats sont stockés.
Ces instructions dépendent fortement de l'architecture du processeur, de sorte que chaque type de CPU (qu'il s'agisse de x86, ARM, MIPS, entre autres) possède son propre ensemble d'instructions avec une syntaxe et des capacités particulières.
Structure d'une instruction
Les instructions sont généralement composées de deux parties :
- Code d'opération (opcode) : Indique l'action à exécuter, comme l'ajout, le déplacement de données, la comparaison, etc.
Les opérandes fournissent les informations nécessaires à l'exécution de l'opération et peuvent être stockées dans des registres, en mémoire ou être des constantes. Toutes les instructions ne requièrent pas d'opérandes ; dans certains cas, ceux-ci peuvent être implicites dans l'instruction ou stockés dans des registres prédéfinis.
Types d'instructions en langage assembleur
Selon la fonctionnalité qu'elles exécutent dans un programme, les instructions en langage assembleur peuvent être classées en plusieurs groupes. Les plus pertinents sont détaillés ci-dessous :
1. Instructions de transfert de données
Ces instructions permettent de copier des données d'un emplacement à un autre sans en modifier le contenu à la source. Elles sont essentielles pour le transfert d'informations entre les registres, la mémoire et les périphériques.
Certaines des instructions les plus courantes dans ce groupe sont :
- MOV : Copie le contenu d'un opérande vers un autre. Par exemple,
MOV AX, BXcopier le contenu de BX vers AX. - MOVS / MOVSB / MOVSW : Déplace les chaînes d'une adresse source (SI) vers une adresse de destination (DI), automatisant ainsi le processus de transfert.
- LODS / LODSB / LODSW : Charge une valeur de l'adresse indiquée par le registre SI dans l'accumulateur (AL ou AX).
- LIRE: Charge une adresse effective au lieu de la valeur. Utile pour obtenir l'adresse d'une variable ou d'une structure.
2. Instructions sur la batterie
La pile est une structure LIFO (dernier entré, premier sorti) utilisée pour stocker temporairement des données, passer des paramètres ou sauvegarder le contexte d'exécution.
- POUSSER: Stocke une valeur sur la pile, décrémentant le pointeur SP.
- POP: Récupère la valeur la plus récente stockée sur la pile, en incrémentant SP.
- PUSHF / POPF : Ils stockent et récupèrent l'état des indicateurs du processeur sur la pile.
3. Instructions arithmétiques et logiques
Elles permettent d'effectuer des calculs et des opérations sur les bits. Ces instructions sont essentielles pour manipuler les données numériques et prendre des décisions dans le flux d'exécution du programme.
Parmi les plus utilisés on retrouve :
- AJOUTER / SOUS-SOUS : Ajouter et soustraire.
- MUL / IMUL : Multiplications binaires.
- DIV / IDIV : Division (entière ou signée).
- ET / OU / XOR / NON : Opérations logiques au niveau du bit.
- SHL / SHR / ROL / ROR : Décalages et rotations de bits.
4. Instructions de contrôle de flux
Elles permettent de modifier la séquence d'exécution du programme , en introduisant des sauts ou des appels conditionnels et inconditionnels à d'autres instructions.
- JMP : Saute inconditionnellement vers une autre adresse dans le programme.
- APPEL / RET: Appeler une sous-routine et revenir.
- JE/JNE/JG/JL/JZ/JNZ : Sauts conditionnels, ils sont exécutés si certaines conditions sont remplies (après une comparaison).
5. Instructions d'entrée/sortie (E/S)
Elles permettent la communication entre le processeur et les périphériques externes. Ces instructions permettent la lecture et l'écriture de données depuis/vers les ports (matériel).
- IN: Lit les données à partir d'un port d'entrée.
- EN DEHORS: Envoie des données vers un port de sortie.
6. Instructions à virgule flottante
De nombreux processeurs possèdent des coprocesseurs mathématiques (ou instructions spéciales) dédiés au traitement des nombres décimaux (à virgule flottante). Ces instructions permettent des opérations telles que :
- Addition, soustraction, multiplication et division de nombres réels.
- Opérations trigonométriques (sinus, cosinus, tangente).
- Opérations logarithmiques, exponentielles et racines.
Ces instructions sont généralement conformes à la norme IEEE 754 en matière de précision numérique.
Modes d'adressage
Un aspect fondamental de la conception des instructions réside dans l'identification de l'emplacement des opérandes. Les modes d'adressage définissent la manière dont le processeur accède aux données.
1. Adressage immédiat
Les données sont directement intégrées à l'instruction. C'est rapide, mais cela ne permet pas de modifier les valeurs sans changer l'instruction.
MOV AX, 5
2. Adressage direct
L'adresse mémoire contenant les données est spécifiée explicitement.
MOV AX,
3. Adressage indirect
L'adresse effective est obtenue à partir du contenu d'un enregistrement. Très flexible, elle est utilisée pour les structures et les listes chaînées.
MOV AX,
4. Adressage indexé
L'adresse est calculée en additionnant une base et un index (par exemple, pour parcourir un tableau). Elle utilise des registres spéciaux tels que SI, DI ou les registres de base et de décalage.
MOV AX,
Formats d'instructions : différents types selon l'architecture
La structure d’une instruction peut varier en fonction de l’architecture. Les formats courants incluent :
Format 4 voies
Elle comprend deux opérandes, l'emplacement du résultat et l'adresse de l'instruction suivante. Elle est désormais obsolète en raison de sa complexité.
Format 3 voies
Elle spécifie deux opérandes et une adresse de destination. Elle est courante dans les architectures RISC modernes.
Format 2 voies
Utilisez un opérande source et un opérande de destination (ce dernier pouvant également fournir une valeur). Couramment utilisé sur les architectures x86 et autres architectures CISC.
Format unidirectionnel
Un seul opérande est spécifié ; l’autre est considéré comme l’accumulateur. Ce cas de figure est fréquent dans les processeurs anciens et les systèmes simples.
Format d'adresse 0 (basé sur la pile)
Ces opérations utilisent la pile pour accéder aux opérandes et aux résultats, et les stocker. Cette méthode est très efficace pour les machines à pile, comme certaines calculatrices programmables.
Instructions macro et pseudo-opcodes
Pour améliorer la productivité, de nombreux assembleurs proposent des macro-instructions qui décomposent une seule ligne en plusieurs instructions. Celles-ci sont utiles pour éviter la répétition de motifs complexes ou pour créer des structures de haut niveau telles que des boucles ou des instructions conditionnelles.
Les pseudo-opcodes Ce sont des instructions que l'assembleur traduit en interne en une véritable séquence d'instructions. Par exemple, NOP (aucune opération) peut être traduit par XCHG AX, AX sur CPU x86.
Directives assembleur
Les directives ( également appelées pseudo-opérations ) ne sont pas des instructions au sens strict. Elles servent à contrôler le processus d'assemblage, à définir des données, des sections de code, des macros, des conditions de compilation, etc.
Voici quelques exemples courants :
- .données / .code : Ils indiquent la section de données ou de code.
- .org : Définit l'adresse à partir de laquelle l'assemblage démarrera.
- .équ: Définit des constantes symboliques.
Cas d'utilisation du langage assembleur
Malgré l'essor des langages de haut niveau, le langage assembleur reste essentiel dans plusieurs domaines :
- Développement de systèmes embarqués et de microcontrôleurs.
- Pilotes de programmation, chargeurs de démarrage et BIOS.
- Optimisation extrême dans des applications telles que les jeux vidéo ou la cryptographie.
- Ingénierie inverse, débogage et piratage de bas niveau.
De plus, la formation en langage assembleur occupe toujours une place importante dans les cursus d'informatique et d'électronique, car elle permet de comprendre en profondeur le fonctionnement d'un processeur, le stockage et la manipulation des données, ainsi que l'exécution des instructions au niveau binaire.
La compréhension de tous les types d'instructions d'assemblage, de leur structure, de leurs fonctionnalités et de leurs modes d'adressage fournit une base solide à tout programmeur qui souhaite se plonger dans la programmation de bas niveau ou comprendre comment les langages de haut niveau sont finalement traduits en code machine. Bien que son utilisation soit devenue plus spécifique, il reste un outil essentiel dans de nombreux domaines critiques du développement de logiciels et de systèmes.