Vous êtes sur la page 1sur 71

ASSEMBLEUR

Apprendre l'assembleur
(INTEL - DOS 16 bits)
Par Benot-M

Ce document a t tlcharg depuis http://benoit-m.developpez.com/assembleur/tutoriel

Dernire modification du contenu le 03 janvier 2003

Dsormais, pour apprendre le franais, il faudra SAVOIR le franais ! disait Coluche. De mme, ce tutoriel s'adresse tous ceux qui connaissent dj les rudiments dun langage volu tel que le BASIC, le FORTRAN, le C ou le PASCAL et qui souhaitent apprendre l'assembleur. Une connaissance mme sommaire dun de ces langages suffit ! Aucune connaissance en programmation systme nest requise : le but de ce cours est justement den introduire les fondements. Contrairement aux langages volus, l'assembleur, ou langage dassemblage est constitu d'instructions directement comprhensibles par le microprocesseur : c'est ce qu'on appelle un langage de bas niveau. Il est donc intimement li au fonctionnement de la machine. C'est pourquoi il est relativement difficile assimiler, en tout cas beaucoup plus que les langages de haut niveau. Cela explique galement pourquoi il existe au moins autant de langages dassemblage que de modles de microprocesseurs. Avant d'apprendre lassembleur INTEL 80x86, il est donc primordial de sintresser quelques notions de base concernant par exemple la mmoire ou le microprocesseur. Cest l en effet que se trouvent les principales difficults pour le dbutant. Ne soyez pas rebut par labstraction des concepts prsents dans les premiers paragraphes : il est normal que durant la lecture, beaucoup de choses ne soient pas claires dans votre esprit. Tout vous semblera beaucoup plus simple quand nous passerons la pratique dans le langage assembleur. Le microprocesseur peut fonctionner sous deux modes : le mode rel et le mode protg. Le mode protg permet daccder 232 octets de mmoire vive, alors que le mode rel ne peut en adresser que 220 = 1 Mo. Nous ne traiterons dans ce cours que le mode rel. Cest celui quutilisent la plupart des programmes DOS. Convention : toutes les adresses sont crites en notation hexadcimale. Les autres nombres seront la plupart du temps reprsents en base dcimale. Dans le cas contraire, nous ajouterons la lettre h aprs les chiffres.

PREMIERE PARTIE
NOTIONS DE BASE SUR LE FONCTIONNEMENT DE L'ORDINATEUR

I. LARITHMETIQUE SIGNEE
On appelle arithmtique non signe larithmtique dans laquelle tous les entiers sont positifs. En arithmtique signe au contraire, les nombres peuvent tre soit positifs, soit ngatifs. Un nombre sign nest donc pas forcment ngatif. Les donnes informatiques se prsentent sous la forme dune succession de chiffres binaires, les bits. Nous supposerons que les systmes de numration binaire et hexadcimal vous sont dj familiers. Il est en revanche fort possible que vous ne connaissiez pas la faon dont un ordinateur reprsente les nombres ngatifs. Il existe deux conventions : la notation en signe et valeur absolue et la notation en complment 2. La premire est extrmement simple : le premier bit reprsente le signe, et les autres bits la valeur absolue du nombre. Le bit de signe vaut 1 si le nombre est strictement ngatif, 0 sinon. Par exemple, le nombre (14) cod sur 8 bits scrit ainsi : 10001110 Cette convention nest quasiment jamais utilise en informatique. On lui prfre la reprsentation en complment 2 dont le principe est le suivant : - les nombres positifs sont cods de la mme faon quen convention signe et valeur absolue . - les nombres ngatifs sont obtenus en inversant tous les bits, puis en ajoutant 1. Exemple : le nombre 14 cod sur 8 bits est reprsent ainsi : 00001110 et (14) ainsi :
inversion ajout

des bits : 11110001

dune unit : 11110010 : 11110010

rsultat

Remarque : le rsultat intermdiaire, 11110001, est appel complment 1 . Vous allez immdiatement comprendre lavantage de cette reprsentation. Faisons la somme de 14 et de (14), de la mme faon que sil sagissait dentiers positifs :

00001110 + 11110010 = 100000000 Le rsultat tant cod sur 8 bits, le 1 situ gauche nest pas pris en compte. On obtient donc 14 + (-14) = 0. Lintrt vident est que la diffrence de deux nombres peut se calculer avec le mme algorithme que leur somme. Il suffit de transformer au pralable le nombre retranch en son oppos. Cette conversion est trs simple et trs rapide. Au contraire, en reprsentation signe et valeur absolue , on aurait eu besoin de nombreux algorithmes, car plusieurs cas se prsentent. Remarque : la reprsentation en complment 2 revient en fait crire (-1) comme ceci : 11111111 (-2) comme cela : 11111110 (-3) comme cela : 11111101 etc Il y a ainsi une symtrie entre les nombres positifs et les nombres ngatifs. Il en rsulte que le bit le plus gauche reprsente le signe, de la mme faon quen notation signe et valeur absolue . Avant tout calcul, nous pouvons donc affirmer que le nombre 10010101 est ngatif.

II. LA MEMOIRE VIVE 1. La segmentation de la mmoire


Votre PC est conu pour grer 1 Mo (soit 220 octets) de mmoire vive en mode rel. Il faut donc 20 bits au minimum pour adresser toute la mmoire. Or en mode rel les bus dadresses nont que 16 bits. Ils permettent donc d'adresser 216 = 65536 octets = 64 Ko, ce qui est insuffisant ! Afin de pallier ce manque, on utilise deux nombres pour adresser un octet quelconque de la RAM. Le premier est appel adresse de segment, le second adresse d'offset. Ils seront stocks sparment. La mmoire est ainsi dcoupe en segments de 64 Ko chacun. Un segment est donc en quelque sorte un gros bloc de mmoire auquel on peut accder grce une adresse de segment qui dsigne son numro. Par exemple, le premier segment est le segment 0000 (en hexa), le deuxime est le 0001, le quarante-deuxime est le 0029, etc... Chaque numro est cod sur 16 bits, cest--dire 4 chiffres hexa. Pour accder un octet particulier dans un segment, il suffit de compter le dcalage de cet octet par rapport au dbut du segment. Ce dcalage est obligatoirement infrieur ou gal 65535 : il tient bien sur 16 bits lui aussi. On appelle ce dcalage offset . L'adresse d'un octet se note XXXX:YYYY o XXXX est l'adresse de segment et YYYY est l'offset (tous deux en notation hexadcimale, bien sr). Par exemple, le dix-septime octet de la RAM (le numro 16) est situ l'adresse 0000:0010. De mme, loctet 0000:0100 est l'octet numro 256. Nous en arrivons la petite subtilit quil convient de bien saisir, sous peine de ne rien comprendre certains programmes en assembleur. On pourrait penser que loctet qui se trouve ladresse 0001:0000 est le numro 65536. Il nen est rien. C'est l'octet numro 16. Eh oui ! Les segments ne sont pas situs gentiment les uns la suite des autres. Ils sont fort mal levs et n'attendent pas que les segments qui les prcdent soient termins avant de commencer ! Ils se marchent donc sur les pieds. Autrement dit, le deuxime segment ne dmarre pas l'octet 65536 comme il devrait le faire s'il tait bien sage, mais l'octet 16 ! Le troisime dmarre l'octet 32 et ainsi de suite La notion de segment nest pas tant physique que mathmatique : elle sert se reprer dans la RAM. La consquence immdiate de tout cela est qu'un octet n'a pas une adresse unique. Par exemple, l'octet numro 66 peut tre adress par 0000:0042, mais aussi par 0001:0032, par 0002:0022, par 0003:0012 ou encore par 0004:0002. Toutes ces adresses sont quivalentes. Voil pour la subtilit. Si vous avez compris, vous devriez tre capable de trouver facilement comment on calcule l'adresse effective d'un octet, c'est dire sa position absolue dans la RAM. Allez, un petit effort !

Voici la solution : si l'adresse de l'octet est A17C:022E, alors son adresse effective est A17C x 16 + 022E, soit A17C0 + 022E = A19EE. On a multipli par 16, car le segment A17C dbute loctet A17C x 16, puis on a simplement ajout le dcalage. Au final, on a bien une adresse sur 20 bits puisqu'on obtient 5 chiffres hexa. Chaque petit bloc de 16 octets sappelle un paragraphe.

Remarque importante : Il est souvent plus simple de considrer quun segment est un bloc de taille quelconque qui dbute une adresse effective multiple de 16 et qui permet, laide de son adresse de segment et dun offset, dadresser le bloc entier (64 Ko au maximum). Cette dfinition est notre avis celle qui a le plus de sens, et nous l'utiliserons tout au long de ce cours.

2. Structure dun programme en mmoire


Lorsque lutilisateur excute un programme, celui-ci est dabord charg en mmoire par le systme. Le DOS distingue deux modles de programmes excutables : les fichiers COM et les fichiers EXE. La diffrence fondamentale est que les programmes COM ne peuvent pas utiliser plus dun segment dans la mmoire. Leur taille est ainsi limite 64 Ko. Les programmes EXE ne sont quant eux limits que par la mmoire disponible dans lordinateur.

a) les fichiers COM


Lorsquil charge un fichier COM, le DOS lui alloue toute la mmoire disponible. Si celle-ci est insuffisante, il le signale lutilisateur par un message et annule toute la procdure dexcution. Dans le cas contraire, il cre le PSP du programme au dbut du bloc de mmoire rserv, et copie le programme charger la suite.

Mais quest-ce donc quun PSP ? Pour simplifier, le PSP ( Program Segment Prefix ) est une zone de 256 (= 100h) octets qui contient des informations diverses au sujet du programme. Cest dans le PSP que se trouve la ligne de commande tape par lutilisateur. Par exemple, le PSP dun programme appel MONPROG, excut avec la commande MONPROG monfic.txt /S /H, contiendra la chane de caractres suivante : monfic.txt /S /H. Le programmeur a ainsi la possibilit daccder aux paramtres. Voici titre indicatif la structure simplifie du PSP (ne vous souciez pas de ce que vous ne comprenez pas : pour l'instant, seules les deux dernires lignes nous intressent vraiment) : Offset 00h 02h 04h 05h 0Ah 0Eh 12h 16h 2Ch 2Eh 80h 81h Description Appel de l'int 20h Adresse du 1er segment qui se trouve au del du prog. Rserv Far call de l'int 21h (inutilis) Vecteur de l'int 22h Vecteur de l'int 23h Vecteur de l'int 24h Rserv Segment du bloc d'environnement Rserv Nombre de caractres dans la ligne de commande sans compter le code ASCII 13 (retour chariot) Ligne de commande ( partir du caractre espace qui suit le nom du programme) + code ASCII 13 Taille (octets) 2 2 1 5 4 4 4 22 2 82 1 127

A prsent que nous connaissons lexistence du PSP, il nous faut revenir sur un point important. Comme nous lavons dit, un programme COM ne peut comporter quun seul segment, bien que le DOS lui rserve la totalit de la mmoire disponible. Ceci a deux consquences. La premire est que les adresses de segment sont inutiles dans le programme : les offsets seuls permettent dadresser nimporte quel octet du segment. La seconde est que le PSP fait partie de ce segment, ce qui limite 64 Ko 256 octets la taille maximale dun fichier COM. Cela implique galement que le programme lui-mme dbute loffset 100h et non loffset 0h.

b) les fichiers EXE


Pour un fichier EXE, tout est toujours un peu plus compliqu. (Devise du programmeur dbutant en assembleur) Bien quil soit possible de nutiliser quun seul segment tout faire, la plupart des programmes EXE ont un segment rserv au code (cest ainsi quon appelle les instructions du langage machine), un ou deux autres aux donnes, et un dernier la pile. La pile est une mmoire trs spciale qui sert comme son nom lindique empiler des donnes de 16 bits de faon temporaire. On peut ensuite retrouver ces donnes en les dpilant. Le dpilage se fait toujours dans lordre inverse de lempilage. Le PSP a lui aussi son propre segment. Le programme commence donc loffset 0h du segment de code et non loffset 100h.

Afin que le programme puisse tre charg et excut correctement, il faut que le systme sache o commence et o sarrte chacun de ces segments. A cet effet, les compilateurs crent un en-tte (ou header ) au dbut de chaque fichier EXE. Ce header ne sera pas copi en mmoire. Son rle est simplement dindiquer au DOS (lors du chargement) la position relative de chaque segment dans le fichier.

3. Les cycles de lecture-criture


Le code et les variables dun programme se trouvent dans la mmoire vive. Pour accder une donne en mmoire, le processeur place son adresse dans un bus dadresse. Un cycle de lecture se met alors en place. Il consiste retourner la donne lue au processeur via le bus de donnes. Pour lcriture, ladresse de la destination est transmise dans le bus dadresse et la donne crire est place dans le bus de donnes. Ouf ! Nous aurons loccasion de revenir sur la mmoire vive dans les autres chapitres pour apporter quelques prcisions. Vous devriez mieux comprendre toutes ces notions en lisant la suite, car jusquici nous navons pas encore parl de la faon dont lordinateur se sert des adresses pour accder des donnes ou pour excuter du code. Cest l quintervient le microprocesseur...

