TUTORIAL ASSEMBLEUR - chapitre 2 -------------------------------- Les premières instructions - Le premier programme ------------------------------------------------- Nous allons voir dans ce chapitre, quelques instructions. Ensuite nous nous attaquerons à notre premier exécutable. Les programmes nécessaires pour débuter --------------------------------------- Pour pouvoir programmer en assembleur, il convient d'acquérir certains programmes qui faciliteront les tâches. Il existe différents assembleurs. Tout d'abord, nous avons les programmes commerciaux. La palme revient au Turbo Assembleur (TASM) de Borland. Ensuite nous avons le Microsoft Assembleur (MASM) de Microsoft. Ces programmes sont bien entendu payants et ne sont pas des sharewares. Si vous voulez avoir un programme à bas prix et même gratuit, l'assembleur A86 avec son débogueur D86 sont les deux logiciels qu'il vous faut. Il existe aussi NASM (netwide assembler), cet assembleur est intéressant pour ceux qui programment en C car il permet de linker du code en asm dans un programme en C. NASM est un freeware et il est très performant, on le trouve aisément sur les FTP. Il permet de faire des exécutables aussi séparement, cependant, il ne vaut pas TASM sur ce point là. A86 a un gros inconvénient, il ne peut générer des fichiers EXE, seulement des COM. Cela veut dire que vous ne pourrez faire des programmes dont la taille est supérieure à 65k. Il y'a d'autres différences entre les EXE et les COM, cependant pour débuter, créer des fichiers COM est suffisant. A86 n'est pas capable aussi dans sa version shareware de gérér les instructions du 386. Pour pouvoir écrire le code source qui contiendra les instructions, il vous faut un simple éditeur de texte, le programme du DOS, Edit, convient parfaitement pour ce travail. Le Notepad de Windows est aussi un bon outil mais il est limité par la taille du fichier à éditer (même si ce problème se pose rarement, il est préferable de travailler sous DOS que sous Windows pour éviter certains désagréments causés par Win). Comment les utiliser ? ---------------------- Je ne vais pas vous donner des fichiers d'aide sur les programmes mais je vais juste expliquer leur fonctionnement. En cas de problème, il faut vous référer aux fichiers texte livrés avec le programme. Pour ce qui est de l'assembleur, avec le programme A86, il faut taper sous l'invite du DOS : A86 fichier.asm (fichier.asm est le nom de votre fichier assembleur) Cela aura pour conséquence de créer le programme "fichier.com" que vous pourrez exécuter. A86 peut aussi vous renvoyer un message d'erreur si votre programme possède des erreurs de syntaxe, il faudra alors réediter le fichier source et chercher l'erreur. A86 ne vous informera PAS des bugs présents dans votre programme. Les bugs ne sont pas des erreurs de syntaxe, mais des fautes de programmation qui conduisent votre programme à planter, ou à se comporter d'une facon incorrecte. La première instruction : MOV ----------------------------- Cette instruction vient de l'anglais "move" qui signifie déplacer mais attention, le sens de ce terme est modifié car l'instruction MOV ne déplace pas mais place tout simplement. Cette instruction nécessite deux opérandes (deux variables) qui sont la destination et la source. Ceux-ci peuvent être des registres généraux ou des emplacements mémoire. Cependant, les deux opérandes ne peuvent pas être toutes les deux des emplacements mémoire. De même, la destination ne peut pas être ce qu'on appelle une valeur immédiate (les nombres sont des valeurs immédiates, des valeurs dont on connait immédiatement le résultat) donc pas de MOV 10,AX. Ceci n'a pas de sens, comment pouvez-vous mettre dans le nombre 10, la valeur de AX ? 10 n'est pas un registre. Une autre règle à respecter, les opérandes doivent être de la même taille donc pas de MOV AX,AL, cela me semble assez logique. On ne peut pas utiliser une valeur immédiate avec un registre de segment (MOV ES,5 = impossible mais MOV ES,AX = possible). Quelques exemples : MOV AL,CL (place le contenu de CL dans AL) donc si AL=5 et CL=10, nous aurons AL=10 et CL=10. MOV CX,ES:[DI] (place dans CX, le contenu 16 bits de l'emplacement ES:[DI]). Donc si le word (le word est l'unité correspondant à 16 bits) ES:[DI]=34000, nous aurons CX=34000. MOV CL,DS:[SI] (place dans CL, le contenu 8 bits (byte) de l'emplacement DS:[SI]). Donc si DS:[SI] (attention en 8 bits) = 12, CL vaudra 12. Au sujet de ces emplacements mémoires, il faut que vous vous les représentiez comme des "cases" de 8 bits, comme le plus petit registre fait 8 bits, on ne peut pas diviser la mémoire en emplacements plus petits. On peut prendre directement 16 bits en mémoire (un word) ou carrément un dword (32 bits). Il est tres important de saisir cette notion. Un exemple concret : vous avez des livres sur une étagère, le livre se trouvant toute à gauche est le 1er de la liste, nous nous déplacons de gauche à droite. Un livre est un byte (8 bits), 2 livres sont un word (16 bits), 4 livres font un dword (32 bits). Si nous faisons MOV AX,ES:[DI], nous allons prendre 2 livres, en commencant par le livre se trouvant à l'emplacement DI et en prenant ensuite le livre se trouvant à l'emplacement DI+1 (l'emplacement suivant dans votre rangée de livre, 1 byte plus loin en mémoire). Voici un autre exemple : MOV EAX,ES:[DI] (place un dword depuis ES:[DI] dans EAX). C'est comme si on copiait 4 livres dans EAX. Et quelques exemples incorrects : MOV 1,10 (impossible et pas logique) MOV ES:[DI],DS:[SI] (incodable malheureusement) MOV ES,10 (incodable, il faut passer par un registre général donc MOV ES,AX ou MOV ES,CX mais pas de MOV ES,AL). Ce qu'il faut retenir c'est que l'instruction MOV est comme le signe '=' MOV ES,CX c'est comme faire ES=CX. Une autre instruction : JMP --------------------------- JMP est une simplification pour exprimer le mot JUMP qui signifie sauter en anglais. JMP va servir dans le programme pour "passer" d'une opération à une autre, de sauter dans le programme à différents endroits pour effectuer d'autrest taches. Je ne vais pas m'attarder dans des explications sur le pointeur d'instruction mais sachez que chaque instruction est désignée par un emplacement en mémoire (défini par CS:[IP]). L'instruction JMP va donc modifier la valeur de IP et par conséquence changer d'instruction. On peut utiliser JMP avec des valeurs immédiates. Exemples : JMP 10 (il aura pour effet de passer, non pas à l'instruction qui se trouve à la ligne 10 , mais à l'emplacement mémoire 10. Une instruction n'est pas forcément de taille 1, certaines peuvent s'étaler sur plusieurs bytes.) Il est plus simple d'utiliser des "étiquettes qu'on peut écrire sous la forme "ETIQUETTES:". Avec les étiquettes, il suffit d'écrire JMP ETIQUETTES pour arriver directement à l'instruction qui suit le étiquette. Un petit exemple de code: DEBUT : MOV AX,14 JMP DEBUT Ce programme ne fait rien sinon placer continuellement 14 dans AX, on appelle cela une boucle. Nous verrons plus tard qu'il existe différents types de sauts. Quelques instructions arithmétiques : ADD et SUB ------------------------------------------------ ADD sert à additionner, et nécessite deux opérandes : une source et une destination. La destination prendra la valeur de source + destination. Les règles de combinaison sont les mêmes que pour MOV mais avec SUB et ADD, l'utilisation des registres de segment est impossible. Exemples : ADD AX,CX (si AX=10 et CX=20 alors nous aurons AX=30 et CX=20) ADD EAX,EBX ADD AX,-123 (l'assembleur autorise les nombres négatifs) SUB DI,12 Quelques exemples impossibles : ADD AX,CL (comme pour MOV, un 16 bits avec un 8 bits sont incompatibles) SUB ES:[DI],DS:[SI] ADD ES,13 (impossible car c'est un registre de segment) Notre premier programme ----------------------- Nous allons faire un petit programme qui ne fera rien du tout si ce n'est de s'exécuter et de retourner au DOS. Voici le code que vous allez écrire avec l'Editeur du DOS (ou Notepad) et que vous allez enregistrer sous le nom de C1.ASM MOV AX,100 SUB AX,10 ADD AL,5 RET Après avoir écrit ce texte, lancez le programme A86 en tapant "A86 C1.ASM". Si tout va bien, A86 devrait renvoyer un message du genre "Object : C1.COM". Maintenant lancez le programme C1 comme pour n'importe quel exécutable, rien ne se passe ? C'est tout à fait normal. Notre programme calcule quand même la valeur de AX mais rien ne s'affiche à l'écran, tout se passe dans le processeur (CPU). Maintenant étudions de plus près le code. MOV AX,100 place 100 dans AX (AX=100). Ensuite nous avons SUB AX,10 (AX=90) et ADD AL,5 qui va ajouter 5 à la partie basse de AX ce qui donne AX=95. Mais qu'est-ce donc ce RET ? Il s'agit d'une instruction (ret=return=retour) qui indique au processeur de rendre la main au DOS. Si vous tapez "DIR" pour voir tous les fichiers, vous verrez votre C1.COM de 9 bytes. Un des intérêts majeur de l'assembleur est la taille des fichiers crées, ils sont compacts, bien plus que ceux crées à partir de compilateur comme le C, BASIC ou PASCAL. (les compilateurs C deviennent cependant de plus en plus efficaces). ### Chapitre 2 - dake / c a l o d o x ### ### http://www.space.ch/scene/calodox ###