Zero One Cyber

Contenu du cours
Tutoriel Assembleur – Chapitre 1 : Les bases indispensables pour débuter
Dans ce premier chapitre, tu découvriras les fondamentaux du langage Assembleur afin de comprendre comment un programme interagit directement avec le processeur et la mémoire. Tu apprendras : ce qu’est réellement l’Assembleur et à quoi il sert le rôle du processeur, des registres et de la mémoire la structure d’un programme assembleur les instructions de base et leur fonctionnement le flux d’exécution d’un programme les notions essentielles pour lire et comprendre du code assembleur simple Ce chapitre pose les bases indispensables pour aborder la programmation bas niveau, le reverse engineering et l’analyse de binaires dans la suite du cours. Aucun prérequis avancé n’est nécessaire : tout est expliqué pas à pas, avec une approche claire et accessible.
0/13
Programmation bas niveau : maîtriser l’Assembleur

Les premières instructions – Premier programme

 

Dans ce chapitre, nous allons découvrir les premières instructions du langage assembleur.
Ces notions nous permettront ensuite de passer à une étape clé : la création de notre tout premier programme exécutable.

 

L’objectif est de comprendre comment s’écrit un programme assembleur simple et comment il est transformé en un fichier exécutable par l’assembleur.

 

Les outils nécessaires pour débuter

 

Pour programmer en assembleur, il est indispensable de disposer de certains outils adaptés. Il existe plusieurs assembleurs, chacun avec ses spécificités.

 

Assembleurs commerciaux

 

Parmi les solutions commerciales les plus connues, on trouve :

 

  • Turbo Assembler (TASM) de Borland

  • Microsoft Assembler (MASM) de Microsoft

 

Ces outils sont puissants et très complets, mais ils sont payants et ne sont pas distribués en shareware.

 

Assembleurs gratuits ou à faible coût

 

Pour débuter sans investir dans un logiciel commercial, plusieurs alternatives existent :

 

  • A86 accompagné de son débogueur D86
    Ces outils sont simples d’utilisation et adaptés à l’apprentissage. Leur principal inconvénient est qu’ils ne peuvent générer que des fichiers COM, dont la taille est limitée à 65 Ko. Cela reste cependant suffisant pour les premiers programmes.
    À noter également que la version shareware de A86 ne prend pas en charge les instructions spécifiques aux processeurs 386 et supérieurs.

  • NASM (Netwide Assembler)
    NASM est un assembleur gratuit et très performant. Il est particulièrement apprécié par les développeurs travaillant avec le langage C, car il permet d’intégrer facilement du code assembleur dans des programmes écrits en C.
    NASM peut également générer des exécutables de manière autonome, même s’il est généralement considéré comme moins orienté DOS classique que TASM.

 

Éditeurs de texte

 

Pour écrire le code source contenant les instructions assembleur, un simple éditeur de texte suffit :

 

  • L’éditeur EDIT sous DOS est parfaitement adapté

  • Le Bloc-notes de Windows peut également convenir, bien qu’il présente certaines limitations

 

De manière générale, travailler dans un environnement DOS est souvent préférable pour éviter les problèmes liés à Windows et garantir un comportement plus prévisible lors de la compilation et de l’exécution.

 

 

Comment utiliser les outils

 

L’objectif ici n’est pas de détailler toute la documentation des programmes, mais de comprendre leur fonctionnement général. En cas de difficulté, il est recommandé de consulter les fichiers d’aide fournis avec chaque outil.

 

Utilisation de l’assembleur A86

 

Avec l’assembleur A86, la compilation se fait directement depuis l’invite de commandes DOS :

 
A86 fichier.asm

fichier.asm représente le fichier source assembleur.

 

Cette commande génère un fichier exécutable nommé fichier.com, que vous pourrez ensuite lancer.
Si le programme contient des erreurs de syntaxe, A86 affichera des messages d’erreur. Il faudra alors rouvrir le fichier source, corriger les erreurs et relancer l’assemblage.

 

 A86 ne détecte pas les bugs logiques.
Un bug n’est pas une erreur de syntaxe, mais une erreur de programmation qui peut provoquer un comportement incorrect ou un plantage du programme.

 

La première instruction : MOV

 

L’instruction MOV provient du mot anglais move (déplacer). En réalité, elle ne déplace pas une valeur, mais copie une valeur d’une source vers une destination.

 

Syntaxe générale

 
MOV destination, source
 

L’instruction MOV nécessite deux opérandes :

 

  • une destination

  • une source

 

Ces opérandes peuvent être :

 

  • des registres

  • des emplacements mémoire

  • des valeurs immédiates (nombres)

 

Cependant, certaines règles doivent être respectées.

 

Règles importantes de l’instruction MOV

 

  1. Les deux opérandes ne peuvent pas être des emplacements mémoire
    Exemple incorrect :

     
    MOV ES:[DI], DS:[SI]
     
  2. La destination ne peut pas être une valeur immédiate
    Exemple incorrect :

     
    MOV 10, AX

    Un nombre n’est pas un emplacement de stockage.

  3. Les deux opérandes doivent avoir la même taille
    Exemple incorrect :

     
    MOV AX, AL
  4. On ne peut pas charger directement une valeur immédiate dans un registre de segment
    Exemple incorrect :

     
    MOV ES, 5

    Exemple correct :

     
    MOV AX, 5
    MOV ES, AX

 