III. LE MICRO-PROCESSEUR LES REGISTRES 1. Gnralits sur les registres


Le microprocesseur est le cur de lordinateur. Cest lui qui est charg de reconnatre les instructions et de les excuter (ou de les faire excuter). Chaque instruction se prsente sous la forme dune suite de bits quon reprsente en notation hexadcimale (exemple : B44C, ou 1011010001001100 en binaire). Une instruction se compose dun code oprateur (le plus souvent appel opcode ) qui dsigne laction effectuer (B4 dans notre exemple) et dun champ doprandes sur lesquelles porte lopration (ici loprande est 4C). Pour travailler, le microprocesseur utilise de petites zones o il peut stocker des donnes. Ces zones portent le nom de registres et sont trs rapides d'accs puisqu'elles sont implantes dans le microprocesseur lui-mme et non dans la mmoire vive. Les registres des processeurs INTEL se classent en quatre catgories :
les les les le

registres gnraux (16 bits) registres de segment (16 bits) registres d'offset (16 bits)

registre des indicateurs (16 bits)

2. Les registres gnraux


Ils ne sont pas rservs un usage trs prcis, aussi les utilise-t-on pour manipuler des donnes diverses. Ce sont en quelque sorte des registres tout faire. Chacun de ces quatre registres peut servir pour la plupart des oprations, mais ils ont tous une fonction principale qui les caractrise. Nom AX BX CX DX Fonction privilgie Accumulateur Base Compteur Donnes

Le registre AX sert souvent de registre d'entre-sortie : on lui donne des paramtres avant d'appeler une fonction ou une procdure. Il est galement utilis pour de nombreuses oprations arithmtiques, telles que la multiplication ou la division de nombres entiers. Il est appel accumulateur . Exemples d'utilisation :
linstruction ADD

MOV AX, 1982 place lentier 1982 dans AX.

AX, 1983 ajoute AX le nombre 1983 et place le rsultat dans AX.

Le registre BX peut servir de base. Nous verrons plus tard ce que ce terme signifie.

Le registre CX est utilis comme compteur dans les boucles. Par exemple, pour rpter 15 fois une instruction en assembleur, on peut mettre la valeur 15 dans CX, crire l'instruction prcde d'une tiquette qui reprsente son adresse en mmoire, puis faire un LOOP cette adresse. Lorsqu'il reconnat l'instruction LOOP, le processeur sait que le nombre d'itrations excuter se trouve dans CX. Il se contente alors de dcrmenter CX, de vrifier que CX est diffrent de 0 puis de faire un saut ( jump ) ltiquette mentionne. Si CX vaut 0, le processeur ne fait pas de saut et passe linstruction suivante. Exemple :

Le registre DX contient souvent l'adresse d'un tampon de donnes lorsqu'on appelle une fonction du DOS. Par exemple, pour crire une chane de caractres l'cran, il faut placer loffset de cette chane dans DX avant d'appeler la fonction approprie. Chacun de ces quatre registres comporte 16 bits. On peut donc y stocker des nombres allant de 0 65535 en arithmtique non signe, et des nombres allant de 32768 32767 en arithmtique signe. Les 8 bits de poids fort dun registre sont appels partie haute et les 8 autres partie basse . Chaque registre est en fait constitu de deux sous-registres de 8 bits. La partie haute de AX sappelle AH, sa partie basse AL. Il en va de mme pour les trois autres. En arithmtique non signe, il en dcoule la formule suivante : AX = AH x 256 + AL ainsi que leurs homologues : BX = BH x 256 + BL CX = CH x 256 + CL DX = DH x 256 + DL Il va de soi quen modifiant AL ou AH, on modifie galement AX. Pour stocker un nombre de 32 bits, on peut utiliser des paires de registres. Par exemple, DX:AX signifie DX x 65535 + AX en arithmtique non signe. Cette notation (DX:AX) nest pas reconnue par lassembleur (ni par la machine). Ne confondez pas cela avec les adresses de segment et doffset.

Sur un PC relativement rcent, AX, BX, CX, DX ne sont en fait que les parties basses de registres de 32 bits nomms EAX, EBX, ECX, EDX ( E pour Extended ). On a donc un moyen plus pratique de stocker les grands nombres. En fait, chaque registre (pas seulement les registres gnraux) peut contenir 32 bits.

3. Les registres de segment


Ils sont au nombre de quatre : Nom CS DS ES SS Nom complet Code segment Data segment Extra segment Stack segment Traduction Segment de code Segment de donnes Extra segment Segment de pile

Contrairement aux registres gnraux, ces registres ne peuvent servir pour les oprations courantes : ils ont un rle trs prcis. On ne peut dailleurs pas les utiliser aussi facilement que AX ou BX, et une petite modification de lun deux peut suffire planter le systme. Eh oui ! Lassembleur, ce nest pas Turbo Pascal ! Il ny a aucune barrire de protection, si bien quune petite erreur peut planter le DOS. Mais rassurez-vous : tout se rpare trs bien en redmarrant lordinateur Dans le registre CS est stocke ladresse de segment de la prochaine instruction excuter. La raison pour laquelle il ne faut surtout pas changer sa valeur directement est vidente. De toute faon, vous ne le pouvez pas. Le seul moyen viable de le faire est dutiliser des instructions telles que des sauts (JMP) ou des appels (CALL) vers un autre segment. CS sera alors automatiquement actualis par le processeur en fonction de ladresse darrive. Le registre DS est quant lui destin contenir ladresse du segment des donnes du programme en cours. On peut le faire varier condition de savoir exactement pourquoi on le fait. Par exemple, on peut avoir deux segments de donnes dans son programme et vouloir accder au deuxime. Il faudra alors faire pointer DS vers ce segment. ES est un registre qui sert adresser le segment de son choix. On peut le changer aux mmes conditions que DS. Par exemple, si on veut copier des donnes dun segment vers un autre, on pourra faire pointer DS vers le premier et ES vers le second. Le registre SS adresse le segment de pile. Il est rare quon doive y toucher car le programme na quune seule pile. Intressons-nous prsent aux valeurs que le DOS donne ces registres lors du chargement en mmoire dun fichier excutable ! Elles diffrent selon que le fichier est un programme COM ou EXE. Pour crire un programme en assembleur, il est ncessaire de connatre ce tableau par cur : Registre CS DS ES Valeur avant lexcution Fichier COM Fichier EXE Adresse de lunique segment, cest Adresse du segment de code dire adresse de segment du PSP Adresse de lunique segment, cest Adresse de segment du PSP dire adresse de segment du PSP Adresse de lunique segment, cest Adresse de segment du PSP

SS

dire adresse de segment du PSP Adresse de lunique segment, cest Adresse du segment de pile dire adresse de segment du PSP

Le schma suivant montre mieux la situation :

Dans un fichier EXE, le header indique au DOS les adresses initiales de chaque segment par rapport au dbut du programme (puisque le compilateur n'a aucun moyen de connatre l'adresse laquelle le programme sera charg). Lors du chargement, le DOS ajoutera ces valeurs l'adresse d'implantation pour obtenir ainsi les vritables adresses de segment. Dans le cas d'un fichier COM, tout est plus simple. Le programme ne comporte qu'un seul segment, donc il suffit tout btement au DOS de charger CS, DS, ES et SS avec l'adresse d'implantation. Remarque : Pourquoi DS et ES pointent-ils vers le PSP dans le cas dun fichier EXE ? Premire raison : pour que le programmeur puisse accder au PSP ! Deuxime raison : parce quun programme EXE peut comporter un nombre quelconque de segments de donnes. Cest donc au programmeur dinitialiser ces registres, sil veut accder ses donnes.

4. Les registres doffset


Les voici : Nom IP SP SI DI Nom complet Instruction pointer Stack pointer Source index Destination index Traduction Pointeur dinstruction Pointeur de pile Index de source Index de destination

BP

Base pointer

Pointeur de base

Le registre IP dsigne loffset de la prochaine instruction excuter, par rapport au segment adress par CS. La combinaison de ces deux registres (i.e. CS:IP) suffit donc connatre ladresse absolue de cette instruction. Le processeur peut alors aller la chercher en mmoire et lexcuter. De plus, il actualise IP en lincrmentant de la taille de linstruction en octets. Tout comme CS, il est impossible de modifier IP directement. Le registre SP dsigne le sommet de la pile. Il faut bien comprendre le fonctionnement de la pile, aussi allons-nous insister sur ce point. La pile ne peut stocker que des mots. On appelle un mot ( word en anglais) un nombre cod sur deux octets (soit 16 bits). Prenons un exemple simple : un programme COM. Le segment de pile (adress par SS) et le segment de code ne font quun. Avant lexcution, SP vaut FFFE. Cest loffset de la dernire donne de 16 bits empile, par rapport SS bien sr. Pourquoi FFFE ? Tout simplement parce que la pile se remplit lenvers, cest--dire en partant de la fin du segment et en remontant vers le dbut. Le premier mot empil se trouve loffset FFFE. Il tient sur deux octets : loctet FFFE et loctet FFFF. Mais comment se fait-il quun mot soit dj empil avant le dbut du programme ? Ce mot est un zro que le DOS place sur la pile avant lexcution de tout programme COM. Nous en verrons la raison plus tard. A prsent, que se passe-t-il si un instant quelconque une instruction ordonne au processeur dempiler un mot ? Eh bien le stack pointer sera dcrment de 2 et le mot sera copi lendroit point par SP. Rappelez-vous que la pile se remplit lenvers ! Cest pour cette raison que SP est dcrment chaque empilage et non pas incrment. Un petit exemple pour rendre les choses plus concrtes : PUSH AX Leffet de cette instruction est dempiler le mot contenu dans le registre AX. Autrement dit, SP est automatiquement dcrment de 2, puis AX est copi ladresse SS:SP. Lors du dpilage, le mot situ au sommet de la pile, cest--dire le mot adress par SS:SP, est transfr dans un registre quelconque choisi par le programmeur, aprs quoi le stack pointer est incrment de 2. Exemple : POP BX Cette fois, on retire le dernier mot empil pour le placer dans le registre BX. Evidemment, SP sera incrment de 2 aussitt aprs. La pile est extrmement utile lorsquil sagit de stocker provisoirement le contenu dun registre qui doit tre modifi. Exemple :

Il est important de comprendre quon ne peut dpiler que le mot qui se trouve au sommet de la pile. Le premier mot empil est le dernier qui sera dpil. La pile doit tre manipule avec une extrme prcaution. Un dpilage injustifi fait planter la machine presque systmatiquement. Les trois derniers registres sont beaucoup moins lis au fonctionnement interne du processeur. Ils sont mis la disposition du programmeur qui peut les modifier sa guise et les utiliser comme des registres gnraux. Comme ces derniers cependant, ils ont une fonction qui leur est propre : servir dindex (SI et DI) ou de base (BP). Nous allons expliciter ces deux termes. Dans la mmoire, les octets se suivent et forment parfois des chanes de caractres. Pour utiliser une chane, le programmeur doit pouvoir accder facilement tous ses octets, lun aprs lautre. Or pour effectuer une opration quelconque sur un octet, il faut connatre son adresse. Cette adresse doit en gnral tre une constante valuable par le compilateur. Pourquoi une constante ? Parce que ladresse est une oprande comme les autres, elle se trouve immdiatement aprs lopcode et doit donc avoir une valeur numrique fixe ! Prenons un exemple : MOV AH, [MonOctet] Pas de panique ! Cette instruction en assembleur signifie Mettre dans AH la valeur de loctet adress par le label MonOctet ! . A la compilation, MonOctet sera remplac par la valeur numrique qu'il reprsente et on obiendra alors une instruction en langage machine telle que : 8A260601 8A26 est lopcode (hexa) de linstruction MOV AH, [constante quelconque], et 0601 est loffset de MonOctet. Il serait pourtant fastidieux, dans le cas dune chane de 112 caractres, de traiter les octets avec 112 instructions dans lesquelles seule ladresse changerait. Il faudrait pouvoir faire une boucle sur ladresse, mais alors celle-ci ne serait plus une constante, do le problme. Pour les constructeurs du microprocesseur, la seule solution tait de crer de nouveaux opcodes pour chaque opration portant sur un octet en mmoire. Ces opcodes spciaux feraient la mme action que ceux dont ils seraient drivs, mais ladresse passe en paramtre serait alors considre comme un dcalage par rapport un registre spcial. Il suffirait donc de faire varier ce registre, et le processeur y ajouterait automatiquement la valeur de loprande pour obtenir ladresse relle ! Cest cela que servent SI, DI et BP. Par exemple :

MOV AH, [MonOctet + DI] sera cod : 8AA50601 8AA5 est lopcode pour linstruction MOV AH, [constante quelconque + DI]. Remarque : les registres SI et BP auraient tout aussi bien pu tre employs, mais pas les registres gnraux, SAUF BX. En effet, BX peut jouer exactement le mme rle que BP. Noubliez pas que BX est appel registre de base , et que BP signifie Base Pointer. Nous verrons la diffrence entre une base et un index lorsque nous commencerons lassembleur.

5. Le registre des indicateurs


Un programme doit pouvoir faire des choix en fonction des donnes dont il dispose. Pour cela, il lui faut par exemple comparer des nombres, examiner leur signe, dcouvrir si une erreur a t constate, etc Il existe cet effet de petits indicateurs, les flags qui sont des bits spciaux ayant une signification trs prcise. De manire gnrale, les flags fournissent des informations sur les rsultats des oprations prcdentes. Ils sont tous regroups dans un registre : le registre des indicateurs. Comprenez bien que chaque bit a un rle qui lui est propre et que la valeur globale du registre ne signifie rien. Le programmeur peut lire chacun de ces flags et parfois modifier leur valeur directement. En mode rel, certains flags ne sont pas accessibles. Nous nen parlerons pas. Nous ne commenterons que les flags couramment utiliss. Nous verrons quelle utilisation on peut faire de ces indicateurs dans la troisime partie de ce tutoriel. CF ( Carry Flag ) est lindicateur de retenue. Il est positionn 1 si et seulement si lopration prcdemment effectue a produit une retenue. De nombreuses fonctions du DOS lutilisent comme indicateur derreur : CF passe alors 1 en cas de problme. PF ( Parity Flag ) renseigne sur la parit du rsultat. Il vaut 1 ssi ce dernier est pair. AF ( Auxiliary Carry Flag ) est peu utilis. ZF ( Zero Flag ) passe 1 ssi le rsultat dune opration est gal zro. SF ( Sign Flag ) passe 1 ssi le rsultat dune opration sur des nombres signs est ngatif. TF ( Trap Flag ) est utilis pour le dbuggage dun programme. Sil vaut 1, une routine spciale du dbuggeur est appele aprs lexcution de chaque instruction par le processeur. IF ( Interrupt Flag ) sert empcher les appels dinterruptions lorsquil est positionn 1. Cependant, toutes les interruptions ne sont pas masquables .

DF ( Direction Flag ) est utilis pour les oprations sur les chanes de caractres. Sil vaut 1, celles-ci seront parcourues dans le sens des adresses dcroissantes, sinon les adresses seront croissantes. OF ( Overflow Flag ) indique quun dbordement sest produit, cest--dire que la capacit de stockage a t dpasse. Il est utile en arithmtique signe. Avec des nombres non signs, il faut utiliser ZF et SF. Remarque : Les notations CF, PF, AF, etc ne sont pas reconnues par lassembleur. Pour utiliser les flags, il existe des instructions spcifiques que nous dcrirons plus tard.

IV. LES INTERRUPTIONS 1. Introduction


Le microprocesseur ne peut excuter quune seule instruction la fois. Pour connatre son adresse, il utilise le couple de registres CS:IP dont la valeur est incrmente automatiquement. Par consquent, le code du programme courant est excut de manire linaire. Imaginons cependant quun vnement extrieur demande lattention de lordinateur, par exemple la pression dune touche du clavier. La machine doit pouvoir ragir immdiatement, sans attendre que le programme en cours dexcution se termine. Pour cela, elle interrompt ce dernier pendant un bref instant, le temps de traiter lvnement survenu puis rend le contrle au programme interrompu. Une interruption nest rien dautre que lappel dune routine spciale prsente en mmoire appele ISR ( Interrupt Service Routine ). Les interruptions se divisent en trois catgories :
les les les

interruptions lectroniques, par exemple : le clavier interruptions du BIOS, par exemple : laccs aux disques interruptions du DOS, par exemple : laccs aux systmes de fichiers

Comment sont-elles dclenches ? Une interruption peut tre dclenche par votre matriel. Cest ce qui arrive lorsque vous appuyez sur une touche du clavier. Aucun logiciel nintervient et le contrle est pass directement la routine qui gre le clavier : ce sont les interruptions matrielles. Les interruptions logicielles sont quant elles appeles par des instructions en langage machine au sein dun programme. Leur importance est capitale. Rappelez-vous que contrairement au PASCAL ou au C, lassembleur ne dispose pas de fonction prprogramme. Chaque instruction doit tre directement traduisible en langage machine. Mais alors, comment fait-on pour crire une chane de caractres lcran ? Ou bien pour lire un caractre entr au clavier ? Eh bien on le fait de la mme faon que le DOS lui-mme ! On dclenche les interruptions appropries laide de linstruction INT du langage machine. Cest donc une routine du DOS (ou parfois du BIOS) qui fera tout le travail. Les paramtres (ou leurs adresses) sont passs dans les registres. Voici un petit exemple en assembleur qui crit la lettre A lcran :

Examinons-le ligne par ligne :


linstruction

MOV DL, A demande au processeur de mettre dans le registre DL le code ASCII de la lettre A, cest--dire 65, ou 41h. AH, 02 : mettre le nombre 2 dans AH.

MOV Enfin,

la dernire instruction appelle linterruption numro 21h. Il existe 256 interruptions. Toutes sont notes en base hexadcimale.

Explications : Comme vous aurez trs vite loccasion de vous en rendre compte, linterruption 21h est linterruption du DOS par excellence. Elle permet dappeler de nombreuses fonctions trs diverses. Pour cela, il suffit de mentionner leur numro dans le registre AH. Il est trs difficile de mmoriser le rle de chaque interruption, et a fortiori de chaque fonction ou sous-fonction, dautant plus delles sont dsignes par des numros hexadcimaux et quelles attendent des paramtres dans des registres prcis. Cest pourquoi tout programmeur se doit davoir sa disposition une liste des interruptions pour travailler. Celle de Ralph Brown est trs connue, et vous la trouverez sur lInternet. Revenons notre exemple. La fonction numro 2 de linterruption 21h sert crire un caractre lcran. Il faut pour cela crire le code ASCII du caractre dans le registre DL et bien sr placer le nombre 2 dans AH. Une fois que AH et DL ont t ajusts, linterruption 21h peut tre appele laide de linstruction INT. Dautres interruptions ne remplissent quune seule tche. Vous navez donc pas besoin de mettre un numro de fonction dans AH. Lappel de linterruption suffit.

2. La table des vecteurs dinterruptions


A chaque appel dinterruption, lordinateur doit pouvoir trouver ladresse de lISR correspondante. Pour cela, il dispose de la table des vecteurs dinterruptions (TVI, ou IVT : Interrupt Vector Table ). Cette table est implante ladresse 0000:0000 cest--dire au dbut de la RAM. La table est organise comme suit : Adresse 0000:0000 0000:0002 Taille (octets) 2 2 Valeur Adresse doffset de linterruption numro 0 Adresse de segment de linterruption numro 0

0000:0004 0000:0006 0000:0008 0000:000A 0000:000C 0000:000E

2 2 2 2 2 2

Adresse doffset de linterruption numro 1 Adresse de segment de linterruption numro 1 Adresse doffset de linterruption numro 2 Adresse de segment de linterruption numro 2 Adresse doffset de linterruption numro 3 Adresse de segment de linterruption numro 3 etc etc etc Adresse doffset de linterruption numro 255 Adresse de segment de linterruption numro 255

0000:03FC 0000:03FE

2 2

La raison pour laquelle les offsets prcdent les adresses de segment vient du codage en little endian utilis par INTEL. Les processeurs de cette marque (contrairement la plupart des autres, qui travaillent en big endian ) ont une reprsentation des donnes en mmoire aussi curieuse quinsupportable pour le programmeur : ils placent le poids fort aprs le poids faible. Ainsi, le mot 4A28h sera cod 284Ah. Puisque ladresse de lISR tient sur 32 bits (16 + 16), elle est reprsente comme un double mot ( dword ), donc ladresse doffset, qui est le mot de poids faible, se trouve au dbut. Eh oui, cest pnible, mais il faudra sy faire ! Remarque : pour calculer ladresse de lentre dans la TVI correspondant linterruption numro X, il suffit de multiplier X par 4. Exemple : ladresse de lISR numro 21h est stocke 0000:0084.

3. Sauvegarde de ltat des registres lors de lappel


Un appel dinterruption obit certaines rgles, car il est indispensable, une fois lISR excute, que le programme interrompu retrouve les registres dans le mme tat quils taient auparavant. Tout doit se passer comme si linterruption navait jamais eu lieu. Cest pourquoi avant de faire un saut lISR pointe par lentre correspondante dans la TVI, lordinateur sauvegarde tous les registres sur la pile courante. Il restaurera leur contenu avant de rendre le contrle. Cette procdure est automatique. Il nincombe pas au programmeur de prendre toutes ces prcautions.

DEUXIEME PARTIE
PREMIER CONTACT AVEC LE LANGAGE ASSEMBLEUR

Cette partie a pour but de vous prsenter larchitecture du langage assembleur travers de courts exemples. Ne vous inquitez pas si vous ne comprenez pas parfaitement certaines instructions : toutes seront dtailles dans la troisime partie. Lessentiel est que vous compreniez grossirement ce quon fait et pourquoi on le fait. Les explications qui accompagnent ces exemples devraient y suffire. Vous pourrez ensuite apprendre le langage en lui-mme en consultant la partie suivante.

Remarques pratiques prliminaires :


Les

mots qui sont imprims en italique sont ceux qui ne font pas partie du langage en luimme. Ils sont choisis par le programmeur. les programmes prsents ci-dessous suivent la syntaxe du compilateur TASM. Il existe de trs lgres diffrences dun compilateur lautre. code peut tre crit en majuscules ou en minuscules. Chaque mot est spar des autres par des espaces ou des tabulations. commentaires sont prcds du signe ;.

Tous

Le

Les Les

nombres doivent toujours commencer par un chiffre (entre 0 et 9), mme les nombres hexadcimaux. Il faut donc crire 0F2Ah et non pas F2Ah. Par contre, lcriture 5CFh est correcte.

Les

apostrophes et les guillemets sont quivalents. Il est cependant plus commode de rserver lusage des guillemets aux chanes de plusieurs caractres et celui des apostrophes aux caractres isols. pouvez taper vos programmes avec lditeur de texte du DOS (EDIT.COM). Donnezleur lextension .asm. compilation se fait en tapant TASM /m9 MONPROG si votre source sappelle MONPROG.ASM. Le paramtre /m9, facultatif, indique au compilateur quil devra effectuer 9 passes, cest--dire quil examinera 9 fois le code source. Comme chaque examen se fait de manire linaire, le compilateur trouve parfois des instructions qui font rfrence des labels placs plus loin dans le programme. Il manque donc dinformations, mais il continue son examen jusqu la fin. Quand il a termin, il recommence tout depuis le dbut pour rsoudre les problmes qui staient poss. La compilation cre un fichier objet (.obj). Pour obtenir un fichier EXE, tapez TLINK MONPROG. Pour un fichier COM, tapez TLINK /tdc MONPROG. Aprs ldition des liens (le linkage ), vous pouvez supprimer les fichiers

Vous

La

MONPROG.obj et MONPROG.map.
Il

est possible de crer un fichier BAT qui soccupe de toutes ces tapes. Ouvrez lditeur EDIT du DOS et tapez un programme tel que celui-ci : @ECHO OFF TASM /m9 %1.asm IF NOT EXIST %1.obj GOTO FIN TLINK %1.obj REM : ajouter ici /tdc pour obtenir un fichier COM ERASE %1.map ERASE %1.obj :FIN Enregistrez-le et nommez-le MAKE.BAT. Vous pouvez compiler et linker en tapant MAKE MONPROG. Pour compiler des fichiers COM, ajoutez le paramtre '/tdc' la commande TLINK.

Pour

pouvoir lancer TASM et TLINK quel que soit le dossier courant, changez la variable PATH ainsi : PATH = %path%;c:\MonChemin\DossierTASM Vous pouvez inclure cette ligne la fin de votre fichier AUTOEXEC.BAT afin quelle soit excute chaque dmarrage.

Vous

pouvez dbugger vos programmes (par exemple les excuter instruction par instruction en observant les changements induits dans la RAM et dans les registres,...) avec le logiciel Turbo Debugger 16/32 bits qui est trs pratique et trs performant. A dfaut, vous pouvez vous rabattre sur l'archaque DEBUG.COM (il se trouve dans votre dossier de commandes DOS). Mais alors bon courage !

Le seul travail du compilateur (et du linkeur) est de convertir chacune de vos instructions en son quivalent en langage machine. Le programme compil prsentera donc exactement la mme structure et la mme linarit que votre code source.

I. PREMIER EXEMPLE : LES FICHIERS COM


Voici un petit programme COM qui crit le message Bonjour, monde ! lcran.