Exemples valides

 
MOV AL, CL

Copie le contenu de CL dans AL.
Si AL = 5 et CL = 10, alors après l’instruction :

 

  • AL = 10

  • CL = 10

 
MOV CX, ES:[DI]

Copie une valeur 16 bits (word) depuis la mémoire à l’adresse ES:[DI] vers le registre CX.

 
MOV CL, DS:[SI]

Copie une valeur 8 bits (byte) depuis la mémoire à l’adresse DS:[SI] vers le registre CL.

 

Comprendre la mémoire (byte, word, dword)

 

La mémoire peut être vue comme une suite de cases de 8 bits, appelées bytes.
On ne peut pas accéder à moins de 8 bits à la fois.

 

  • 1 byte = 8 bits

  • 1 word = 16 bits = 2 bytes

  • 1 dword = 32 bits = 4 bytes

 

Analogie :


Imagine une étagère de livres :

  • 1 livre = 1 byte

  • 2 livres = 1 word

  • 4 livres = 1 dword

Si on écrit :

 
MOV AX, ES:[DI]
 

Le processeur lit 2 bytes consécutifs, à partir de l’adresse DI et DI+1.

 
MOV EAX, ES:[DI]

Copie 4 bytes consécutifs (un dword) dans le registre EAX.

 

Exemples incorrects

 
MOV 1, 10
 
MOV ES:[DI], DS:[SI]
 
MOV ES, 10

 

À retenir

 

L’instruction MOV fonctionne comme une affectation :

 
MOV ES, CX ≈ ES = CX

Elle est l’une des instructions les plus importantes en assembleur et constitue la base de toute manipulation de données.

 

Une autre instruction : JMP

 

L’instruction JMP vient de l’anglais JUMP, qui signifie « sauter ».
Elle permet de changer le flux d’exécution du programme, en passant d’une instruction à une autre.

Chaque instruction en mémoire possède une adresse unique, représentée par le couple CS:[IP] (Code Segment et Instruction Pointer). Lorsque JMP est utilisée, elle modifie la valeur de IP, ce qui fait que le processeur exécute l’instruction à l’adresse cible.

 

Utilisation

 

  • JMP peut être utilisée avec une valeur immédiate, correspondant à l’adresse mémoire à atteindre.
    Exemple :

     
    JMP 10

    Ici, le processeur passe directement à l’instruction se trouvant à l’adresse mémoire 10 (attention : une instruction peut occuper plusieurs bytes).

  • Il est plus pratique d’utiliser des étiquettes, qui rendent le code plus lisible :

     
    DEBUT:
    MOV AX, 14
    JMP DEBUT

    Ce petit programme crée une boucle infinie, qui place continuellement la valeur 14 dans AX. Nous verrons plus tard différents types de sauts (JZ, JNZ, etc.).

 

Instructions arithmétiques : ADD et SUB

 

Les instructions ADD et SUB permettent de faire des calculs simples.

 

Règles générales

  • Elles utilisent deux opérandes : une source et une destination.

  • La destination est modifiée :

     
    destination = destination ± source
  • Les registres de segment ne peuvent pas être utilisés avec ADD ou SUB.

  • Les opérandes doivent être de la même taille.

 

Exemples valides

 
ADD AX, CX ; AX = AX + CX
ADD EAX, EBX
ADD AX, -123 ; valeurs négatives autorisées
SUB DI, 12

 

Exemples invalides

 
ADD AX, CL ; incompatibilité 16 bits vs 8 bits
SUB ES:[DI], DS:[SI] ; deux emplacements mémoire
ADD ES, 13 ; registre de segment non autorisé

 

Notre premier programme

Nous allons créer un programme très simple, qui calcule quelques valeurs et retourne au DOS.
Enregistrez-le avec l’éditeur DOS (ou Notepad) sous le nom C1.ASM :

 
MOV AX, 100
SUB AX, 10
ADD AL, 5
RET

Compilation

 

Dans l’invite DOS, tapez :

 
A86 C1.ASM

Si tout se passe bien, A86 générera le fichier C1.COM.

 

Exécution

 

Lancez le programme C1. Rien ne s’affiche à l’écran, et c’est normal : le programme effectue ses calculs uniquement dans le processeur.

 

Analyse du code

 

  1. MOV AX, 100 → place la valeur 100 dans le registre AX (AX = 100)

  2. SUB AX, 10 → soustrait 10 à AX (AX = 90)

  3. ADD AL, 5 → ajoute 5 à la partie basse d’AX (AL), ce qui donne AX = 95

  4. RETreturn : retourne le contrôle au DOS

 

Remarque

 

L’un des avantages majeurs de l’assembleur est la compacité des fichiers exécutables. Ici, C1.COM ne fait que 9 bytes.
Les programmes compilés à partir de langages comme C, BASIC ou Pascal sont généralement beaucoup plus volumineux, même si les compilateurs modernes deviennent de plus en plus efficaces.