Ce code source commence par des directives. Une directive est une information que le programmeur fournit au compilateur. Elle nest pas transforme en une instruction en langage machine. Elle najoute donc aucun octet au programme compil. La directive .386 indique au compilateur que le programme est destin tourner sur des processeurs INTEL de modle 386 (ou suprieur). Cela nous autorise utiliser certaines instructions qui ne sont pas disponibles sur les modles antrieurs, comme PUSHA ou POPA. Dans cet exemple, cette directive aurait trs bien pu tre omise. La ligne code segment use16 sert dclarer un segment que lon appelle code. On aurait tout aussi bien pu le nommer marteau ou voiture. Ce sera le segment de notre programme. Noubliez pas quun fichier COM ne peut comporter quun seul segment. Cette ligne ne sera pas compile : elle ne sert qu indiquer au compilateur le dbut dun segment. Le mot use16 indique que les adresses de segment et doffset sont codes sur 16 bits et non sur 8 bits. Vous devez systmatiquement lcrire. La directive assume cs:code, ds:code, ss:code

informe le compilateur que tout au long du programme, CS, DS et SS pointeront de faon privilgie vers le segment code, ce qui est vident dailleurs puisque cest le seul segment Vous comprendrez le sens exact de assume dans la troisime partie du cours. Enfin, les mots org 100h signifient quil faudra ajouter 100h (soit 256) tous les offsets. Pourquoi ? Souvenez-vous de la structure dun programme COM en mmoire. Si vous ncrivez pas cette ligne, TASM considrera que le programme dbute loffset 0000. Or, lors de lexcution, le DOS le chargera aprs le PSP, cest--dire ladresse 100h. Cest pourquoi il est ncessaire de recalculer les offsets : loffset 0000 deviendra 0100. Cette directive est en quelque sorte le trait caractristique des fichiers COM. Nous en arrivons au programme proprement dit. Il commence par un label : debut : Lui non plus nest pas compil. Il ne sert qu reprsenter ladresse de linstruction qui le suit, cest--dire : mov ah, 09h Cette ligne demande au processeur de charger la valeur 9 dans le registre AH. Cest le numro de la fonction de linterruption 21h qui crit une chane de caractres lcran. Loffset de cette chane est attendu dans DX. Do la ligne suivante : mov dx, offset message Le mot-cl offset sert extraire loffset du label message qui reprsente quant lui ladresse du message crire (il contient donc une adresse de segment ET un offset). Ladresse de segment de la chane doit tre transmise dans DS. Mais il est inutile de changer ce registre, car il pointe dj vers notre segment. Il nous reste appeler linterruption 21h : int 21h et rendre la main au DOS : ret Lorsque nous aborderons les procdures, vous comprendrez mieux le sens de ce mot et ce quil fait exactement. Pour linstant, sachez simplement que seul un fichier COM peut se terminer avec cette instruction. Nous arrivons la ligne : message db Bonjour, monde !, $ Il sagit dune dfinition de donnes. Le mot db ( define byte ) signifie que le compilateur devra crire les octets qui suivent tels quils sont dans notre code source. Il va donc crire le code ASCII du B, puis celui du o, etc Il terminera en crivant le code ASCII du signe $.

Cest ainsi que la fonction 9 de linterruption 21h reconnat la fin de la chane crire. Si vous oubliez ce signe, elle crira tous les octets de la RAM jusqu ce quelle tombe par hasard sur lui. Le mot message plac en dbut de ligne est un label de donnes. Il reprsente ladresse du code ASCII du B. Remarquez quil ny a pas de caractre : aprs un label de donnes. La ligne code ends indique la fin du segment code, et enfin end debut informe le compilateur que le fichier est fini, tout comme le END. du PASCAL. Le nom du label debut est mentionn : ce sera le point dentre de notre programme. Cest vers lui que pointera CS:IP avant lexcution. Remarque : vous ntes pas tenu de rendre aux registres la valeur quils avaient au dbut de votre programme. De toute faon, avant de charger un programme, le DOS sauvegarde le contenu de tous les registres puis met le contenu des registres gnraux (ainsi que SI, DI et BP) zro. Il les restaurera quand vous lui rendrez la main.

II. DEUXIEME EXEMPLE : LES FICHIERS EXE


Le programme suivant est un programme EXE qui fait exactement la mme chose que lexemple prcdent.

Examinons-le ! Tout dabord, la directive org 100h

a disparu. En effet, lors de lexcution, CS pointera vers notre segment de code et non pas vers le PSP. Il est donc inutile de dcaler les offsets de 256. Remarquons que notre programme dispose de deux segments supplmentaires :
Le Le

segment data est destin contenir les donnes, cest--dire les variables. segment pile sera notre segment de pile.

Notre directive assume devient donc : assume cs:code, ds:data, ss:pile Ainsi, le compilateur est inform que DS pointera vers le segment data et SS vers pile. Les deux lignes suivantes, mov ax, data mov ds, ax servent initialiser le registre DS. Celui-ci pointe vers le PSP au dbut du programme mais nous voulons le faire pointer vers notre segment de donnes appel data. Cela est ncessaire puisque la fonction 9 de linterruption 21h attend ladresse de la chane dans le couple DS:DX et que notre message se trouve dans le segment de donnes. La premire instruction charge ladresse du segment data dans AX. La seconde transfre cette valeur de AX dans DS. Mais pourquoi diable utiliser AX comme intermdiaire ? Aprs tout, on pourrait crire : mov ds, data Eh bien non ! Pour la simple raison que DS est un registre de segment et quen tant que tel on ne peut pas lui charger de valeur immdiate. On appelle valeur immdiate toute constante tape directement dans linstruction ellemme. Exemples de chargement de valeurs immdiates : mov ax, 135 ;charge 135 dans AX mov bx, offset message ;charge loffset de message dans BX mov bx, offset fin offset debut ;charge le nombre doctets entre fin et debut dans BX mov es, 10 ;instruction illicite car ES est un registre de segment ! Remarque : une autre possibilit aurait t d'crire : PUSH AX (empiler AX) puis POP DS (dpiler le dernier nombre empil et le placer dans DS). Les trois lignes suivantes :

mov ah, 09h mov dx, offset message int 21h nont pas chang. Il nous faut galement terminer le programme par un appel de la fonction 4ch de linterruption 21h. Cest ainsi que se terminent les programmes EXE. mov ah, 4ch int 21h Remarque : on aurait galement pu crire : mov ax, 4c00h int 21h La seule diffrence est que AL est mis zro, ce qui indique au programme qui on rend le contrle (ici le DOS) que notre programme sest termin normalement. Les fichiers COM peuvent galement utiliser la fonction 4ch. Le segment de code se termine : code ends et le segment de donnes commence sa suite : data segment use16 message db Bonjour, monde !, $ data ends Il nous reste crire le segment de pile. Dans ce programme, il ntait pas absolument indispensable de le sparer du segment de code. Mais cest une bonne habitude de le faire. pile segment stack remplissage db 256 DUP (?) pile ends Le mot-cl stack indique que ce segment est le segment de pile. Les mots db 256 DUP (?) dclarent 256 octets non initialiss. Cest la matire de notre pile. Sachez que tout appel dinterruption se traduit par lempilage des flags et de CS:IP. Il est donc indispensable davoir une pile, mme si celle-ci peut ventuellement partager le mme segment que le code, comme dans un fichier COM. Mais dans un programme EXE, il vaut mieux rserver un segment la pile. Les 256 octets que nous dclarons ici indiquent seulement que la pile contient 256 octets. Ainsi, au dbut de lexcution, SS:SP pointera vers la fin de ces octets. Nous verrons ce que signifie le point dinterrogation dans la troisime partie.

La fin du fichier et le point dentre sont signals par : end debut Et voil ! Vous avez dcouvert lallure dun programme en assembleur. Nous pouvons donc prsent nous pencher sur ltude du langage.

TROISIEME PARTIE
LE LANGAGE ASSEMBLEUR

I. DEFINITION DE DONNEES ET ADRESSAGE 1. Les dfinitions de donnes


Les mots db ( define byte ), dw ( define word ), dd ( define double word ) permettent de dclarer et dinitialiser une variable. Il faut bien comprendre que leur seule action est dcrire les donnes dans lexcutable lendroit mme o elle se trouvent dans le code source. Pour accder ces donnes (appeles variables ), il suffit de connatre leur adresse. Pour cela, on peut les faire prcder dun label de donnes. Exemple : TOTO dw 1982 Dans la ligne prcdente, TOTO reprsente ladresse du nombre 1982 qui est dfini juste aprs. Comme ce nombre est cod sur deux octets (word = 16 bits), cest le premier octet qui est adress par TOTO. Le compilateur se contentera dcrire le nombre 1982 lendroit o se trouve la dclaration. Remarque : en C, on crirait ceci : int TOTO = 1982; En BASIC ou en PASCAL, cette dfinition na pas dquivalent, puisque les variables ne peuvent tre initialises lors de leur dclaration. Il est donc obligatoire dajouter une ligne de code pour le faire. Dans la partie prcdente, nous avons eu dfinir le message qui serait affich lcran. Voici la ligne que nous avons crite : message db Bonjour, monde !, $ Lorsquil rencontre une chane de caractres, le compilateur crit les codes ASCII de tous les caractres, les uns la suite des autres. Voici une autre manire dcrire cette dfinition de donnes. Le rsultat (i.e. le programme compil) est EXACTEMENT LE MME : message db 42h, 111, nj db our, mo db nde !$

Pour dfinir plusieurs fois la suite les mmes donnes, on utilise DUP ( duplicate ) de la manire suivante : TOTO db 100 dup(TOTO EST BEAU) Cela revient crire : TOTO db TOTO EST BEAU TOTO db TOTO EST BEAU TOTO db TOTO EST BEAU ; etc (100 fois) Il est frquent que de nombreuses donnes naient pas besoin dtre initialises une valeur prcise. Dans ce cas, on les regroupe la fin du programme et on les remplace par le caractre ?. Les adresses des labels seront calcules de la mme faon mais aucune donnes ne sera crite dans le fichier (et a fortiori dans la RAM). On dit que lon met ses variables sur le tas ( heap en anglais). La seule diffrence avec une dfinition classique est quau dbut de lexcution, nos variables nauront pas de valeur dfinie. Leurs valeurs seront alatoires en ce sens quon ne peut les connatre au moment de la compilation. Exemple :

Remarque : Si elles ne sont pas regroupes en fin de programme, le compilateur sera oblig d'crire les donnes dans le fichier afin de ne pas fausser les adresses des variables (ou du code) qui suivent. Il remplira alors les points dinterrogation avec des zros. Pour indiquer quun chiffre est not en base hexadcimale, on lui ajoute la lettre h. La lettre b signifie que le chiffre est cod en binaire, la lettre 'o' en octal et la lettre d en base dcimale (base par dfaut).

2. Ladressage
a) ladressage immdiat
On appelle adressage immdiat ladressage qui ne fait intervenir que des constantes. Considrons cette partie de programme qui stocke le nombre 125h dans une variable appele TOTO, lui ajoute 15 puis charge le rsultat dans AX :

La ligne mov word ptr ds:[TOTO], 125h charge le nombre 125h dans le mot de la RAM adress par DS et loffset de TOTO. La ligne suivante ajoute 15 au contenu de ce mot. Lexpression word ptr devant ladresse, obligatoire ici, indique la taille de la variable dans laquelle doit tre stock le nombre 125h. Si on avait mis dword ptr, ce nombre aurait t cod sur 32 bits (00000125h) au lieu de 16 bits (0125h) : on aurait donc cras les deux octets qui suivent la variable. Si on avait mis byte ptr, la compilation aurait t impossible car un octet ne peut contenir un nombre suprieur FFh. Le compilateur na en effet aucun moyen de connatre cette taille. La variable TOTO na pas de taille (malgr le mot dw) : ce nest en fait quun pointeur vers le premier octet du word quelle reprsente. En revanche, la troisime instruction ne fait pas apparatre lexpression word ptr. Cette fois-ci elle est facultative du fait que la destination (AX = 16 bits) impose la taille. On peut videmment remplacer TOTO par une constante numrique : mov word ptr ds:[004Ch], 125h

Le mot 125h sera alors crit ladresse DS:4C. Une question se pose prsent : que se passe-t-il si le programmeur ncrit pas le registre de segment dans ladresse ? Cest l quintervient la directive assume. Le compilateur va devoir trouver lui-mme quel registre lutilisateur a voulu sous-entendre. Si on a utilis un label, alors le segment sera celui dans lequel est dclar le label. Mais le compilateur veut un REGISTRE de segment. Il va donc prendre celui qui est cens pointer vers le bon segment et pour le savoir, il examine la directive assume. Voil pourquoi cette dernire peut nous pargner dcrire pour chaque variable lexpression ds:. Comprenez bien que cette directive ne sert rien dautre qu cela et quen aucune faon elle ne force les registres de segment prendre quelque valeur que ce soit.

b) ladressage index et/ou bas


Comme nous lavons dj expliqu, il est possible dutiliser des registres de base ou dindex pour adresser un octet. On appelle base les registres BX et BP et index les registres SI et DI. La diffrence est que la base est cense tre fixe tandis que lindex varie automatiquement lorsquon utilise certaines oprations, telles que MOVSB. Remarque : BX, BP, DI et SI peuvent tous tre utiliss comme des registres gnraux. Voici les adressages possibles:
Constante

seule (= adressage immdiat) : Exemples : MOV AH, byte ptr [TOTO] MOV BX, word ptr ds:[1045h] MOV ES:[10 + TOTO x 2], BL

Base

seule : Exemple : MOV dword ptr ds:[BP], 15

Index

seul : Exemple : MOV dword ptr es:[DI], 142

Base

+ Constante : Exemples : MOV byte ptr ds:[BP + 1], 12 MOV ds:[BX + (TOTO BOBO)/10], AX

Index

+ Constante : Exemples : MOV CX, [TOTO + DI] MOV AL, ds:[1 + SI]

Base

+ Index : Exemple : MOV ds:[BP + SI], AH

Base

+ Index + Constante : Exemple : MOV AX, word ptr [TOTO + BX + DI + 1]

Remarque : si la constante nest pas un label, il est parfois impratif de spcifier le registre de segment ! Tout dpend du contexte

II. SAUTS INCONDITIONNELS, PROCEDURES ET MACROS 1. Les sauts inconditionnels


Ce paragraphe rpond la question : Mais comment fait-on un GOTO en assembleur ? . Linstruction quivalente est JMP qui signifie jump . La syntaxe est JMP MonLabel La rfrence ltiquette MonLabel sera remplace lors de la compilation par la distance (signe) en octets qui spare linstruction qui suit immdiatement le JMP de linstruction adresse par MonLabel. En pratique, le JMP sutilise exactement comme un GOTO en BASIC. Cette instruction permet de faire un saut inconditionnel : le programme fera ce saut quoiquil arrive. Exemple :

Le mot short ajout aprs jmp indique au compilateur que le label COUCOU se trouve une distance (signe) qui peut tre stocke sur un seul octet. Le compilateur ne le sait pas encore lorsquil essaie de compiler linstruction de saut car le label se trouve en de de cette instruction. Cest pourquoi il prvoit deux octets pour crire le saut, au cas o ladresse darrive soit loigne de plus de 128 octets. Lorsquil effectue une deuxime passe , sil saperoit quun seul octet aurait suffi il remplit alors loctet inutile avec linstruction NOP ( No Operation ) qui ne fait rien du tout. Le programme marchera parfaitement (encore heureux !), mais cela gaspille un octet. Le programmeur a la possibilit daider le compilateur en ajoutant le mot short, ainsi un seul octet est prvu pour la distance de saut. Si le label est plac plus haut que l'instruction de saut, il est inutile de l'crire. Remarque : Ce mot peut galement tre utilis avec les instructions de saut conditionnel que nous tudierons plus loin.

2. Les procdures
a) appels de procdures
Ceux qui ont dj programm en BASIC connaissent les instructions GOSUB et RETURN. Leurs quivalents en assembleur sont CALL et RET.
Linstruction

CALL sert appeler une procdure :

Syntaxe CALL MonLabel Action : empile loffset de linstruction suivante puis fait un simple saut ladresse reprsente par MonLabel.
RET

(ou RETN) permet de retourner linstruction qui suit immdiatement le CALL :

Syntaxe : RET Action : dpile ladresse de retour et la met dans IP. Le programme continue donc ladresse qui suit le CALL. Remarque : Rappelez-vous quil est possible de terminer un programme COM avec linstruction RET. Puisque le DOS empile un zro de deux octets au chargement du programme, IP prendra la valeur 0000 lorsque le processeur excutera cette instruction : il pointera donc vers le dbut du PSP. Or le PSP commence toujours par les deux octets suivants : CDh 20h (ce qui scrit INT 20h en assembleur). Linterruption 20h, qui permet de terminer un programme COM, sera donc appele et le contrle sera rendu au DOS. Voici un exemple dutilisation des procdures aussi simple que possible : ce programme COM appelle 12 fois une procdure qui crit un message lcran et rend la main au DOS. Il nest daucune utilit et nest pas optimis du tout.

Remarque : Les codes ASCII 10 et 13 reprsentent respectivement la fin de ligne et le retour chariot. Grce eux, on revient la ligne chaque fois quon a crit le message. Ce programme fonctionne parfaitement. Toutefois, les conventions dcriture veulent que les procdures soient crites comme suit :

Le programme compil est toujours le mme, mais le code est plus lisible puisqu'on distingue

les procdures des simples labels. Le mot near signifie que ladresse de cette procdure est rduite un offset. Il ny a pas dadresse de segment. La procdure ne pourra donc tre appele que de lintrieur mme du segment. Le mot qui a le sens contraire de near est far. Les call far sont assez peu utiliss.

b) le passage des paramtres


Il existe deux moyens de passer des paramtres une procdure : les registres et la pile.
Le

passage par registres :

Il consiste transmettre les paramtres dans des registres convenus lavance, par exemple AX et BX. Les deux gros avantages de cette mthode sont sa simplicit et la vitesse dexcution. Linconvnient majeur est le nombre limit de registres, dautant plus quau moment de lappel, certains dentre eux ne seront peut-tre pas disponibles.
Le

passage par la pile :

Cest la mthode quutilisent les langages de haut niveau tels que le C ou le PASCAL. Avant lappel, on empile les paramtres un un. La procdure appele se chargera de les lire. Pour cela on utilise le registre BP de la manire suivante : on transfre la valeur de SP dans BP laide de linstruction MOV BP, SP. Ladresse de retour (qui sera dpile quand le processeur rencontrera l'instruction RET) se trouve ladresse SS:[BP], le dernier paramtre est adress par SS:[BP + 2], lavant-dernier par SS:[BP + 4], etc On peut ainsi lire nimporte quel paramtre sans le dpiler. Attention cependant ! A la fin de la procdure, il faudra tout de mme rendre SP la valeur quil avait avant lempilage des paramtres. Pour cela, on fait suivre linstruction RET du nombre de paramtres, multipli par 2 (car chaque paramtre comporte deux octets). Exemple :

Soyez toujours trs vigilant avec les appels de procdures : pensez que ladresse de retour sera dpile lorsque le programme rencontrera linstruction RET. Il serait donc suicidaire de laisser une donne empile avant dappeler cette instruction.

3. Les macros
Etant donn que certaines instructions se rptent constamment dans un programme, lcriture de macrofonctions (ou macros) est un moyen pratique de rendre votre code source plus lisible. Il est possible de choisir pour certaines suites dinstructions un nom qui les reprsente. Lorsque le compilateur (en fait, le prprocesseur) rencontrera ce nom dans votre code source, il le remplacera par les lignes de code quil dsigne. Ces lignes forment une macro . Les macros, la diffrence des procdures, nont aucune signification pour la machine. Seul le compilateur comprend leur signification. Elles ne sont quun artifice mis la disposition du programmeur pour clarifier son programme. Lorsque le compilateur rencontre le nom dune macro dans votre code, il le remplace par le code de la macro. Tout se passe exactement comme si vous aviez tap vous-mme ce code la place du nom de la macro. Ainsi, si vous appelez quinze fois une macro dans votre programme, le compilateur crira quinze fois le code de cette macro. Cest toute la diffrence avec les procdures qui ne sont crites quune seule fois mais peuvent tre appeles aussi souvent quon veut laide dun CALL. Voici comment crire une macro : lexemple suivant sert crire un message lcran.

Le code prcdent peut tre crit nimporte o dans votre programme, condition quil se trouve avant tout appel de cette macro. Afin dviter les ennuis, il est fortement conseill de runir vos macros au dbut du code, avant toute autre ligne. De toute faon, il ne sera pas compil lendroit o vous lavez crit mais aux endroits o se trouvent les appels de macros. Le mot text? est un paramtre . Le point dinterrogation nest pas requis ; nous lavons mis pour indiquer quil sagit dun paramtre et non dune variable. Une macro peut utiliser plusieurs paramtres spars par des virgules. Pour appeler cette macro, il vous suffit dcrire la ligne ecrit_texte Coucou ! Ceci est un essai ! Le compilateur se chargera alors de la remplacer par les instructions comprises entre la premire et la dernire ligne de cet exemple, en prenant le soin de remplacer le mot text? par le message fourni en paramtre. En assembleur, chaque label doit avoir un nom unique. Or, si une macro est appele plusieurs fois, les mmes noms seront utiliss. Il faut donc la plupart du temps inclure la directive LOCAL qui forcera le compilateur changer le nom des labels chaque appel de la macro. Attention : cette directive doit suivre immdiatement la dclaration de la macro. Supposons prsent que lon veuille crire lcran le message Je suis bien content et revenir la ligne laide de notre macro ecrit_texte. La syntaxe suivante : ecrit_texte Coucou ! Ceci est un essai !, 10, 13 est incorrecte, car le compilateur croirait que lon a crit trois paramtres ! Il faut alors entourer notre unique paramtre par les signes < et > :

ecrit_texte <Coucou ! Ceci est un essai !, 10, 13>

4. La directive EQU
La directive EQU a un rle voisin de celui des macros. Elle permet de remplacer un simple mot par dautres plus complexes. Son intrt est quelle peut tre invoque en plein milieu dune ligne. Quelques exemples : Longueur EQU (fin debut) Message EQU Bonjour messieurs ! Comment allez-vous ?, $ Version EQU 2 Quitter EQU ret Quitter2 EQU int 20h Mettre_dans_AH EQU mov ah, Interruption_21h EQU int 21h Un programme qui contient de telles directives peut se terminer ainsi : Mettre_dans_AH 4Ch Interruption_21h Ou ainsi (si cest un COM) : Quitter2

5. Linclusion de fichiers
Il est possible daccder des procdures, des macros ou des dfinitions EQU qui se trouvent dans dautres fichiers. Cela permet de se constituer des librairies de macros ou de procdures que lon peut rutiliser dun programme lautre. Pour inclure le fichier TOTO.LIB, crivez au dbut de votre code source :

La condition if1 indique au compilateur que linclusion ne doit seffectuer que lors de la premire passe. Le fichier TOTO.LIB est un fichier texte tout fait banal qui contient des lignes de code en assembleur.

III. LES MACHINE

PRINCIPALES

INSTRUCTIONS

DU

LANGAGE

Remarques prliminaires :
Le

principe du langage assembleur est de remplacer chaque opcode hexadcimal par mot facile retenir. Ce mot est appel mnmonique. Par exemple, INT est mnmonique associ lopcode CDh. Chaque fois que le compilateur rencontrera mot, il le remplacera par loctet CDh et crira ensuite loprande (ici : le numro linterruption) en hexadcimal.

un le ce de

Cette

liste rcapitule les instructions que nous connaissons dj et en prsente de nouvelles. Elle nest pas exhaustive mais vous sera amplement suffisante pour la plupart de vos programmes. instructions, comme PUSHA, ne sont disponibles que pour des modles de processeurs plus volus que le 8086, par exemple le 286. Noubliez pas la directive .386 si vous les utilisez.

Certaines

1. Linstruction NOP ( No Operation )


Syntaxe : NOP Description : Ne fait rien ! Mais alors RIEN ! Que dalle ! Niet !

2. Linstruction MOV ( Move )


Syntaxe : MOV Destination, Source Description : Copie le contenu de Source dans Destination. Mouvements autoriss : MOV Registre gnral, Registre quelconque MOV Mmoire, Registre quelconque MOV Registre gnral, Mmoire MOV Registre gnral, Constante MOV Mmoire, Constante MOV Registre de segment, Registre gnral Remarques : Source et Destination doivent avoir la mme taille. On ne peut charger dans un registre de segment que le contenu dun registre gnral (SI, DI et BP sont considrs ici comme des registres gnraux). Exemples : MOV AX, 5 MOV ES, DX MOV AL, [Variable1] ;Copie un octet car AL contient 8 bits

MOV [Variable2], DS ;Copie un word car DS contient 16 bits MOV word ptr [Variable3], 12 ;Ici, on spcifie que la variable est un word

3. Linstruction XCHG ( Exchange )


Syntaxe : XCHG Destination, Source Description : Echange les contenus de Source et de Destination. Mouvements autoriss : XCHG Registre gnral, Registre gnral XCHG Registre gnral, Mmoire XCHG Mmoire, Registre gnral

4. Linstruction JMP ( Jump )


Syntaxe : JMP MonLabel Description : Saute linstruction pointe par MonLabel.

5. Loprateur CMP ( Compare )


Syntaxe : CMP Destination, Source Description : Cet oprateur sert comparer deux nombres : Source et Destination. C'est le registre des indicateurs qui contient les rsultats de la comparaison. Ni Source ni Destination ne sont modifis. Indicateurs affects : AF, CF, OF, PF, SF, ZF Remarque : Cet oprateur effectue en fait une soustraction mais contrairement SUB, le rsultat nest pas sauvegard. Le programme doit pouvoir ragir en fonction des rsultats de la comparaison. Pour cela, on utilise les sauts conditionnels (voir ci-dessous).

6. Les instructions de saut conditionnel


Les sauts conditionnels sont terriblement importants car ils permettent au programme de faire des choix en fonction des donnes. Un saut conditionnel nest effectu qu certaines conditions portant sur les flags (par exemple : CF = 1 ou ZF = 0). Certains mnmoniques de sauts conditionnels sont totalement quivalents, cest--dire quils reprsentent le mme opcode hexadcimal. Cest pour aider le programmeur quils existent parfois sous plusieurs formes.

a) les sauts de comparaison

JE

( Jump if Equal ) fait un saut au label spcifi si et seulement si ZF = 1. Rappelezvous que ce flag est 1 si et seulement si le rsultat de lopration prcdente vaut zro. Comme CMP ralise une soustraction, on utilise gnralement JE pour savoir si deux nombres sont gaux.

Exemple :

Mnmonique quivalent : JZ ( Jump if Zero )


JG

( Jump if Greater ) fait un saut au label spcifi si et seulement si ZF = 0 et SF = OF. On lutilise en arithmtique signe pour savoir si un nombre est suprieur un autre.

Exemple :

Mnmonique quivalent : JNLE ( Jump if Not Less Or Equal )


JGE

( Jump if Greater or Equal ) fait un saut au label spcifi si et seulement si SF = OF. On lutilise en arithmtique signe pour savoir si un nombre est suprieur ou gal un autre.

Mnmonique quivalent : JNL ( Jump if Not Less )


JL

( Jump if Less ) fait un saut au label spcifi si et seulement si SF <> OF. On lutilise en arithmtique signe pour savoir si un nombre est infrieur un autre.

Mnmonique quivalent : JNGE ( Jump if Not Greater Or Equal )


JLE

( Jump if Less Or Equal ) fait un saut au label spcifi si et seulement si SF <> OF ou ZF = 1. On lutilise en arithmtique signe pour savoir si un nombre est infrieur ou gal un autre.

Mnmonique quivalent : JNG ( Jump if Not Greater )


JA

( Jump if Above ) fait un saut au label spcifi si et seulement si ZF = 0 et CF = 0. On lutilise en arithmtique non signe pour savoir si un nombre est suprieur un autre.

Mnmonique quivalent : JNBE ( Jump if Not Below Or Equal )


JAE

( Jump if Above or Equal ) fait un saut au label spcifi si et seulement si CF = 0. On lutilise en arithmtique non signe pour savoir si un nombre est suprieur ou gal un autre.

Mnmonique quivalent : JNB ( Jump if Not Below )


JB

( Jump if Below ) fait un saut au label spcifi si et seulement si CF = 1. On lutilise en arithmtique non signe pour savoir si un nombre est infrieur un autre.

Mnmonique quivalent : JNAE ( Jump if Not Above Or Equal )


JBE

( Jump if Below or Equal ) fait un saut au label spcifi si et seulement si CF = 1 ou ZF = 1. On lutilise en arithmtique non signe pour savoir si un nombre est infrieur ou gal un autre.

Mnmonique quivalent : JNA ( Jump if Not Above )

b) les sauts de test sur les flags


Ces instructions testent un flag unique et excutent ou non le saut selon la valeur de ce flag.
JC

( Jump if Carry ) fait un saut au label spcifi si et seulement si CF = 1.

Remarques : Ce mnmonique correspond au mme opcode que JB. Il est souvent employ pour vrifier que lappel dune interruption na pas dclench derreur. Exemple :

Si lappel de la fonction 3Eh de linterruption 21H se solde par une erreur, alors la CF vaudra 1 et le saut sera accompli. Dans le cas oppos, lexcution continuera normalement de manire linaire.
JNC JZ

( Jump if not Carry ) fait un saut au label spcifi si et seulement si CF = 0.

( Jump if Zero ) fait un saut au label spcifi si et seulement si ZF = 1. Ce mnmonique correspond au mme opcode que JE. ( Jump if not Zero ) fait un saut au label spcifi si et seulement si ZF = 0. Ce mnmonique correspond au mme opcode que JNE. ( Jump if Sign ) fait un saut au label spcifi si et seulement si SF = 1. ( Jump if not Sign ) fait un saut au label spcifi si et seulement si SF = 0.

JNZ

JS

JNS JO

( Jump if Overflow ) fait un saut au label spcifi si et seulement si OF = 1. ( Jump if not Overflow ) fait un saut au label spcifi si et seulement si OF = 0.

JNO JP

( Jump if Parity ) fait un saut au label spcifi si et seulement si PF = 1. ( Jump if not Parity ) fait un saut au label spcifi si et seulement si PF = 0.

JNP

c) le saut de test sur le registre CX


JCXZ ( Jump if CX = Zero ) fait un saut au label spcifi si et seulement si CX = 0.

7. Les instructions arithmtiques


a) linstruction INC ( Increment )
Syntaxe : INC Destination Description : Incrmente Destination.

Indicateurs affects : AF, OF, PF, SF, ZF Exemple : INC CL

b) linstruction ADD ( Addition )


Syntaxe : ADD Destination, Source Description : Ajoute Source Destination Indicateurs affects : AF, CF, OF, PF, SF, ZF Exemple : ADD byte ptr [VARIABLE + DI], 5

c) linstruction ADC ( Add with Carry )


Syntaxe : ADC Destination, Source Description : Ajoute (Source + CF) Destination. Indicateurs affects : AF, CF, OF, PF, SF, ZF

d) linstruction DEC ( Decrement )


Syntaxe : DEC Destination Description : Dcrmente Destination. Indicateurs affects : AF, OF, PF, SF, ZF

e) linstruction SUB ( Substract )


Syntaxe : SUB Destination, Source Description : Soustrait Source Destination. Indicateurs affects : AF, CF, OF, PF, SF, ZF

f) linstruction SBB ( Substract with Borrow )


Syntaxe : SBB Destination, Source Description : Soustrait (Source + CF) Destination. Indicateurs affects : AF, CF, OF, PF, SF, ZF

g) linstruction MUL ( Multiply )


Syntaxe : MUL Source Description : Effectue une multiplication dentiers non signs.

Si Si Si

Source est un octet : AL est multipli par Source et le rsultat est plac dans AX. Source est un mot : AX est multipli par Source et le rsultat est plac dans DX:AX.

Source est un double mot : EAX est multipli par Source et le rsultat est plac dans EDX:EAX.

Indicateurs affects : CF, OF Remarque : Source ne peut tre une valeur immdiate. Exemples : MUL CX MUL byte ptr [TOTO]

h) linstruction IMUL ( Integer Multiply )


Syntaxe : IMUL Source IMUL Destination, Source IMUL Destination, Source, Valeur Description : Effectue une multiplication dentiers signs. IMUL Source :
Si Si Si

Source est un octet : AL est multipli par Source et le rsultat est plac dans AX. Source est un mot : AX est multipli par Source et le rsultat est plac dans DX:AX.

Source est un double mot : EAX est multipli par Source et le rsultat est plac dans EDX:EAX.

IMUL Destination, Source : Multiplie Destination par Source et place le rsultat dans Destination. IMUL Destination, Source, Valeur : Multiplie Source par Valeur et place le rsultat dans Destination. Indicateurs affects : CF, OF

i) linstruction DIV ( Divide )


Syntaxe : DIV Source Description : Effectue une division euclidienne dentiers non signs.
Si

Source est un octet : AX est divis par Source, le quotient est plac dans AL et le reste dans AH. Source est un mot : DX:AX est divis par Source, le quotient est plac dans AX et le reste dans DX.

Si

Si

Source est un double mot : EDX:EAX est divis par Source, le quotient est plac dans EAX et le reste dans EDX.

Indicateurs affects : AF, OF, PF, SF, ZF Remarque : Source ne peut tre une valeur immdiate.

j) linstruction IDIV ( Integer Divide )


Syntaxe : IDIV Source Description : Effectue une division euclidienne dentiers signs.
Si

Source est un octet : AX est divis par Source, le quotient est plac dans AL et le reste dans AH. Source est un mot : DX:AX est divis par Source, le quotient est plac dans AX et le reste dans DX. Source est un double mot : EDX:EAX est divis par Source, le quotient est plac dans EAX et le reste dans EDX.

Si

Si

Indicateurs affects : AF, CF, OF, PF, SF, ZF

k) linstruction NEG ( Negation )


Syntaxe : NEG Destination Description : Forme le complment 2 de Destination, i.e. prend loppos de Destination. Indicateurs affects : AF, CF, OF, PF, SF, ZF Remarque : A ne pas confondre avec NOT, qui forme le complment 1.

8. Les instructions logiques


a) linstruction NOT ( Logical NOT )
Syntaxe : NOT Destination Description : Effectue un NON logique bit bit sur Destination (i.e. chaque bit de Destination est invers).

b) linstruction OR ( Logical OR )
Syntaxe : OR Destination, Source Description : Effectue un OU logique inclusif bit bit entre Destination et Source. Le rsultat est stock dans Destination. Indicateurs affects : CF, OF, PF, SF, ZF

Remarque : Afin doptimiser la taille et les performances du programme, on peut utiliser linstruction OR AX, AX la place de CMP AX, 0. En effet, un OU bit bit entre deux nombres identiques ne modifie pas Destination et est excut infiniment plus rapidement quune soustraction. Comme les flags sont affects, les sauts conditionnels sont possibles.

c) linstruction AND ( Logical AND )


Syntaxe : AND Destination, Source Description : Effectue un ET logique bit bit entre Destination et Source. Le rsultat est stock dans Destination. Indicateurs affects : CF, OF, PF, SF, ZF

d) linstruction TEST ( Test for bit pattern )


Syntaxe : TEST Destination, Source Description : Effectue un ET logique bit bit entre Destination et Source. Le rsultat nest pas conserv, donc Destination nest pas modifi. Seuls les flags sont affects. Cet oprateur est souvent utilis pour tester certains bits de Destination. Indicateurs affects : CF, OF, PF, SF, ZF Exemple :

e) linstruction XOR ( Exclusive logical OR )


Syntaxe : XOR Destination, Source Description : Effectue un OU logique exclusif bit bit entre Destination et Source. Le rsultat est stock dans Destination. Indicateurs affects : CF, OF, PF, SF, ZF Remarque : Pour remettre un registre zro, il est prfrable de faire XOR AX, AX que MOV AX, 0. En effet, le rsultat est le mme mais la taille et surtout la vitesse dexcution de

linstruction sont trs largement optimises.

f) linstruction SHL ( Shift logical Left )


Syntaxe : SHL Destination, Source Description : Dcale les bits de Destination de Source positions vers la gauche. Les bits les plus droite sont remplacs par des zros. Indicateurs affects : AF, CF, OF, PF, SF, ZF Exemple : SHL AX, 4 ;permet de multiplier par 16 de faon infiniment plus rapide que MUL Mnmonique quivalent : SAL ( Shift Arithmetical Left )

g) linstruction SHR ( Shift logical Right )


Syntaxe : SHR Destination, Source Description : Dcale les bits de Destination de Source positions vers la droite. Les bits les plus gauche sont remplacs par des zros. Indicateurs affects : AF, CF, OF, PF, SF, ZF Mnmonique quivalent : SAR ( Shift Arithmetical Right )

h) linstruction ROL ( Rotate Left )


Syntaxe : ROL Destination, Source Description : Effectue une rotation des bits de Destination de Source positions vers la gauche. Le dernier bit tre sorti gauche et tre rentr droite est plac dans CF. OF est mis 1 si et seulement si le signe de Destination a chang. Indicateurs affects : AF, CF, OF, PF, SF, ZF

i) linstruction ROR ( Rotate Right )


Syntaxe : ROR Destination, Source Description : Effectue une rotation des bits de Destination de Source positions vers la droite. Le dernier bit tre sorti droite et tre rentr gauche est plac dans CF. OF est mis 1 si et seulement si le signe de Destination a chang. Indicateurs affects : AF, CF, OF, PF, SF, ZF

j) linstruction RCL ( Rotate through Carry Left )


Syntaxe : RCL Destination, Source Description : Effectue une rotation des bits de Destination de Source positions vers la gauche. CF est utilis comme intermdiaire : chaque bit qui sort gauche est plac dans CF, et le

contenu de CF est ensuite rinsr droite. OF est mis 1 si et seulement si le signe de Destination a chang. Indicateurs affects : AF, CF, OF, PF, SF, ZF

k) linstruction RCR ( Rotate through Carry Right )


Syntaxe : RCR Destination, Source Description : Effectue une rotation des bits de Destination de Source positions vers la droite. CF est utilis comme intermdiaire : chaque bit qui sort droite est plac dans CF, et le contenu de CF est ensuite rinsr gauche. OF est mis 1 si et seulement si le signe de Destination a chang. Indicateurs affects : AF, CF, OF, PF, SF, ZF

9. Les instructions de manipulation des flags


a) linstruction CLC ( Clear Carry flag )
Syntaxe : CLC Description : Met CF 0. Indicateurs affects : CF

b) linstruction STC ( Set Carry flag )


Syntaxe : STC Description : Met CF 1. Indicateurs affects : CF

c) linstruction CLD ( Clear Direction flag )


Syntaxe : CLD Description : Met DF 0. Indicateurs affects : DF

d) linstruction STD ( Set Direction flag )


Syntaxe : STD Description : Met DF 1. Indicateurs affects : DF

e) linstruction CLI ( Clear Interrupt flag )

Syntaxe : CLI Description : Met IF 0. Indicateurs affects : IF

f) linstruction STI ( Set Interrupt flag )


Syntaxe : STI Description : Met IF 1. Indicateurs affects : IF

g) linstruction CMC ( Complement Carry flag )


Syntaxe : CMC Description : Inverse CF. Indicateurs affects : CF

h) linstruction LAHF ( Load AH from Flags )


Syntaxe : LAHF Description : Charge dans AH loctet de poids faible du registre des indicateurs.

i) linstruction SAHF ( Store AH into Flags )


Syntaxe : SAHF Description : Stocke les bits de AH dans le registre des indicateurs.

10. Les instructions de gestion de la pile a) linstruction PUSH ( Push Word onto Stack )
Syntaxe : PUSH Source Description : Empile le mot Source. SP est dcrment de 2. Remarques : Source ne peut tre une valeur immdiate. Il est possible dabrger votre code source en crivant par exemple PUSH AX BX BP. Le compilateur crira alors trois fois linstruction PUSH du langage machine. Il est possible galement dempiler des doubles mots.

b) linstruction POP ( Pop Word off Stack )


Syntaxe : POP Destination Description : Dpile le mot qui se trouve au sommet de la pile et le place dans Destination. SP

est incrment de 2.

c) linstruction PUSHF ( Push Flags onto Stack )


Syntaxe : PUSHF Description : Empile le registre des indicateurs. SP est dcrment de 2. Remarque : PUSHFD empile le registre des indicateurs cod sur 32 bits.

d) linstruction POPF ( Pop Flags off Stack )


Syntaxe : POPF Description : Dpile le mot qui se trouve au sommet de la pile et le place dans le registre des indicateurs. SP est incrment de 2. Indicateurs affects : Tous Remarque : POPFD est utilis pour un registre des indicateurs cod sur 32 bits.

e) linstruction PUSHA ( Push All registers onto Stack )


Syntaxe : PUSHA Description : Empile AX, BX, CX, DX, BP, SI, DI et SP. Remarque : PUSHAD est utilis pour des registres de 32 bits.

f) linstruction POPA ( Pop All registers off Stack )


Syntaxe : POPA Description : Restaure AX, BX, CX, DX, BP, SI, DI et SP partir de la pile. Remarque : POPAD est utilis pour des registres de 32 bits.

11. Les instructions de gestion des chanes doctets


a) linstruction MOVSB ( Move String Byte )
Syntaxe : MOVSB Description : Copie loctet adress par DS:SI ladresse ES:DI. Si DF = 0, alors DI et SI sont ensuite incrments, sinon ils sont dcrments. Remarque : Pour copier plusieurs octets, faire REP MOVSB ( Repeat Move String Byte ). Le nombre doctets copier doit tre transmis dans CX de mme que pour un LOOP. Exemple :

b) linstruction SCASB ( Scan String Byte )


Syntaxe : SCASB Description : Compare loctet adress par ES:DI avec AL. Les rsultats sont placs dans le registre des indicateurs. Si DF = 0, alors DI est ensuite incrment, sinon il est dcrment. Remarques : Pour comparer plusieurs octets, faire REP SCASB ou REPE SCASB ( Repeat until Egal ), ou encore REPZ SCASB ( Repeat until Zero ). Ces trois prfixes sont quivalents. Le nombre doctets comparer doit tre transmis dans CX. La boucle ainsi cre sarrte si CX = 0 ou si le caractre point par ES:DI est le mme que celui contenu dans AL (i.e. si ZF = 1). On peut ainsi rechercher un caractre dans une chane. Pour rpter au contraire la comparaison jusqu ce que ZF = 0, cest--dire jusqu ce que AL et le caractre adress par ES:DI diffrent, utiliser REPNE ou REPNZ. Exemple :

c) linstruction LODSB ( Load String Byte )


Syntaxe : LODSB Description : Charge dans AL loctet adress par DS:SI. Si DF = 0, alors SI est ensuite incrment, sinon il est dcrment. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour MOVSB.

d) linstruction STOSB ( Store String Byte )


Syntaxe : STOSB Description : Stocke le contenu de AL dans loctet adress par ES:DI. Si DF = 0, alors DI est ensuite incrment, sinon il est dcrment. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour LODSB.

e) linstruction CMPSB ( Compare String Byte )


Syntaxe : CMPSB Description : Compare loctet adress par DS:SI et celui adress par ES:DI. Si DF = 0, alors SI et DI sont ensuite incrments, sinon ils sont dcrments. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour SCASB.

12. Les instructions de gestion des chanes de mots


Ce sont les mmes que les prcdentes, hormis quelles traitent des mots et non des octets et que leur nom se termine par un W au lieu du B.

a) linstruction MOVSW ( Move String Word )


Syntaxe : MOVSW Description : Copie le mot adress par DS:SI ladresse ES:DI. Si DF = 0, alors DI et SI sont ensuite incrments de 2, sinon ils sont dcrments de 2. Remarque : Pour copier plusieurs mots, faire REP MOVSW. Le nombre de mots copier doit tre transmis dans CX.

b) linstruction SCASW ( Scan String Word )


Syntaxe : SCASW Description : Compare le mot adress par ES:DI avec AX. Les rsultats sont placs dans le registre des indicateurs. Si DF = 0, alors DI est ensuite incrment de 2, sinon il est dcrment de 2. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour SCASB.

c) linstruction LODSW ( Load String Word )


Syntaxe : LODSW Description : Charge dans AX le mot adress par DS:SI. Si DF = 0, alors SI est ensuite incrment de 2, sinon il est dcrment de 2. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour LODSB.

d) linstruction STOSW ( Store String Word )


Syntaxe : STOSW Description : Stocke le contenu de AX dans le mot adress par ES:DI. Si DF = 0, alors DI est ensuite incrment de 2, sinon il est dcrment de 2. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour STOSB.

e) linstruction CMPSW ( Compare String Word )


Syntaxe : CMPSW Description : Compare le mot adress par DS:SI et celui adress par ES:DI. Si DF = 0, alors SI et DI sont ensuite incrments de 2, sinon ils sont dcrments de 2. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour CMPSB.

13. Les instructions de gestion des chanes de doubles mots


Elles traitent des doubles mots et leur nom se termine par un D.

a) linstruction MOVSD ( Move String Double Word )


Syntaxe : MOVSD Description : Copie le double mot adress par DS:SI ladresse ES:DI. Si DF = 0, alors DI et SI sont ensuite incrments de 4, sinon ils sont dcrments de 4. Remarque : Pour copier plusieurs doubles mots, faire REP MOVSD. Le nombre de doubles mots copier doit tre transmis dans CX.

b) linstruction SCASD ( Scan String Double Word )


Syntaxe : SCASD Description : Compare le double mot adress par ES:DI avec EAX. Les rsultats sont placs dans le registre des indicateurs. Si DF = 0, alors DI est ensuite incrment de 4, sinon il est dcrment de 4. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour SCASB.

c) linstruction LODSD ( Load String Double Word )


Syntaxe : LODSD Description : Charge dans EAX le double mot adress par DS:SI. Si DF = 0, alors SI est ensuite incrment de 4, sinon il est dcrment de 4. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour LODSB.

d) linstruction STOSD ( Store String Double Word )


Syntaxe : STOSD Description : Stocke le contenu de EAX dans le double mot adress par ES:DI. Si DF = 0, alors DI est ensuite incrment de 4, sinon il est dcrment de 4. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour STOSB.

e) linstruction CMPSD ( Compare String Double Word )


Syntaxe : CMPSD Description : Compare le double mot adress par DS:SI et celui adress par ES:DI. Si DF = 0, alors SI et DI sont ensuite incrments de 4, sinon ils sont dcrments de 4. Remarque : Possibilit dutiliser les prfixes de rptition, de mme que pour CMPSB.

14. Les instructions dappel


a) linstruction CALL ( Procedure Call )

Syntaxe : CALL MaProc Description : Appel de procdure. Si MaProc se trouve dans un segment extrieur, le processeur empile CS. Ensuite, dans tous les cas, il empile IP et fait un saut ltiquette MaProc.

b) linstruction RET (ou RETN)


Syntaxe : RET Description : Retour de procdure se trouvant lintrieur du segment (NEAR). Un mot est dpil et plac dans IP. Le contrle retourne donc la procdure appelante.

c) linstruction RETF
Syntaxe : RETF Description : Retour de procdure se trouvant lextrieur du segment (FAR). Deux mots sont dpils et placs dans CS:IP. Le contrle retourne donc la procdure appelante.

15. Les instructions de boucle


a) linstruction LOOP
Syntaxe : LOOP MonLabel Description : Dcrmente CX, puis, si CX <> 0, fait un saut MonLabel.

b) linstruction LOOPE ( Loop while Equal )


Syntaxe : LOOPE MonLabel Description : Dcrmente CX, puis, si CX <> 0 et ZF = 1, fait un saut MonLabel. Mnmonique quivalent : LOOPZ

c) linstruction LOOPNE ( Loop while not Equal )


Syntaxe : LOOPNE MonLabel Description : Dcrmente CX, puis, si CX <> 0 et ZF = 0, fait un saut MonLabel. Mnmonique quivalent : LOOPNZ

16. Les instructions dadressage


a) linstruction LEA ( Load effective address )
Syntaxe : LEA Destination, Source Description : Charge loffset de la source dans le registre Destination.

Exemple : LEA BP, word ptr [BP + TOTO]

b) linstruction LDS ( Load pointer using DS )


Syntaxe : LDS Destination, Source Description : Transfre dans DS:Destination le contenu de la mmoire adresse par Source.

c) linstruction LES ( Load pointer using ES )


Syntaxe : LES Destination, Source Description : Transfre dans ES:Destination le contenu de la mmoire adresse par Source.

17. Les instructions de conversion arithmtique


Remarque prliminaire : Nous nexpliciterons pas toutes ces instructions.

a) linstruction AAA ( ASCII Adjust for Addition ) b) linstruction AAD ( ASCII Adjust for Division ) c) linstruction AAM ( ASCII Adjust for Multiplication ) d) linstruction AAS ( ASCII Adjust for Substraction ) e) linstruction CBW ( Convert Byte to Word )
Syntaxe : CBW Description : Convertit loctet sign stock dans AL en un mot (sign) stock dans AX. Ainsi, si AL est ngatif, AH sera rempli de 1 binaires, sinon, AH sera mis 0.

f) linstruction CWD ( Convert Word to Double Word )


Syntaxe : CWD Description : Convertit le mot sign stock dans AX en un double mot (sign) stock dans DX:AX. Ainsi, si AX est ngatif, DX sera rempli de 1 binaires, sinon DX sera mis 0.

g) linstruction DAA ( Decimal Adjust for Addition ) h) linstruction DAS ( Decimal Adjust for Substraction ) i) linstruction MOVSX ( Move with Sign Extend )
Syntaxe : MOVSX Destination, Source Description : Dplace le contenu sign dun registre de 8 bits dans un registre de 16 bits, ou bien dplace le contenu sign dun registre de 16 bits dans un registre de 32 bits. Si Source est

ngatif, la partie haute de Destination sera remplie de 1 binaires, sinon elle sera remplie de 0.

j) linstruction MOVZX ( Move with Zero Extend )


Syntaxe : MOVZX Destination, Source Description : Dplace le contenu non sign dun registre de 8 bits dans un registre de 16 bits, ou bien dplace le contenu sign dun registre de 16 bits dans un registre de 32 bits. La partie haute de Destination sera donc mise 0.

k) linstruction XLAT ( Translate )

18. Les instructions dentre-sortie


a) linstruction IN ( Input from port )
Syntaxe : IN Destination, Port Description : Charge un octet ou un mot depuis un port dentre-sortie dans AL ou AX. Port peut tre DX ou bien une constante de 8 bits.

b) linstruction OUT ( Output to port )


Syntaxe : OUT Port, Source Description : Ecrit dans Port la valeur contenue dans Source. Source ne peut tre que AL ou AX. Port est une constante ou bien DX.

QUATRIEME PARTIE
LES INTERRUPTIONS DU DOS RELATIVES AUX FICHIERS

Remarque prliminaire : Cette partie prsente quelques unes des interruptions du DOS qui servent manier les fichiers d'un disque. Nous la concluerons par l'tude d'un exemple de programme qui crypte un fichier choisi par l'utilisateur.

I. LECTURE ET ECRITURE DE FICHIERS AVEC LES HANDLES


Sous DOS, il existe deux mthodes pour accder aux fichiers et pour chacune d'elles un lot d'interruptions spcifiques. La premire est la mthode des FCB ( File contol block ). Elle est rarement utilise, aussi ne l'aborderons nous pas. Nous tudierons le principe de la mthode des handles . Pour lire ou crire des donnes dans un fichier, il est ncessaire de l'ouvrir, c'est--dire de le charger en mmoire. Quand toutes les oprations de lecture et d'criture auront t effectues, le fichier devra tre referm afin d'enregistrer les ventuelles dernires modifications et surtout de librer la mmoire occupe.

1. Ouverture d'un fichier


On ouvre un fichier en appelant la fonction 3dh de l'interruption 21h. Celle-ci attend comme paramtre dans DS:DX l'adresse d'une chane de caractres qui contient le chemin d'accs au fichier sur un disque, par exemple C:\MonDoss\MonFic.txt. Remarque : il n'est pas indispensable de mentionner le chemin d'accs complet : par dfaut, le fichier sera cherch partir du dossier courant. Remarque importante : La chane doit tre imprativement suivie de l'octet 00h qui sert marquer sa fin. Il nous faut galement spcifier le mode d'accs en crivant dans AL un 0 (si on veut ouvrir le fichier en lecture seule), un 1 (si on veut l'ouvrir en criture seule) ou un 2 (lecture ET criture). Si l'interruption choue, le flag CF sera mis 1 sans que le fichier soit ouvert. Dans le cas contraire, CF est mis 0 et le registre AX contient un petit nombre entier (par exemple 5) appel handle (ce qui signifie poigne ) du fichier. Ce handle reprsente le fichier. C'est lui qu'il faudra dsormais invoquer pour effectuer des oprations de lecture ou d'criture, et non pas le chemin d'accs. En effet, les chemins d'accs ne sont donc plus d'aucune utilit puisque les fichiers sont ouverts dans la mmoire vive.

2. Lecture dans un fichier


Une fois le fichier ouvert, on peut le lire avec la fonction 3fh. Il suffit de mentionner le handle dans BX, le nombre d'octets lire dans CX, et l'adresse d'un buffer dans DS:DX. Au cas o vous ne sauriez pas ce qu'est un buffer (ou tampon), sachez que c'est simplement une variable (gnralement une chane de caractres) destine recevoir des donnes (ou

en fournir). Dans notre cas, le buffer va recevoir les octets lus dans le fichier. Aprs l'appel, AX contient le nombre d'octets qui ont t effectivement lus (il peut tre infrieur la taille demande si le fichier n'est pas assez long). En cas de problme, CF sera mis 1.

3. Ecriture dans un fichier


Pour crire des donnes, on procde de mme avec la fonction 40h. Les paramtres sont les mmes que pour la fonction 3fh. Le buffer contient cette fois les octets crire. Aprs l'appel, le nombre d'octets qui ont t effectivement crits est stock dans AX (il sera tre infrieur la taille spcifie si le disque est plein). Les donnes sont crites sur le disque ds que le tampon (dans la mmoire vive) est plein.

4. Existence d'un pointeur de fichier


Une question se pose cependant : quel endroit du fichier les donnes sont-elles lues (ou crites) ? Rponse : quand un fichier est ouvert, un pointeur spcial pointant vers le dbut du fichier est cr. La premire opration de lecture (ou d'criture) se fera donc au dbut du fichier. Mais entre chaque opration, le pointeur est incrment de la taille des donnes que l'on a lues (ou crites). La deuxime opration se fera donc sur les octets qui suivent ceux de la premire. Remarque : Il est possible de modifier directement le pointeur de fichier : voyez pour cela la fonction 42h...

5. Fermeture d'un fichier


Pour terminer, le fichier doit tre referm. Les modifications ventuellement apportes et non enregistres seront crites sur le disque, et le handle sera libr. C'est la fonction 3eh qui se charge de tout cela. Elle attend simplement le handle du fichier dans BX. Et comme d'habitude, CF vaut 1 aprs l'appel si des erreurs ont t rencontes. Remarque : Attention lorsque vous laissez le fichier ouvert longtemps afin d'y ajouter progressivement des donnes ! Si le systme plante, vous perdrez les donnes qui se trouvent dans le tampon ce moment. C'est pourquoi il est conseill de forcer rgulirement l'criture sur le disque en refermant le fichier.

6. Conclusion
Le tableau suivant rcapitule ces diffrentes tapes : Fonction 3dh 3eh 3fh Description Ouvrir le fichier Fermer le fichier Lire le fichier Paramtres - DS:DX : adresse d'une chane contenant le chemin d'accs - AL : mode d'accs - BX : handle - BX : handle - CX : nombre d'octets - DS:DX : adresse d'un buffer

40h

Ecrire dans le fichier

- BX : handle - CX : nombre d'octets - DS:DX : adresse d'un buffer

II. LES FONCTIONS DE RECHERCHE DE FICHIERS


Pour rechercher un fichier (ou un dossier), on se sert des fonctions 4eh ( Find First ) et 4fh ( Find Next ). Imaginons par exemple que nous voulions chercher dans le dossier courant tous les fichiers qui portent l'extension .com afin de les supprimer. Comment devons-nous nous y prendre ?

1. La fonction 4eh
La fonction 4eh sert dfinir des critres de recherche et trouver le premier fichier qui correspond ces critres (s'il existe). On doit passer dans DS:DX l'adresse de la chane de caractres qui contient le masque de recherche (dans notre exemple, ce masque est *.com). Par dfaut, les fichiers sont cherchs dans le dossier courant. Mais on peut videmment spcifier un autre chemin dans le masque. Remarque importante : afin que le DOS puisse connatre sa taille, le masque doit imprativement tre termin par l'octet 00h ! On crit galement dans CX les attributs des fichiers que l'on dsire trouver. Si CX vaut 0, seuls les fichiers normaux pourront tre trouvs. En fait, chaque bit de CL reprsente un attribut, comme le montre le tableau ci-dessous : Bit 1 2 3 4 5 6 7 8 Signification Lecture seule Fichier cach Fichier systme Volume Rpertoire Fichier (Aucune...) (Aucune...)

Pour demander la fonction 4eh de ne pas oublier les fichiers cachs, il suffit donc de charger CX avec la valeur 2 (bit numro 2 = 1). De mme, l'attribut 00000111b (soit 7) nous permettra de trouver les fichiers en lecture seule, les fichiers cachs et les fichiers systmes. Remarque : Ne vous souciez pas trop des bits numro 4 et 6. Laissez-les 0. Une fois que les paramtres ont t ajusts, on peut appeler la fonction 4eh. Si aucun fichier n'a t trouv, le flag CF est mis 1. On doit donc fait un test sur CF pour savoir si la recherche peut continuer ou si elle doit s'arrter. Si au contraire la fonction a trouv un fichier, les caractristiques de ce fichier (i.e. son nom, sa taille, ses attributs,...) sont inscrits dans une zone de la mmoire appele DTA ( Disk Transfer Area ). Mais o se trouve donc cette DTA et quoi ressemble-t-elle ? Rponse : par dfaut, le DOS place la DTA dans le PSP de votre programme, l'offset 80h.

Remarque : il vous est naturellement possible de la dplacer en faisant appel la fonction 1ah. Voici la structure de la DTA : Adresse 00h 01h 0Ch 15h 16h 18h 1Ah 1Eh Description Lettre du lecteur (0=courant, 1=A, 2=B, ...) sur lequel se trouve le fichier Modle de la recherche Rserv Attributs du fichier Heure du fichier Date du fichier Taille du fichier Nom du fichier avec l'extension Taille (octets) 1 11 9 1 2 2 4 13

Puisque par dfaut la DTA est situe dans le PSP l'offset 80h, le nom du fichier trouv est crit l'offset 80h + 1eh = 9eh. De mme, la taille se trouve l'offset 9ah, etc...

2. La fonction 4fh
Jusqu' prsent, nous n'avons trouv qu'un seul fichier ! Pour poursuivre la recherche, appelez la fonction 4fh sans crire aucun paramtre dans les registres. Les caractristiques de votre recherche ont t mmorises dans la DTA : vous n'avez donc pas les rappeler. De mme que pour la fonction 4eh, CF est mis 1 si aucun nouveau fichier n'a t trouv. C'est le signe que vous pouvez arrter votre recherche.

3. Conclusion
Rsumons nous : Fonction 4eh 4fh Paramtres - DS:DX : adresse d'une chane Trouver le premier fichier qui correspond contenant le masque aux caractristiques spcifies - CX : attributs Trouver le prochain fichier Aucun ! Description

A titre d'exemple, crivons prsent le programme que nous voquions tout l'heure : trouver tous les fichiers COM du dossier courant et les effacer.

III. EXEMPLE DE PROGRAMME 1. Entre bufferise au clavier


L'exemple que nous proposons ici fait appel une saisie au clavier. Comme nous n'en n'avons pas encore rencontr, ce paragraphe explique brivement comment utiliser les fonctions 0ah et 0ch. On peut se servir de la fonction 0ah pour lire une chane de caractres au clavier. Le seul paramtre fournir est l'adresse d'un buffer. Comme il est souvent indispensable d'effacer le buffer avant la lecture, il est prfrable de ne pas utiliser la fonction 0ah directement mais d'appeler la fonction 0ch. En effet, celle-ci commence par effacer le buffer, puis appelle la fonction 0ah (ou une fonction voisine dont le numro doit tre transmis dans AL). Voici le code crire :

La seule difficult est dans la dclaration du buffer. Voici comment vous devez vous y prendre si vous considrez que l'utilisateur pourra entrer au plus n caractres :

Le premier octet de maChaine doit contenir le nombre d'octets maximal qui pourra tre entr, plus 1. Pourquoi plus 1 ? Tout simplement parce que le DOS met la fin des caractres taps le code ASCII 13 (retour chariot). Pour comprendre la suite de la dclaration, il faut savoir de quelle manire le DOS transmet les caractres qui ont t lus. Aprs la lecture, le deuxime octet du buffer contiendra le nombre exact d'octets lus (sans compter le 13 final). La chane proprement dite ne commencera donc qu'au troisime octet. Puisqu'un octet est utilis pour donner au DOS le nombre maximal de caractres autoris, un autre pour recevoir le nombre de caractres lus effectivement, et encore un autre pour recevoir le code ASCII 13, le buffer doit comporter trois octets de plus que la taille maximale de la chane. C'est pourquoi on crit : maChaine db n+1, ?, n dup(?), ?

2. Le programme

Le programme suivant demande l'utilisateur d'entrer le nom d'un fichier se trouvant dans le dossier courant puis crypte ce fichier en appliquant un NOT logique sur chaque octet. Naturellement, il n'est pas optimis du tout. Ce n'est qu'un exemple !

Suggestion : quand vous aurez compris ce petit programme, essayez donc de l'amliorer ! Par exemple, il faudrait que l'utilisateur puisse taper le nom du fichier crypter directement comme paramtre du programme (i.e. CRY MONFICH.EXE). Voyez pour cela la structure du PSP telle que prsente dans la premire partie. De plus, le programme devrait pouvoir trouver automatiquement le nom du fichier d'arrive : ce serait le mme que celui du fichier crypter, mais avec une extension diffrente (par exemple .cry). Vous pourriez galement tendre les possibilits du logiciel en permettant l'utilisateur de saisir non plus un simple nom de fichier, mais un masque complexe avec des chemins d'accs et des caractres jokers comme '*' et '?'. Vous aurez donc besoin des fonctions de recherche 4eh et 4fh. L'utilisateur doit de surcrot pouvoir choisir s'il veut crypter un fichier ou bien le dcrypter...

CONCLUSION
Voil. Nous esprons que vous avez compris lessentiel de ce cours, savoir la logique de la programmation en assembleur. Les connaissances que vous avez acquises en lisant la fin du cours devraient vous permettre de mieux saisir les premiers chapitres. Cest pourquoi nous vous invitons relire ce tutoriel. Certaines notions doivent encore vous paratre obscures. Maintenant que vous vous tes familiaris avec lassembleur, commencez par crire et tester quelques petits programmes COM inutiles et trs simples. Vous verrez quau bout de quelques essais, tout ce que vous avez lu vous semblera trs concret. Lorsque vous aurez crit vous-mme quelques tout petits programmes qui fonctionnent, lassimilation du langage deviendra alors trs rapide, car lassembleur est un langage trs logique et trs cohrent. Nous vous conseillons dcrire une librairie de petites macros ou procdures qui vous serviront dans tous vos programmes. Par exemple, vous pouvez faire une macro qui affiche un entier lcran, ou bien qui convertit une chane de caractres en un nombre entier. Voici un exemple de macro qui renvoie dans AL le nombre de chiffres dun entier non sign de deux octets pass dans AX :

N.B. : Pensez avant toute chose vous munir dune liste des interruptions du DOS. Vous ne pourrez rien faire si vous nen avez pas !

Bon courage et bonne chance !

Vous aimerez peut-être aussi