Académique Documents
Professionnel Documents
Culture Documents
Pas A Pas Vers L Assembleur Par Lord Noteworthy 1 PDF
Pas A Pas Vers L Assembleur Par Lord Noteworthy 1 PDF
Introduction......6
Dcimale.11
Binaire....11
Octal13
Hexadcimale..13
Dcimale Binaire..14
Binaire Dcimale.16
Binaire Hexadcimale16
Hexadcimale Binaire 17
Laddition...................19
La soustraction20
Astuce20
Historique..22
Notations...................25
Registres gnraux...29
Registres de segments....31
Registres doffset...31
Registre de flag..32
La pile33
La mmoire..................34
La pagination mmoire.......................34
Organisation de la mmoire35
Mnmonique.38
Oprandes.38
Lisibilit et prsentation.39
Notes et abrviations.40
Oprandes.....................41
Instructions de dcalage...43
Instructions de traitement..............43
Saut inconditionnel.................43
Saut conditionnel....44
Configuration de RadAsm....................53
Directive ALIGN...73
Loprateur PTR..................77
Loprateur TYPE...78
Les tableaux.78
Loprateur LENGTHOF80
Les structures..80
Les unions.82
Les pointeurs...83
Les crochets.85
Programmation vnementielle...89
La classe de fentre..93
Les Tests.................102
Comparaisons de registres104
Expressions composes.104
Les boucles.105
Sortir de la boucle107
La procdure de fentre.....................109
Conclusion et remerciement..137
Annexes......138
Alors a y est ? Vous avez dcid de se lancer la programmation en Assembleur mais vous ne savez
pas trop par o commencer ? Bon, je vais essayer de vous donner quelques bases, ce qui croyez-
moi, n'est pas vident ...
Mon obsession pour lAssembleur ma normment incit cerner ce qui est juste savoir, car pour
tout expliquer, cela demanderait quelque milliers de pages, crites en tous petits caractres. Nanmoins,
partir de nombreux exemples, vous allez vous familiariser avec la syntaxe de ce langage et apprendre
travailler avec les instructions. Vous ferez connaissance de quelques principes de base sur
larchitecture des systmes informatiques, dans le cadre concret de la famille des processeurs IA-32
Intel et renforcerez vos comptences sur la syntaxe MASM. Enfin vous aurez un aperu de larchitecture
Win32. Il nest nullement indispensable davoir une certaine exprience en programmation pour tirer parti
de ce Guide, seulement de la patience, de la volont, de la dtermination dapprendre et de comprendre.
Certes si vous avez touch tout autre langage de haut niveau que l'assembleur, vous allez vous sentir
plus laise, hors langages de balisage tels que lHTML ne vous servira surtout pas.
Pour finir je tiens prciser certaines petites choses. Tout dabord ce texte, beaucoup de personne
auraient pu lcrire. De plus je ne suis pas parfait, il n'est pas improbable que ce Guide contienne
quelques erratas, des incohrences ou d'autres petites choses qui m'auraient chappes, si vous en
dcelez une, merci de m'en faire part pour que je les corrige au plus vite possible.
Bon, eh bien sur ce, bonne lecture, et bon apprentissage tous, en gardant l'esprit la profonde
maxime du regrett professeur Shadoko : La plus grave maladie du cerveau, c'est de rflchir .
Introduction
Le dbut du document aborde des notions importantes en Assembleur et ncessaires pour bien
comprendre la suite. Vous serez sans doute un peu du de ne pas faire des choses extrmement
puissantes immdiatement, mais patience : qui veut aller loin mnage sa monture. Ainsi, avant de nous
Contrairement ce qu'on dit souvent, un ordinateur ce n'est pas une machine trs intelligente, c'est une
machine qui donne lillusion dtre intelligente car elle calcule trs vite, part a, un ordinateur a ne
sait faire que des calcules trs simple, encore pas avec tous les chiffres, mais uniquement deux chiffres,
le 0 et le 1. Le langage de chaque ordinateur est le langage machine o les instructions et les donnes
sont reprsentes par des combinaisons de bits, les fameux zros et uns. Lorsquun ordinateur traite du
texte, du son, de limage, de la vido, il traite en ralit des nombres.
Les langages de programmation ont considrablement volu depuis les premiers calculateurs labors
pour assister les calculs de trajectoire dartillerie durant la seconde guerre mondiale. A cette poque l,
les programmeurs travaillaient en langage machine, ce qui consistait grer des chaines trs longues
composes de 1 et de 0, ce fut un vritable travail de fourmi. Bientt, les premiers assembleurs
rendirent les instructions machine plus intelligibles et plus facile utiliser. Dans les annes soixante, pour
faciliter encore la programmation, on a mis en place d'autres langages de programmation plus
abordables, plus comprhensible par lhumain, ces langages sont dits volus parce quils donnent la
possibilit aux programmeurs dutiliser une syntaxe proche de la langue anglaise, avec des instructions
et des mots comme let variable = 10.
Dans des discussions passionnes sur les comptences de chacun, il est rare que quelqu'un ne sorte
pas l'idiotie suivante :
Le langage machine c'est plus rapide que l'assembleur ! Ou pire encore : L'assembleur, c'est gnial,
c'est plus rapide que le langage machine !
Rassurer vous, si vous avez faire ce genre de personnes, ne vous sentez pas ignorant, il s'agit de
personnes qui ne savent pas de quoi elles parlent, et qui se permettent de porter des jugements. Le
langage machine c'est exactement la mme chose que l'assembleur, seule l'apparence diffre. Je
m'explique. Si vous voulez mettre la valeur 5 dans EAX vous taperez :
Nessayer pas den comprendre le contenu, vous navez mme pas encore abord la chapitre 1.
Cette instruction en assembleur sera quelque chose qui ressemble a en binaire : 1100110 10111000
101
Comme vous avez pu le constater, tout cela nas rien de sorcier, le binaire que traite lordinateur avec
facilit ne convient pas au programmeur qui commet souvent, par manque dattention, des erreurs trs
difficiles ensuite dtecter, les nombres binaires se ressemblent, surtout aprs travaill avec eux
pendant plusieurs heures, prtant confusion et sans signification apparente. Il parait donc vident que
ce type d'criture est difficilement lisible pour nous, tre humains.... Un programmeur pourra tenter de se
souvenir de quelques codes binaires mais il pourrait investir ses efforts dans des tches plus
productives. Lide vient davoir un programme qui effectue la traduction langage assembleur langage
machine, cest ce programme qui est appel lassembleur.
Il est bien sur possible de traduire un programme crit en assembleur la main en remplaant chaque
instruction son quivalente en binaire ; cest ce quon lappelle lassemblage manuel, mais croyez moi
nombreuses sont les difficults associes cette conversion. Voici un petit exemple :
Langage de programmation :
(lAssembleur) CMP EAX, EBX
JNE Failed
;
JMP end
Failed:
End:
Demble on comprend mieux lintrt de lassembleur et des langages volus qui soulagent les
programmeurs d'un fardeau norme, et qui prsentent une facilit de programmation bien plus grande
que le langage machine.
Lassembleur abrg ASM est le langage de programmation (un code de communication, permettant
un tre humain de dialoguer avec sa machine) de plus bas niveau. Cela signifie quil est trop proche du
matriel, qui oblige le programmeur se soucier de concepts proches du fonctionnement de la machine,
comme la mmoire.
Heureusement, ils existent des langages hauts niveau, linstar de Visual Basic, Delphi, C++, Java...,
ce sont les langages les plus utiliss de nos jours, qui permettent au programmeur de s'abstraire de
dtails inhrents au fonctionnement de la machine. Il permet de manipuler des concepts bien plus
Si nous rsumons, le terme "Assembleur" dsigne tour tour deux choses diffrentes, mais
apparentes : le langage de programmation de plus bas niveau accessible facilement un humain et un
logiciel transformant un fichier source contenant des instructions, en un fichier excutable que le
processeur peut comprendre.
Evidemment, rien n'est parfait. Jetons un petit coup d'il sur le revers de la mdaille:
Comme tout langage de programmation, lassembleur a ses inconvnients, mais aussi ses avantages:
Tous les langages de programmation sont des hritiers plus ou moins directs de ce langage
lmentaire quest lassembleur, ce dernier peut vous donner la logique ncessaire pour
programmer en nimporte quels langages, ce langage trouve sa place dans l'ensemble des
applications, sans oublier que n'importe quel programme, crit dans n'importe quel langage est
finalement traduit en langage machine pour tre excut.
On a la possibilit de faire tout et n'importe quoi avec la mmoire. L'ASM n'a pas de limite et
de scurit. Autant il peut tre utile, autant il peut dtruire ;)
L'assembleur se rvle tre un langage bien part, son apprentissage poursuit double objectif, dune
part avoir une comprhension plus profonde de la faon dont fonctionne lordinateur, dautre part vous
donnez des atouts considrables pour la comprhension et la matrise de tous les autres langages de
programmation.
Il est important de savoir ou et quand il faut utiliser l'ASM afin d'avoir un programme le plus performant
tout en conservant des temps de dveloppement les plus courts possibles, lASM pourra vous tre utile
dans plusieurs cas :
Tout ce qui doit tre optimis au niveau de la taille, par exemple pour programmer un virus...
Lorsque la vitesse dexcution est un facteur critique et que la moindre microseconde est
prcieuse, ou ne peut pas tre fait avec autre chose que de l'assembleur, par exemple un
driver de disque dur, un secteur de boot, ou une routine d'affichage de polygones/triangles en
3D...
Vu que lassembleur est qualifi comme tant le langage de programmation le plus bas niveau, il dpend
donc fortement du type de processeur. Ainsi il n'existe pas un langage assembleur, mais un langage
assembleur par type de processeur. Il est donc primordial davoir un minimum de connaissances
techniques. Nous verrons ensemble certains points essentiels la bonne comprhension de la suite
dinformations dveloppes dans ce guide savoir les termes techniques, les conventions, les bases
numrales, les diffrents types de reprsentations, la mmoire et 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 travers vos esprits. Tout vous semblera beaucoup plus simple quand
nous passerons la pratique dans le langage assembleur. Ces informations permettront de rafrachir ou
denrichir vos connaissances dans ce domaine.
Dcimale
Depuis la nuit des temps, l'homme a eu besoin de compter et de calculer. Selon les civilisations, divers
systmes de numration on t mis en place puis abandonns.
A l'heure actuelle, nous utilisons le systme de numration dcimal. Ce systme s'est impos en Europe
partir du 10me sicle. Aujourd'hui le systme dcimal est quasiment universel. Lide de ce systme
rside dans le fait que nous possdons dix doigts, lcriture dcimale ncessite donc lexistence de 10
chiffres qui sont 0, 1, 2, 3, 4, 5, 6, 7, 8, et 9.Lorsque nous crivons un nombre en mettant certains de
ces chiffres les uns derrire les autres, lordre dans lequel nous mettons les chiffres est capital. Ainsi,
Le problme est que nous sommes tellement habitus faire ce dcodage de faon instinctive que
gnralement nous nen connaissons plus les rgles. Mais ce nest pas trs compliqu de les
reconstituer. Considrons par exemple le nombre 4678. Il est compos des chiffres des milliers (4), des
centaines (6), des dizaines (7), et des units (8).
Ou bien encore :
Arriv ce stade de la comptition, les matheux notent la ligne ci-dessus laide du symbole de
puissance. Cela donne :
Et voil, nous y sommes. Un nombre peut donc tre dcompos sous la forme de la somme de chacun
des chiffres qui le composent, multiplis par la dimension de la base l'exposant de leur rang. Cette
mthode n'est pas valable uniquement pour les nombres dcimaux.
Binaire
Un ordinateur n'ayant pas de doigts, compter en base dcimale ne lui est pas particulirement adapt.
La base 2, plus connue sous le nom de la base binaire, l'est par contre beaucoup plus. Pour des
raisons technologiques, lordinateur ne peut traiter quune information code sous forme binaire.
Le courant lectrique passe ou ne passe pas, quon peut interprter en 0 ou 1.
Dans la ralit physique il ny a pas de 0 de 1 qui se balade au cur de lordinateur. Le choix du 0 et
de 1 est une pure convention, une image commode, que lon utilise pour parler de toute information
binaire, et on aurait pu choisir nimporte quelle paire de symboles leur place, quelque chose qui ne
peut avoir que de tats : par exemple, ouvert ou ferme, vrai ou faux, militaire ou civil, libre ou occup
Il existe des units de manipulation pour les trs grandes valeurs. Mme si elles ne sont pas employes
par les micro-ordinateurs actuels, il est bon den connatre lexistence.
Un kilo-octet (Ko) = 1000 octets.
Un Mgaoctet (Mo) = 1000 Ko = 1000000 octets.
Un Gigaoctet (Go) = 1000 Mo = 1000000000 octets.
Un Traoctet (To) = 1000 Go = 1000000000000 octets.
Les bits sont gnralement regroups par 4 ou 8 bits. Dans la reprsentation binaire, on distingue les
deux bits dextrmit dun nombre :
Le bit de poids fort (Most Significant Bit, ou MSB) est le bit, dans une reprsentation binaire
donne, ayant la plus grande valeur, celui le plus gauche. Exactement comme dans le
nombre 189, c'est le chiffre le plus gauche qui le plus de poids, la valeur la plus forte.
Le bit de poids faible (Least Significant Bit, ou LSB) est pour un nombre binaire le bit ayant
dans une reprsentation donne la moindre valeur, celui le plus droite. Exactement comme
dans le nombre 189, c'est le chiffre le plus droite qui le moins de poids, la valeur la plus
faible.
De mme, si lon dcoupe un nombre en deux, le premier paquet gauche est appel paquet de poids
faible, le second paquet droite est appel paquet de poids fort. Ainsi un mot est compos de 2
octets :
1 octet de poids fort (Least Significant Byte).
10100101011010110101001000010101
M.S.Bit l.S.B
Les oprations arithmtiques simples telles que l'addition, la soustraction, la division et la multiplication
sont facile effectuer en binaire.
Octale
Compter en octal, cest comme compter en dcimal, si on nutilise pas ses pouces - Tom Lehrer.
Comme vous le devinez srement, tous comme on peut dire que le binaire constitue un systme de
codage en base 2, le dcimal un systme de base 10, vous laurez compris loctal est un systme de
base 8. Ce systme utilise 8 symboles : 0, 1, 2, 3, 4, 5, 6, 7. Il nest plus gure employ aujourdhui,
puisquil servait au codage des nombres dans les ordinateurs de premire gnration. Le systme octal
a cd la place au systme hexadcimal. Etant donne que ce systme de numration nest plus
vraiment employ, on ne sattardera pas davantage sur le sujet !
Hexadcimale
La notation hexadcimale consiste compter non pas en base 2, 8, ou 10, mais en base 16. Cela
ncessite d'avoir 16 chiffres.
En dcimale vous comptez comme a :
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
Et bien en hexadcimale on compte de cette manire :
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12,
Pour les dix premiers, on na t pas cherch bien loin : on a recycl les dix chiffres de la base
dcimale, l il nous manque encore 6 chiffres, plutt quinventer de nouveaux symboles, on a alors
convenu de les reprsenter par les premiers lettres de lalphabet. Ainsi par convention, A vaut 10, B vaut
11 et ainsi de suite jusqu F qui vaut 15.
Afin d'viter tout risque d'erreur entre bases, il est recommand d'crire un :
"b" la fin d'un nombre binaire.
"d" la fin d'un nombre dcimal (base par dfaut).
"o" la fin d'un nombre octal.
"h" la fin d'un nombre hexadcimal, toujours en minuscules, afin de ne pas confondre avec
les "chiffres" hexadcimaux B et D.
Par exemple : 11011b = 27d = 33o =1Bh
Et enfin, la numration binaire, comme les autres systmes de numration, noblige pas la reprsentation
des valeurs nulles ou inutiles, par exemple :
Le nombre 220d = 11011100b est reprsentable sur 8 bits.
Le nombre 16d = 00010000b est reprsentable sur 5 bits, ce qui donne rellement en
omettant les chiffres zro inutiles 10000b.
0 0000 0 0
1 0001 1 1
2 0010 2 2
3 0011 3 3
4 0100 4 4
5 0101 5 5
6 0110 6 6
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
16 10000 20 10
17 10001 21 11
Il est indispensable de savoir faire ce genre de conversion pour tre capable de se dbrouiller avec un
simple crayon pointe de graphite et une feuille de papier (on na pas toujours sous la main une
calculatrice quipe de ce genre de fonction)
Dcimale Binaire
|______||_______||_______||_______|
8 4 2 1
|___1___||___1___||___0___||___1___|
8 4 2 1
Jusqu prsent, nous avons vu diffrents moyens de codage de nombres. Mais il est ncessaire de
savoir galement comment coder des caractres alphanumriques. Par exemple lors de leur entr
partir dun clavier. La mmoire de l'ordinateur conserve toutes les donnes sous forme numrique. Il
n'existe pas de mthode pour stocker directement les caractres. Dans les annes 60, le code ASCII
(American Standard Code for Information Interchange), qui est actuellement le plus connue et le plus
largement compatible, est adopt comme standard, chaque caractre possde donc son quivalent en
code numrique, par exemple la lettre M correspond au nombre 77d. Un nouveau code, plus complet,
qui supplante l'ASCII est l'Unicode. Une des diffrences cls entre les deux codes est que l'ASCII utilise
un octet pour encoder un caractre alors que l'Unicode en utilise deux (ou un mot). Par exemple,
l'ASCII fait correspondre l'octet 41h (65d) au caractre majuscule A; l'Unicode y fait correspondre le
mot 0041h. Comme l'ASCII n'utilise qu'un octet, il est limit 256 caractres diffrents au maximum.
L'Unicode tend les valeurs ASCII des mots et permet de reprsenter beaucoup plus de caractres.
C'est important afin de reprsenter les caractres de tous les langages du monde. Jai inclus la liste des
diffrents codes ASCII ainsi que leur signification en annexe
Mais comment tu fais pour faire 77 !! Regarde bien ton boulier, il n'a que (8 + 4 + 2 + 1) a fait 15.
Bien cette fois ci, il suffit d'agrandir le boulier et voil:
|______||______||______||______||______||______||______||______|
|___0___||___1___||___0___||___0___||___1___||___1___||___0___||___1___|
128 64 32 16 8 4 2 1
Il existe une autre mthode classique pour transformer un nombre du systme dcimale dans un autre
systme, par divisions successives.
La mthode de dcomposition par divisions successives consiste diviser le nombre plusieurs fois (si
ncessaire) dans la base choisie jusqu' obtenir un quotient nul. Tant quil sagit dune conversion
dcimale binaire, on divise par 2. Les restes successifs des divisions, pris dans leur ordre inverse,
forment le nombre dsir.
77 | _2_ _
| 38 |_2_ _
1 | | 19 |_2_ _
0 | | 9 |_2_ _
1 | | 4 |_2_ _
1 | | 2 |_2_ _
0 | | 1
0 |
1
Attention au sens de lecture
Binaire Dcimale
Une fois que le systme binaire est bien compris, il est facile de transposer ses principes pour
comprendre le systme binaire. Je rappelle, pour trouver la valeur dun nombre binaire, il faut, linstar
des bits dcimaux, multiplier la valeur du bit par la valeur de 2 expos par la position du bit moins un.
Cependant, dans ce cas-ci, puisque le bit peut seulement tre 1 ou 0, le calcul revient plus une
dcision dinclure la valeur ou non dans le nombre binaire qu une multiplication. Ainsi, pour trouver la
valeur dun nombre binaire vous pouvez utiliser le tableau suivant :
------------------------------------------------------------------
0 1 0 0 1 1 0 1
------------------------------------------------------------------
27 26 25 24 23 22 21 20
-----------------------------------------------------------------
En suivant les principes noncs dans la conversion binaire. Cependant il ne s'agit plus, de puissances
de 2 mais de puissances de 16 puisque la base est 16.
Binaire Hexadcimale
Pour convertir un nombre en hexadcimale, il yen a deux mthodes lune consiste faire un grand
dtour, en repassant par la base dcimale. Lautre mthode consiste faire le voyage direct du binaire
vers lhexadcimale.
La premire mthode :
Dcimale hexadcimale
On utilise la mthode des divisions successives, mme principe que pour le systme binaire, sauf que
lon divise par 16.
On note les restes des divisions successives puis on lit ces restes en remontant.
Hexadcimale Dcimale :
Inversement il est ais de passer d'un nombre en hexadcimal un nombre dcimal par multiplications
successives, en suivant les principes noncs dans la conversion binaire. Cependant il ne s'agit plus, de
puissances de 2 mais de puissances de 16 puisque la base est 16.
La deuxime mthode :
Plus rapide consiste dcouper le nombre binaire en quartets, partir de la droite, puis remplacer
chaque quartet par le symbole hexadcimal correspondant
Dans l'exemple prcdent, on peut remarquer que 1011 1101 en binaire, nous conduit
B D en hexadcimal.
Le nombre scrit donc en hexadcimal : BD. Cest la mme conclusion quavec la premire mthode.
Hexadcimale Binaire
Le passage de l'hexadcimal en binaire peut se faire de la manire inverse, en convertissant les chiffres
qui composent le nombre hexadcimal en leur quivalent binaire. Notez que les 0 de tte des 4 bits
sont importants ! Si
1011 1101
Bien sr que oui, jusqu prsent nous avons parl de mots binaires sans en spcifier le signe. Un
nombre tel qu'on appris l'crire est appel un nombre non sign (unsigned en anglais), il est
toujours positif. Au contraire, maintenant nous allons apprendre crire des nombres qui peuvent
reprsenter des valeurs soit positifs, soit ngatifs. On dira qu'ils sont signs (signed). Un nombre sign
nest donc pas forcment ngatif.
Chaque bit dun octet peut occuper deux tats, il ya donc dans un octet :
0 0 0 0 0 0 0 0 0
- 1 - 0 0 0 0 0 0 0 1
------ = -----------------------------------------------------------------------------------------
= -1 1 1 1 1 1 1 1 1
Recommenons et soustrayons 1 -1 :
- 1 1 1 1 1 1 1 1 1
Ceci dit cette mthode de dtermination de la reprsentation binaire d'un nombre ngatif n'est pas trs
commode, c'est pourquoi nous allons introduire la notion de notation en complment 2. La procdure
est la suivante :
2. On inverse tous les bits du nombre: les 0 deviennent des 1, les 1 deviennent des 0
(complment 1).
3. On ajoute 1 au rsultat.
2 s'crit 00000010b
Le rsultat trouv est bien le mme que prcdemment. Nous pouvons vrifier que l'opration +2 - 2
donne bien zro sur 8 bits. Le 1 situ gauche nest pas pris en compte. Par cette mthode il est donc
possible de coder les nombre dcimaux compris entre -128 et 127. Le bit du poids fort de chaque octet
est gal :
Notons que cette notation en complment deux n'est pas obligatoire. C'est au programmeur de dcider
si les nombres qu'il utilise sont compris entre 0 et 256 ou bien entre -128 et + 127.
Oprations Arithmtiques
Laddition
Un rappel srement inutile mais qui clarifie des choses... Quand vous faites une addition en dcimal,
vous faites la somme des chiffres se trouvant dans une mme colonne :
Si la somme est infrieure 10, alors vous posez le rsultat obtenu et passez la colonne
suivante.
Si la somme est suprieure 10, alors vous posez le chiffre des units et gardez en retenue le
chiffre des dizaines.
Si vous faites la somme de 2 nombres, alors la retenue ne pourra tre suprieure 1.
Le principe est exactement le mme en binaire, on commence additionner les bits de poids faible, les
bits de droite, puis on a des retenues, lorsque la somme de deux bits poids dpasse la valeur de lunit
la plus grande (dans le ca binaire : 1), cette retenu est report de poids plus fort suivant...
En suivant ce principe, on obtient en binaire la table daddition suivante :
___________________________________________________
Rsultat Report
-------------------------------------------------------------------
0+0= 0 0
-------------------------------------------------------------------
0+1 = 1 0
------------------------------------------------------------------
1+0 = 1 0
------------------------------------------------------------------
1+1 = 0 1
__________________________________________________
11 1 1 1
1 0 0 1 0 1 1 1
De mme en hexadcimal, il suffit de procder comme dans le systme dcimale, ainsi nous obtenons :
A 2 Ah = 10d
+ 3 C Ch = 12d
----------------------
= D E
Dsol cet exemple ne comporte pas de retenues, les nombres obtenus tant plus grand que 16 nous
additionnons 4 et nous effectuons un report, en voici un qui en comporte:
2 F Fh = 15d
+ 5 3
-------------------------
1
= 7 18
4
-------------------------
= 8 22
-------------------------
= 8 2
Ainsi 2Fh + 53h = 82h. Nous pouvons constater quune table daddition en hexadcimal ou une
calculatrice avec la fonction BIN, DEC, OCT, ET HEX se relve un outil prcieux.
La soustraction
Pour effectuer une soustraction en binaire, nous procdons de la mme faon que pour une soustraction
en dcimale, il ya quatre cas possibles :
_______________________________________________
Rsultat Emprunt
1 1 1
1 0 0 0 1 0 1 0
- 0 1 1 1 - 1 0 0 1
------------------------------------- -------------------------------------
0 0 0 1 0 0 0 1
En hexadcimal, a marche comme en dcimal. La seule difficult provient de ce que l'on n'apprend
pas la table d'addition en hexadcimal. B+F=1A par exemple. Il faut donc rflchir un peu plus qu'en
dcimal
F 9
- A 2
--------------------
5 7
Vous avez vu ? Ce nest pas si dur ! On pourrait, de la mme faon, illustrer le fonctionnement d'autres
oprations arithmtiques en binaire, mais l ce n'est pas notre objectif. Cest tout ce qu'il faut retenir
jusquici.
Dornavant, ne vous vous souciez pas de faire ces calculs la main. La solution est beaucoup plus
simple que cela. Procurez vous de votre calculatrice Windows. Pour ce faire, le moyen le plus rapide est
de cliquer sur touche "Windows" + R, tapez "calc" et cliquer sur OK. Un raccourci est aussi disponible,
pour les amants de la souris, dans le menu tous les programmes, dans le sous-menu accessoires. Une
fois que vous avez dmarr la calculatrice, rassurez-vous que vous soyez en mode scientifique,
(Affichage/Scientifique). Vous pouvez choisir le systme numrique laide des 4 boutons radios
encercls (Hex = Hexadcimale, Dc = dcimal, Oct = Octale et Bin pour binaire, ensuite, cliquez sur le
systme numral dans lequel vous voulez avoir la conversion.
Cela fait dj une bonne base pour commencer, vous avez appris les systmes de numration. Vous
devriez tre en mesure deffectuer de simples conversions facilement.
Et c'est parti pour l'assembleur, je rassemble mon cerveau et prend mon courage deux pattes... en
effet, il va m'en falloir, car aprs les explications de bases, assez facile, et que vous connaissiez sans
doute dj, on va s'attaquer un gros morceau trs important dans la programmation en assembleur,
puisqu'il s'agit de la gestion de la mmoire. Il est vital de comprendre comment elle est organise, et
comment on y accde efficacement. D'ou le titre.
Nous y voil. Encore un chapitre barbant... Donc comme je l'ai dit plus haut, ce chapitre est
extrmement important. Car aprs a, on entrera de plein pied dans la programmation en apprenant des
instructions en plus grosse quantit, puis dans les chapitres suivants, nous aborderont la structure des
donnes. Donc je le souligne bien, il faut comprendre ce chapitre.
Pour dcrire brivement ce chapitre, je peux dj vous dire qu'il traitera de l'organisation de la mmoire,
de la faon dont le processeur communique avec, les diffrents registres des processeurs Intel de la
famille 80x86, les modes d'adressage de ces processeurs, ensuite nous expliquerons le fonctionnement
des registres et des drapeaux ainsi que la pile. Enfin, nous verrons les premires instructions
d'assembleur, lies donc la gestion de la mmoire.
Sans entrer dans les dtails qui seront vus en cours, nous prsentons le minimum savoir sur ce quest
un microprocesseur.
Un microprocesseur constitue le cur de tout ordinateur: il excute les instructions qui composent les
programmes que nous lui demandons dexcuter. Les instructions sont stockes en mmoire (en dehors
du microprocesseur). Ces instructions (dont lensemble compose le langage assembleur) sont trs
simples mais nen permettent pas moins, en les combinant, de raliser nimporte quelle opration
programmable. Pour excuter un programme, le processeur lit les instructions en mmoire, une par une.
Il connat tout instant ladresse (lendroit dans la mmoire) laquelle se trouve la prochaine instruction
excuter car il mmorise cette adresse dans son compteur ordinal.
Avant de nous intresser plus particulirement larchitecture interne dun microprocesseur, il convient
de connatre lvolution impressionnante de ces composants.
Historique
Le concept de microprocesseur a t cr par la Socit Intel. Cette Socit, cre en 1968, tait
spcialise dans la conception et la fabrication de puces mmoire. la demande de deux de ses clients
fabricants de calculatrices et de terminaux Intel tudia une unit de calcul implmente sur une
seule puce. Ceci donna naissance, en 1971, au premier microprocesseur du monde, le 4004, qui tait
une unit de calcul 4 bits fonctionnant 108 kHz. Il rsultait de lintgration denviron 2300 transistors.
A partir de cette date, un rythme trs rapide dvolution sest install. De nombreux autres modles sont
apparus, de plus en plus puissants et de plus en plus complexes. Ce rythme dvolution sest maintenu
sans flchir jusqu aujourdhui. Ces volutions concernent les techniques dintgrations des nombres de
transistors et la frquence dhorloge des processeurs. Il y a galement dautres amliorations, comme la
largeur de bus mmoire, la taille des registres ou la taille de la mmoire cache. Dans le mme intervalle
de temps, leur puissance de traitement est passe de 60 000 instructions excutes par seconde par
l'Intel 4004 plusieurs milliards par les machines actuelles les plus puissants. Lhistoire des
Ce rythme d'volution effrn est appel loi de Moore (Gordon E. Moore, du non du prsident de la
compagnie Intel qui l'a formul dans les annes 70). Il prvoyait que les performances des processeurs
(par extension le nombre de transistors intgrs sur silicium) doubleraient tous les 12 mois. Cette loi a
t rvise en 1975, portant le nombre de mois 18. La loi de Moore se vrifie encore aujourd'hui.
Moore estime que cette volution se poursuivra jusquen 2017, date laquelle elle devrait rencontrer des
contraintes lies la physique des atomes.
Le tableau si dessous recense lvolution de la gamme des processeurs compatibles Intel x86, avec les
dates des premires versions de chaque modle.
Finesse de
Nombre de Frquence Largeur
Date Nom gravure MIPS
transistors de l'horloge des donnes
(m)
4 bits/4 bits
1971 4004 2 300 108 kHz
bus
8 bits/8 bits
1974 8080 6 000 6 2 MHz 0,64
bus
16 bits/8 bits
1979 8086 - 8088 29 000 3 5 MHz 0,33
bus
32 bits/32 bits
1989 80486 1 200 000 1 25 100 MHz 20
bus
32 bits/64 bits
1993 Pentium 3 100 000 0,8 0.28 60 233 MHz 100
bus
D'augmenter les vitesses de fonctionnement des processeurs, car les distances entre les
composants sont rduites.
De rduire les cots, car un seul circuit en remplace plusieurs.
De crer des ordinateurs bien plus petits : les micro-ordinateurs.
Comme dans tout circuit intgr la technologie de fabrication impose au microprocesseur des
caractristiques :
Le jeu d'instructions quil peut excuter. Tout microprocesseur contient en lui-mme un jeu
d'instructions. Ces instructions, trs basiques, se rsument une tche simple, par exemple :
Mettre telle valeur dans la mmoire.
Ou additionner telle valeur avec telle autre valeur et mettre le rsultat dans la mmoire.
Comparer deux nombres pour dterminer sils sont gaux, comparer deux nombres pour
dterminer lequel est le plus grand, multiplier deux nombres...
La complexit de son architecture. Cette complexit se mesure par le nombre de transistors
contenus dans le microprocesseur. Plus le microprocesseur contiendra de transistors, plus il pourra
effectuer des oprations complexes, et/ou traiter des chiffres des grande taille.
Le nombre de bits que le processeur peut traiter ensemble, autrement la longueur des donnes
que peut manipuler un microprocesseur. Les premiers microprocesseurs ne pouvaient traiter plus
de 4 bits d'un coup. Ils devaient donc excuter plusieurs instructions pour additionner des nombres
de 32 ou 64 bits. Les microprocesseurs actuels (en 2007) peuvent traiter des nombres sur 64
bits ensemble. Le nombre de bits est en rapport direct avec la capacit traiter de grands
nombres rapidement, ou des nombres d'une grande prcision (nombres de dcimales
significatives).
Notations
x86 ou i86 : est la dnomination de la famille de microprocesseurs compatibles avec le jeu d'instructions
de l'Intel 8086. Les diffrents constructeurs de microprocesseurs pour PC se doivent de maintenir une
compatibilit ascendante afin que les anciens logiciels fonctionnent sur les nouveaux microprocesseurs.
L'architecture de la srie x86 partir du Pentium a t nomme IA-32 par Intel.
IA-32 (Intel architecture 32 bits) ou i386 : dsigne l'architecture partir du Intel 80386, 32 bits, qui a
enfin permis de sortir du mode rel correctement, et de faire un bon multitches sur les Intel. Et d'avoir
un adressage mmoire de 4 Go.
IA-64 (Intel Architecture 64 bits) dsigne larchitecture des nouvelles est une architecture de
processeurs Intel destines remplacer les x86. Il s'agit d'une rupture totale avec la srie x86, le jeu
d'instructions n'ayant plus rien voir, ni les lments de l'architecture du processeur. Le rsultat est
quelque chose de globalement nettement plus simple, donc de bien plus rapide, en donnant un contrle
plus fin au logiciel sur le matriel.
Il faut savoir que les familles de processeur ce sont succds en ajoutant leurs lots d'amliorations, et
pas uniquement en matire de rapidit. Voici les principaux processeurs x86: 8088/8086,
80188/80186, 80286, 80386, 80486, 80586/pentium.
8088, 8086: Ces processeurs, du point de vue de la programmation sont identiques. Ils taient les
processeurs utiliss dans les tous premiers PC. Ils offrent plusieurs registres 16 bits : AX, BX, CX, DX,
SI, DI, BP, SP, CS, DS, SS, ES, IP, FLAGS. Ils ne supportent que jusqu' 1Mo de mmoire et n'oprent
qu'en mode rel. Dans ce mode, un programme peut accder n'importe quelle adresse mmoire,
80286: Ce processeur tait utilis dans les PC de type AT. Il apporte quelques nouvelles instructions au
langage machine de base des 8088/86. Cependant, sa principale nouvelle fonctionnalit est le mode
protg 16 bits. Dans ce mode, il peut accder jusqu' 16Mo de mmoire et empcher les programmes
d'accder la mmoire des uns et des autres. Cependant, les programmes sont toujours diviss en
segments qui ne peuvent pas dpasser les 64Ko.
80386: Ce processeur a grandement amlior le 80286. Tout d'abord, il tend la plupart des registres
32 bits (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP) et ajoute deux nouveaux registres 16 bits :
FS et GS. Il ajoute galement un nouveau mode protg 32 bits. Dans ce mode, il peut accder jusqu'
4Go de mmoire. Les programmes sont encore diviss en segments mais maintenant, chaque segment
peut galement faire jusqu' 4Go !
80486/Pentium/Pentium Pro: Ces membres de la famille 80x86 apportent trs peu de nouvelles
fonctionnalits. Ils acclrent principalement l'excution des instructions.
Le 80586, appel Pentium pour des raisons de protection commerciale, dispose d'un bus de donnes
de 64 bits et est muni d'un dispositif de prvision des branchements. Il est constitu de 2 processeurs
en pipe-line parallles lui permettant d'excuter deux instructions en mme temps. Son cadencement est
envisag (en 1994) jusqu' 150 MHZ.
Pentium MMX: Ce processeur ajoute les instructions MMX (MultiMedia eXentions) au Pentium. Ces
instructions peuvent acclrer des oprations graphiques courantes.
Pentium II: C'est un processeur Pentium Pro avec les instructions MMX (Le Pentium III est
grossirement un Pentium II plus rapide).
Pourquoi les diffrents microprocesseurs dIntel sont-ils alors compatibles entre eux ?
Tout simplement parce que chaque fois que Intel sort un nouveau processeur, toutes les instructions des
processeurs prcdents sont incluses. En fait, il ny a gnralement pas beaucoup de nouvelles
instructions ajoutes. Ceci nous assure que les vieux programmes (ceux crits pour de plus vieux
Le 8086, 8088, 80186 et 80188 nont quun mode de fonctionnement, le mode rel :
1 Mo au maximum et ils sont monotches. A partir du 80286 et surtout du 80386, il y a eu trois modes
de fonctionnement. En voici le dtail :
Le mode rel : mode par dfaut du microprocesseur, celui dans lequel est le processeur au
dmarrage, et dans lequel s'excute DOS. Il fournit les mmes fonctionnalits que le 8086.
Cela a plusieurs consquences, dont lune est quil nest pas possible dadresser plus que 1 Mo
mmoire.
Le mode protg : exploit par Windows partir de la version 3.1. Il tire son nom de "protg"
de ses nombreuses fonctions de protection. Le terme protection signifie ici "protection contre les
bugs ou les programmes malveillants". Eh oui, en mode protg, les programmes sont soumis
des rgles trs strictes, qui ne sont pas rellement astreignante pour des programmeurs
normaux, mais qui sont terribles ds que le programme tente de sortir de l'espace qui lui est
rserv. Pourquoi donc ? Le mode protg t conu pour permettre l'existence de systmes
multitches stables. Imaginons qu'une des tches commette une "erreur de protection", le
systme d'exploitation la ferme, et le systme de plante pas - du moins en thorie...
Par exemple, il est n'est pas possible une tche de faire des E/S sur certains ports, donc de
modifier anarchiquement l'tat du matriels, ce qui pourrait entraner un plantage - seul le
systme d'exploitation est autoris le faire, mais il a pour mission de contrler
scrupuleusement le processus... (Et l, on voit que Windows 95 a t fait lgrement la va-
vite...). Il n'est pas non plus possible de lire des portions de mmoires rservs d'autres
programmes ou au systme d'exploitation, question de confidentialit et de scurit.
Ce qui est trs apprciable, c'est que toutes les erreurs qui pourraient survenir dclenchent ce
que l'on nomme une Exception, c'est dire une interruption dclenche par le processeur,
intercepte par le systme d'exploitation, qui prend les mesures ncessaires (fermer l'application
en question). Consquence immdiate : les plantages, c'est du pass !
Maintenant que nous savons ce qu'est un microprocesseur, penchons-nous sur son organisation
intrieure. En effet, un nombre trs important de divers lments est compris dans la puce de silicium
que vous avez pu observer ci-dessus.
En fait, un microprocesseur x86 nest pas uniquement un bloc de n millions de transistors, mais bien un
assemblage intelligent et fortement optimis de blocs de transistors nomms units. Chaque unit est
ddie une tche prcise. On peut les regrouper en trois parties principales. Il s'agit de :
Le jeu de registre contient l'ensemble des registres du microprocesseur. On appelle registres des cellules
mmoires qui sont loges non pas dans la mmoire RAM de l'ordinateur, mais directement sur le
processeur lui mme dans le but de recevoir des informations spcifiques, notamment des adresses et
des donnes stockes durant l'excution d'un programme. Il existe plusieurs types de registres, mais ils
sont en nombre trs limite. Certains d'entre eux sont affects des oprations d'ordre gnral et sont
accessibles au programmeur tout moment. Nous disons alors qu'il s'agit de registres gnraux.
D'autres registres ont des rles bien plus spcifiques et ne peuvent pas servir un usage non
spcialis. Enfin, d'autres registres sont invisibles et par consquent inaccessible au programmeur. Ces
registres ne sont accessibles qu'au microprocesseur. Lorsque nous excutons un programme, l'UAL
Les registres prsentent l'avantage de permettre un accs beaucoup plus rapide qu'un accs la RAM.
Le microprocesseur et la mmoire RAM constituent en effet deux lments distincts d'un systme
informatique et le processeur doit tout d'abord charg travers un canal toutes les donnes auxquelles il
veut accder. Cela entrane naturellement un certain dlai qui peut tre vit en stockant les donnes
directement dans le microprocesseur. C'est justement cela que servent les registres.
Les instructions agissent sur des donnes qui sont situes soit en mmoire, soit dans des registres du
processeur. Pour accder une donne en mmoire, il faut spcifier son adresse. Pour accder une
donne dans un registre, il faut spcifier son nom (chaque registre possde un nom qui est une chane
de caractres). On peut les regrouper en quatre catgories.
Si lon schmatise :
Chaque gnration tant un amalgame et une amlioration des prcdents, excepts pour les 8088,
8086, 80188, 80186, et 80286 pour lesquels le registre est identique. C'est pourquoi quand je parlerai
de 8086, il sera en fait question de ces 5 processeurs.
AX (Accumulateur) ;
BX (Base) ;
CX (Compteur) ;
et DX (Donnes).
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 caractrisent.
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. Lorsque vous devez utiliser un registre pour une
opration quelconque et que vous ne savez pas lequel utiliser, privilgiez celui-ci cest le plus
optimis au niveau de la rapidit dexcution des oprations. Il est appel "accumulateur".
Exemple :
Le registre BX peut servir de base. Il est utilis pour ladressage indirect, nous verrons plus tard ce que
ce terme signifie.
Le registre CX est utilis comme compteur dans les boucles. Par exemple, pour rpter 10 fois une
instruction en assembleur, on peut mettre la valeur 10 dans CX, crire l'instruction prcde d'une
tiquette qui reprsente son adresse en mmoire, puis faire un LOOP cette adresse. Lorsqu'il
Exemple :
Chacun de ces registres peut tre dcompos en deux sous registres de 8 bits. Par exemple, le registre
AX pouvait tre dcompos en AH et AL comme le montre la Figure si dessus. Le registre AH contient
les 8 bits de poids fort de AX, et AL contient les 8 bits de poids faible. (H pour High et L pour Low).
Au lancement des processeurs 80386 et plus rcents, tous ces registres ont t tendus 32 bits.
Ainsi, le registre AX est devenu EAX (Extended AX). Pour la compatibilit ascendante, AX fait toujours
rfrence au registre 16 bits et on utilise EAX pour faire rfrence au registre 32 bits. AX reprsente les
16 bit de poids faible de EAX tout comme AL reprsente les 8 bits de poids faible de AX (et de EAX). Il
n'y a pas de moyen d'accder aux 16 bit de poids fort de EAX directement. Mais alors, pour travailler
sur la partie haute des 32 bits, il faut employer le registre EAX ou faire une rotation des bits pour la
ramener sur les 16 bits du bas accessibles via AX. Il est vident que ces quatre registres sont lis. Il
lon modifie par exemple AH, cela changera AX, et par consquent EAX. Seuls AH et AL sont
indpendant lun de lautre. Pour modifier la partie haute des 32 bits du registre EAX, il faut procder
via le registre EAX. Par contre, pour modifier la partie basse des 32 bits, on peut procder laide du
registre AX. Il est galement possible de modifier la partie haute du registre de 16 bits AX avec le
registre AH, et la partie basse avec le registre AL. Il est intressant de travailler avec ces registres (AH
et AL) pour la manipulation de caractres ou des donnes dont la taille ne dpasse pas un octet.
Registre(s) Taille
EAX 32 bits
AH AL 8 bits chacun
Les autres registres tendus sont EBX, ECX, EDX, ESI et EDI. La plupart des autres registres sont
galement tendus. BP devient EBP; SP devient ESP; IP devient EIP; et
FLAGS devient EFLAGS.
Registres de segments
Les registres 16 bits CS, DS, SS et ES sont des registres de segment. Ils indiquent quelle zone de la
mmoire est utilise pour les diffrentes parties d'un programme. 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 !
CS pour segment de code, registre permettant de fixer ou de connaitre ladresse du dbut des
instructions dun programme.
SS pour segment de pile, ce registre pointe sur la pile. Comme je ne vous ai pas encore
expliqu ce qu'est la pile, j'y reviendrai plus tard.
ES pour segment extra, ce registre est utile pour la manipulation de donnes entre plusieurs
segments en parallle des registres DS, FS et GS.
FS et GS pour segment extra, ces registres ont les mmes fonctionnalits que le registre DS. Il
est disponible partir des processeurs 80386.
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"
On ne peut pas mettre directement une valeur immdiate dans un registre de segment, le
microprocesseur ne le permet pas:
Par contre :
Registres doffset
SI (Index de source) et DI (Index de destination). Ils sont souvent utiliss comme des pointeurs, mais
peuvent tre utiliss pour la plupart des mmes choses que les registres gnraux. Cependant, ils ne
peuvent pas tre dcomposs en registres de 8 bits.
Les registres 16 bits BP (Pointeur de base) et SP (Pointeur de pile) sont utiliss pour pointer sur des
donnes dans la pile du langage machine et sont appels le pointeur de base et le pointeur de pile,
respectivement. Nous en reparlerons plus tard. Le registre IP (Pointeur dinstruction) contient le
dplacement entre le dbut du registre CS et la prochaine instruction que doit excuter le processeur (Il
peut tre dangereux de manipuler ce registre car, de par sa fonction, une mauvaise utilisation risque
dentraner un plantage de votre programme).
Pour ces registres, on trouve galement la capacit de dcoupage des registres de 32 16 bits
prcdemment nonc dans sur la section des registres gnraux.
Registre de flag
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. Le registre flags permet de fixer et ce connatre ltat du processeur grce aux
diffrents bits qui le composent, ce qui permet ainsi davoir tout instant ltat rsultant de lexcution
dune opration par le microprocesseur. La plupart des instructions affectent ce registre. Chaque bit
relate ltat spcifique de la dernire instruction excut. Aprs lutilisation de certaines instructions, il est
affect et ltat de ses diffrents bits permet de prendre des dcisions, par exemple choix lors de
branchement conditionnel (boucle et saut) pour vrifier sil y a une retenue aprs une opration
arithmtique. Le registre FLAGS est compos de 32 bits galement appel indicateur :
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Bit
0 NT IOPF OF DF IF TF SF ZF 0 AF 0 PF 1 CF Appellation
Les 16 premiers bits (0 15) sont considrs comme les bots de drapeau.
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
ID VIP VIF AC VM RF
Les case qui sont grises correspond aux bits rservs ou non dfinis par Intel.
EFLAGS est un registre en deux groupes de bits indicateurs.
PF (Party Flag), indicateur de parit. Ce bit est positionn ltat haut 1 si le rsultat dune
opration est un nombre pair de bit mis 1.
AF (Auxiliary Flag), retenue auxiliaire. Ce bit est positionn ltat haut 1 si, aprs une
opration, il y a une retenue.
ZF (Zero Flag), indicateur de zro. Ce bit est positionn ltat haut 1 si, aprs une opration,
le rsultat est nul.
SF (Sign Flag), indicateur de signe. Ce bit est positionn ltat haut 1 si, aprs une opration,
le rsultat est ngatif.
IF (Interrupt Flag), sert empcher les appels dinterruptions lorsquil est positionn 1.
Cependant, toutes les interruptions ne sont pas masquables.
OF (Overflow Flag), indicateur de dbordement de capacit. Ce bit est positionn ltat haut 1
si, aprs une opration, le rsultat dborde la capacit du registre. Prenons, par exemple,
laddition de la valeur 0FFFFh maximale qui peut tre stocks dans un mot de 16 bits avec une
valeur 1 quelconque :
0FFFFh + 1h = 10000h. Le rsultat de cette addition est la valeur 10000h et ce nombre ne
tient pas sur 16 bits ! Il y a donc un dpassement ! Cet indicateur sert galement signaler
des dbordements lors de lutilisation darithmtique sign (-32767 32768 contre 0
65535).
Il en existe dautres part ceux quon a vu prcdemment, ce sont les registres MMX et SIMD mais
nous ne les utiliserons pas ici.
A noter que certains assembleurs ne grent pas les dernires volutions des processeurs 80x86 dIntel,
et en particulier la gestion des 8 registres SIMD, et des 47 instructions qui en permettent la
manipulation.
Il existe un certain nombre de registres qui sont faiblement documents. Ces registres existent depuis le
386, ils servent entre autre pour la gestion du mode protg et la mise au point des programmes.
Les cinq registres de contrle sont CR0 CR4 (Control Register).
Les huit registres de mise au point (Debug) sont DR0 DR7 (Debug Register).
Les cinq registres de teste sont TR3 TR7 (Test Register).
Le registre GTDR (Global Descriptor Table Register).
Le registre ITDR (Interrupt Descriptor Table Register).
Le registre LDTR (Local Descriptor Table Register).
Le registre TR (Task Register).
La pile
La programmation d'un ordinateur ncessite l'usage (d'au moins) une pile. Une pile est une rgion de
la RAM o lon va stocker ou retirer des informations, elle est structure linairement et dont on ne peut
manipuler que le sommet, l'image d'une pile d'assiettes : vouloir retirer une assiette du milieu conduit
la catastrophe. La seule mthode d'accs consiste empiler ou dpiler des assiettes partir du
sommet de la pile. Une telle structure permet de conserver en mmoire l'ordre selon lequel on y a
stock des informations. En les dpilant, l'ordinateur se retrouve dans l'tat ou il y tait avant les
oprations qui ont conduit des empilements successifs. L'assembleur vous fera manipuler une pile qui
Dans l'architecture x86 32bits, le registre ESP sert indiquer l'adresse du sommet d'une pile dans la
RAM. Les instructions "PUSH" et "POP" permettent respectivement d'empiler et de dpiler des
donnes. Les instructions "CALL" et "RET" utilisent la pile pour appeler une fonction et la quitter par la
suite en retournant l'instruction suivant immdiatement l'appel.
En cas d'interruption, les registres EFLAGS, CS et EIP sont automatiquement empils. Dans le cas d'un
changement de niveau de priorit lors de l'interruption, les registres SS et ESP le sont aussi.
La mmoire
La mmoire est la partie de lordinateur dans laquelle les programmes et les donnes sont rangs. Sans
mmoire, dans laquelle le processeur lit et crit de linformation, il ny aurait pas dordinateurs tels que
nous les connaissons. Une mmoire est form dun certain nombre de cellules (ou cases), chacune de
Une analogie consiste comparer la mmoire une longue range de tiroirs alignes les un derrire les
autres. Si on donne chaque tiroir un numro, en commenant par 0 pour le 1r tiroir, on dira que ce
numro est l'adresse de la mmoire, dans la suite on parlera d'adresse mmoire. La coutume est (de
nombreux avantages la justifie) de noter les adresses mmoires en hexadcimal.
L'unit mmoire de base est l'octet. Un ordinateur avec 3 Go de mmoire peut stocker jusqu' environ 3
milliards d'octets d'informations.
0 1 2 3 4 5 N-1
3A 11 B1 8A EF 6A AB
Adresses Mmoire
Ce qu'il est important d'avoir l'esprit, c'est que le microprocesseur a besoin de mmoire pour travailler
: c'est dans la mmoire qu'il va lire son programme, crire des valeurs...
La pagination mmoire
Les processeurs IA-32 sont dots dune fonction appele pagination. Elle permet un segment dtre
divis en blocs mmoire, appels pages et mesurant tous 4096 octets. Le mcanisme de pagination
permet lexploitation par tous les programmes qui fonctionnent
En mme temps en espace mmoire apparemment plus vaste que la mmoire physiquement install sur
lordinateur. Lensemble des pages est parfois appel la mmoire virtuelle. Un systme dexploitation
moderne dispose normalement dun programme appel le gestionnaire de mmoire virtuelle (VMM,
Virtual Memory Manager).
La pagination constitue une solution technique de premire importance un problme rencontrent sans
cesse les programmeurs et les concepteurs de matriels. En effet, pour pouvoir excuter un programme,
il faut le charger en mmoire, mais la mmoire est coteuse. Lutilisateur veut pouvoir lancer plusieurs
programmes la fois et basculer entre lun et lautre. En revanche, lespace disque est beaucoup mois
coteux. La pagination donne lillusion de disposer dune quantit quasi illimite de mmoire vive. En
revanche, une partie de la mmoire tant remise sur disque dur, les accs sont beaucoup moins
rapides quavec la mmoire relle.
Organisation de la mmoire
Le mode segment.
Le mode protg.
Le premier style est le mode par dfaut de tous les processeurs x86. Ce style est contraignant dans son
fonctionnement, mais il nest pas ncessaire, contrairement au mode protg, de se lancer dans de
lourdes routines dinitialisation mal matrises. Ce style par dfaut pourrait tre nomm mode
dadressage segment. En effet, la mmoire dans ce mode nest pas un long et unique bloc, mais une
suite de "segment" Les segments ont une taille limite de 64Ko. Cette capacit dadressage de 65 535
octets est due la limite des 16 bit des premiers processeurs 8086. A lpoque, en 1981, un
processeur qui tait capable dadresser plus de 64 ko, ctait trs fort, et le prix de la RAM tait
prohibitif ! Pour trouver ladresse relle de la mmoire, il faut une valeur de positon appel en anglais
"offset" (dcalage). Cet offset est donc le dplacement qui existe entre le premier octet du segment et
loctet de la mmoire qui est pointe.
A partir de ces deux valeurs SEGMENT: OFFSET, on peut localiser nimporte quel octet dans la
mmoire adressable par le processeur. Exemple A000h:0000h
Lorsquils ont conu le mode protg, les ingnieurs dIntel en ont profit pour se dbarrasser dune
srieuse limitation de leurs processeurs jusqualors en mode protg : La limitation dadressage mmoire
de 1Mo a disparu. Il devient possible dadresser 16Mo sur 80286 et 4Go partir du 80386. Par
ailleurs, le 80386, dot dun bus sur 32 bits, dispose de nouveaux modes dadressage mmoire.
A partir du 80286, le processeur dispose dinstructions pour la commutation des tches; cette opration
devient ds lors trs simple programmer et ainsi plus fiable. Ces processeurs comportent aussi une
gestion automatique de la mmoire virtuelle, pas trs intressante sur 80286, mais relativement
performante sur 80386. Le processeur a aussi la capacit de simuler autant de processeurs en mode
rel que lon souhaite et de leur allouer chacun 1 Mo de mmoire. Cest ce qui se passe lorsquon
lance un programme DOS sous Windows. Les programmes excuts ont limpression de tourner sur un
processeur indpendant, avec un mmoire indpendante.
Les programmes Win32 fonctionnent en mode protg depuis le 80286. Mais le 80286 c'est maintenant
de l'histoire ancienne. Donc nous devons seulement nous intresser au 80386 et ses descendants.
Windows dirigent chaque programme Win32 sparment. Ceci signifie que chaque programme Win32
aura sa disposition ses propres espaces de mmoire. Cependant, cela ne signifie pas que chaque
programme win32 a 4GB de mmoire physique, mais seulement que le programme peut adresser
n'importe quelle adresse dans cette gamme. Windows fera tout le ncessaire pour adresser les vraies
rfrences (physiques) du programme aux adresses mmoires valables 00401000 qu'il utilise. Bien
sr, le programme doit respecter les rgles de Windows, autrement il causera une Erreur de Protection
Gnrale tant redoute. Chaque programme est seul dans son espace d'adresse. C'est la diffrence
avec les programmes Win16. Tous les programmes Win16 peuvent malheureusement plus ou moins se
chevaucher les uns les l'autres. Mais pas sous Win32. Ces gardes fous rduisent la chance d'une
criture du code d'un programme par dessus les donnes d'un autre.
Le modle de mmoire est aussi rsolument diffrent des vieux jours du monde du 16 bits. Dsormais,
sous Win32, nous ne sommes plus concerns par le modle de mmoire en plusieurs segments!
(0001.xxxx puis 0002.xxxx puis 0003.xxxx) L'assembleur 32 bits est la fois plus clair et plus
simple que le DOS et il n'est pas handicap par l'arithmtique des segments. Vous n'avez plus vous
soucier des paires de registres comme AX:DX pour les entiers longs et il n'y a plus la limitation des
segments de mmoire 64 Ko qui existait dans la segmentation 16 bits. Il y a seulement un seul
modle de mmoire : le modle de mmoire uniforme (Flat). La mmoire est un seul espace continu.
Quand vous programmez sous Win32, vous devez respecter quelques rgles importantes. Une rgle
majeure est que Windows emploie lui-mme ESI, EDI, EBP et EBX et les valeurs de ses registres
changent, en mme temps qu'une autre application tourne en parallle avec Windows. Rappelez-vous
donc cette rgle primordiale d'abord : si vous employez chacun de ces quatre registres l'intrieur d'une
procdure, n'oubliez jamais de les reconstituer "rtablir" avant le contrle de retour Windows.
L'exemple vident ce sont les Call qui appellent une API de Windows. Cela ne signifie pas que vous ne
pouvez pas employer ces quatre registres, vous le pouvez. Mais seulement que vous devez rtablir ces
registres aprs un call.
Les instructions des x86 sont trs nombreuses et il nest pas question de les dvelopper toutes dans ce
guide. Nous dtaillerons dans chapitre uniquement les instructions classiques, c'est--dire celles qui sont
les plus importantes pour une initiation la programmation courante en assembleur. Dans ce chapitre,
nous dvelopperons le fonctionnement des instructions du microprocesseur et nous agrmenterons ces
descriptifs par quelques courts exemples de mise en situation. Nous approfondirons un certain nombre
de ces instructions.
Pralablement, nous verrons quelques prcautions dusage lies lemploi et au maniement des
instructions, des directives et de certains mots rservs. Ces avertissements engloberont les conventions
de lecture et dcriture des diffrents champs dvelopps.
Et oui, comme toute "langue vivante", l'assembleur possde des propres rgles de "grammaire" et
d'"orthographe". Et gare vous si, dans un dsir d'indpendance tout fait mal propos, vous dcidez
de ne pas y plier!
Ceci dit, ces rgles sont trs simples et il faudra qu'un peu d'habitude pour les connatre. Mieux mme,
ces programmes que jusqu' maintenant vous considriez tre du chinois en seront rduit n'tre
Les rgles absolues: si par malheur vous les transgresser, vous vous ferez froidement jeter
par la machine avec en guise de compliment de petits mots d'amiti de type "ILLEGAL
FORMAT", "MISSING OPERAND", le tout dans le plus pur anglais de Shakespeare;
Les rgles conseilles: ce sont celles qui sont laiss l'apprciation du client. En gros, si vous
ne les saviez pas, vous risquez :
d'une part de passer beaucoup de temps que ncessaire pour faire tourner un
programme.
d'autre part de devoir vous reporter au chapitre consacr au code erreur par suite d'une
tourderie ce qui est trs dsagrable.
Un programme en assembleur a une forme bien particulire. Chaque ligne dun code source assembleur
comporte une instruction. Chaque ligne est compose de champs. De gauche droite, on a :
tiquette
Par exemple vous ne pouvez pas prendre le mot 'MOV' comme nom de label.
Nutilisez pas de labels qui peuvent tre confondus avec dautres labels.
Evitez les lettres I, O, Z, et les chiffres 0, 1, 2.
Evitez aussi des labels tels que XXXX et XXXXX car on ne les diffrencie pas aisment.
Example:
Mnmonique
Un mnmonique dinstruction est un mot court qui identifie une instruction. Les mnmoniques du langage
assembleur sont dorigine anglaise. Les lecteurs franais retrouvent nanmoins de nouveaux lments
communs avec leur langue.
Oprandes
La syntaxe assembleur Intel x86 dfinit loprande de gauche comme oprande destination, celui dans
lequel on trouve le rsultat de linstruction. Loprande de droite est appel oprande source. Le champ
oprande est un champ optionnel selon linstruction (Une instruction peut avoir entre zro et trois
oprandes). Dans la plupart des assembleurs, il ne peut y avoir quune seule instruction par ligne.
Chaque oprande tre le nom dun registre, une constante, une expression constante ou un
emplacement mmoire.
13 Constante
2+6 Expression constante
eax Registre
Aujourdhui, vous savez exactement comment votre programme fonctionne. Nanmoins, si quelquun
dautre le lit ou si vous le relisez vous-mme quaprs quelque temps (vous aurez peut-tre oubli le
rle de telle ligne ou telle fonction), vous serez lun comme lautre dy trouver des commentaires
explicatifs. Ces commentaires expliquent (en franais ou dans toute autre langue que vous parlez) ce
que se passe dans le programme crit en langage informatique.
Ainsi, un commentaire est un texte ajout au code source dun programme servant dcrire le code
source, facilitant sa comprhension par les humains. Il est donc spar du reste du code grce une
syntaxe particulire. La norme est le point virgule (;). Le positionnement de se sigle dans une ligne
implique que tout le texte qui se trouve sa suite est considr comme un commentaire. Ce texte ne
sera donc pas trait lassemblage. Certains assembleurs tolrent la syntaxe dautres langages comme
le C, cest--dire les couples de caractres : // et /* */. Mais je vous conseille de respecter la
norme assembleur dans un souci de compatibilit entre assembleurs. Vous avez dj vu des exemples
des commentaires dans les exemples de programmes que nous avons prsents, voici un exemple de
code incluant des commentaires :
Lisibilit et prsentation
Exemple :
La lisibilit du code source a un impact direct sur la faon dont un dveloppeur comprend un systme
logiciel. La maintenance de code dsigne la facilit de modifier un systme logiciel pour ajouter de
nouvelles fonctionnalits, modifier des fonctionnalits existantes, corriger des bogues ou amliorer les
performances. Bien que la lisibilit et la maintenance rsultent de plusieurs facteurs, la technique de
codage reprsente une partie spcifique du dveloppement de logiciel sur laquelle tous les dveloppeurs
peuvent avoir une influence, il est donc fortement conseill, voire absolument indispensable, dtre un
minimum rgulier et strict dans la prsentation des programmes sources. Aussi, il suffit de respecter une
prsentation uniforme et rgulire, et dappliquer pour cela des rgles lmentaires, qui ne sont pas
spcifiques lassembleur :
Appliquer les tabulations pour amliorer la lisibilit du code source, Ainsi, essayer de
respecter des colonnes imaginaires ddies aux tiquettes, mnmoniques, oprandes et
commentaires.
User des majuscules bon escient. Il est prfrable de rserver par exemple les mots en
majuscules aux dclarations de constantes.
Essayer de casser la linarit du code source car il est relativement lourd danalyser un
fichier source qui nest quune longue suite dinstructions. Pour cela, il faut essayer de faire
des modules, de commenter par blocs. Ce qui se traduit par des sparations des
commentaires grce des lignes de tirets. Nous verrons cela en dtail dans le paragraphe
qui traite la programmation modulaire.
Notes et abrviations
Chaque instruction liste dans ce chapitre est dcrite selon un mme modle, compos de diffrents
champs faisant rfrence aux notions : drapeaux et oprandes.
Comme nous lavons dj vu, le microprocesseur possde un registre particulier quest le registre flag.
La plupart des instructions modifient les indicateurs du registre EFLAGS. Un tableau indique leffet de
linstruction couramment dcrite sur ces indicateurs. Il a la forme suivante ;
OF DF IF TF SF ZF AF PF CF
Pour indiquer ltat de chaque bit composant les flags de ces tableaux, nous avons choisi les signes
suivants :
OF DF IF TF SF ZF AF PF CF
0 * * ? * 0
A la lecture de ce tableau, on peut dire que la direction est interne, il ny a pas dinterruption, il ny a
pas dexcution pas pas, le signe, le zro, la parit sont fonction de lexcution. Enfin, la retenue
auxiliaire est variable. Le dbordement et la retenue sont annuls.
Oprandes
Pour chaque instruction, on utilisera des oprandes afin de visualiser les paramtres de fonctionnement
de chacune. On trouve des mmoires et des registres classiques.
Reg8 dsigne un registre 8 bits : AL, AH, BL, BH, CL, CH, DL, DH.
Reg16 dsigne un registre 16 bits : AX, BX, CX, DX, DI, SI, BP, SP.
Reg32 dsigne un registre 32 bits : EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP.
Accum dsigne laccumulateur qui peut tre AL, AX ou EAX selon la taille de lopration.
Mem16 dsigne un emplacement mmoire de 16 bits.
Mem32 dsigne un emplacement mmoire de 32 bits.
Immed8 dsigne une valeur immdiate de 8 bits.
Immed16 dsigne une valeur immdiate de 16 bits.
Immed32 dsigne une valeur immdiate de 32 bits.
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.
Les instructions arithmtiques et logiques sont effectues par l'unit arithmtique et logique. Il s'agit
d'oprations directement effectues sur les bits de la donne que l'on traite. Sont comprises dans cette
appellation :
Les oprations arithmtiques et logiques modifient l'tat des indicateurs. Voici la liste des ces
instructions :
AAA, AAD, AAM, ADC, ADD, SUB, SBB, CBW, CWD, CWDE, CQD, DAA, DAS, DEC, INC, MUL, DIV,
IMUL, IDIV, AND, OR, XOR, NOT, NEG.
Ces instructions permettent une manipulation directe des bits, un un ou par groupe. Il faut remarquer
que ces instructions fonctionnent sans lemploi des oprations logiques (AND, not, or, etc.) Cette
capacit travailler de cette manire sur les bits est une spcificit de lassembleur.
Instructions de dcalage
On distingue trois groupes dinstructions dans cet ensemble. Le premier groupe permet le dcalage des
bits prsents dans un groupe (octet, mot ou double mot). La direction du dcalage peut tre fixe vers
la droite ou la gauche ou de plusieurs bits.
SAL, SHL, SAR, SHAR, SHLD, SHRD.
Le deuxime groupe est spcialis dans les rotations de bit dans un mme octet, mot ou double mot.
ROR, ROL, RCL, ROR.
Instructions de traitement
Le troisime groupe est constitu des instructions de traitement. C'est--dire les instructions permettant
de manipuler les bits directement, de changer leu tat (0, 1), deffectuer des tests.
BT, BTC, BTR, CLC, STC, CMC, CLD, STD, CLI, STI.
Nous sommes sur le point daborder une partie intressante, dans la mesure ou elle permet de
comprendre la raction du programme suite la valeur du rsultat (0 ou 1). Nous allons maintenant
nous intresser aux conditions. Sans conditions, nos programmes informatiques feraient un peu toujours
la mme chose, ce qui serait carrment barbant la fin.
Pour tester si une condition est vraie avant d'excuter une action, on dispose des instructions permettent
dactiver des branchements "saut", avec ou sans fonction de test et de choix. Le droulement du
programme est alors dvi de son chemin courant vers un autre, spcifique du choix. On distingue ces
instructions de saut en deux catgories suivant que :
Saut inconditionnel
Saut conditionnel
Ces branchements sont effectifs aprs validation dune condition. Il saute ladresse seulement si la
condition est vraie. Dans le cas contraire, lexcution se poursuit avec linstruction suivante. Ces
instructions sont lies aux instructions de test.
Test
Ces instructions permettent la comparaison de deux oprandes passs en paramtre et, en fonction du
rsultat du test, positionnent les flags (CF, SF, AF, etc.). Ces instructions sont lies aux instructions de
saut conditionnel.
CMP, TEST.
MOV registre1, registre2 a pour effet de copier le contenu du registre2 dans le registre1, le contenu
pralable du registre1 tant cras. Cette instruction vient de l'anglais move qui signifie dplacer
mais attention, le sens de ce terme est modifi, car l'instruction MOV ne dplace pas mais place tout
simplement. Cette instruction ncessite deux oprandes qui sont la destination et la source. Ceux-ci
peuvent tre des registres gnraux ou des emplacements mmoire. Cependant, les deux oprandes ne
peuvent pas tre toutes les deux des emplacements mmoire. De mme, la destination ne peut pas tre
ce qu'on appelle une valeur immdiate (les nombres sont des valeurs immdiates, des valeurs dont on
connait immdiatement le rsultat) donc pas de MOV 10, AX. Ceci n'a pas de sens, comment pouvez-
vous mettre dans le nombre 10, la valeur dAX ? 10 n'est pas un registre.
Exemples :
Remarque :
Il est strictement interdit de transfrer le contenu dune case mmoire vers une autre case
mmoire comme suit :
On na pas le droit aussi de transfrer un registre segment vers un autre registre segment sans passer
par un autre registre :
Voil ! Une partie pnible de terminer. Par contre, je n'en ai pas dtaill pour le moment les instructions
car je pense que vous comprendrez mieux le moment venu, avec un exemple concret d'utilisation.
Je suis bien conscient que ces chapitres taient riches en vocabulaire, en nouveauts mais bon, voil :
votre calvaire... ne fait que commencer. Eh oui : tout ceci tait un amuse-bouche ! Maintenant, nous
rentrons dans le vif du sujet. Cela fait dj une bonne base pour commencer. Si vous connaissez dj
tous a sur le bout des doigts, vous tes bien parti. D'ailleurs j'en profite pour vous rappeler qu'il est
ncessaire de connaitre ces chapitres pour pouvoir passer aux suivants. En fait, je dirais mme que
vous n'y parviendrez pas avant un bon bout de temps... Mais tout arrive avec le temps ;) Donc
patience... Et surtout bonne chance ! Et n'oubliez pas que pour apprendre, rien ne vaut la pratique !
Mais rassurez-vous, partir de maintenant tout ce que nous allons faire va apparatre l'cran. J'espre
que vous avez encore de l'nergie, car, dans le chapitre suivant, nous aborderons quelque chose de
bien plus passionnant...
Pour dvelopper des programmes, il faut des outils. Ces outils sont de plusieurs catgories et plus ou
moins performants et complexes en fonction de leur usage. Nous allons expliquer lutilit de chacun
dentre eux. Mais avant a, faisons un petit rcapitulatif.
Chaque type de processeur comprend son propre langage machine. Les instructions dans le langage
machine sont des nombres stocks sous forme octets en mmoire. Chaque instruction son propre code
numrique unique appel code d'opration ou Opcode. Les instructions des processeurs x86 varient en
taille. L'Opcode est toujours au dbut de l'instruction. Beaucoup d'instructions comprennent galement les
donnes (des constantes ou des adresses) utilises par l'instruction. Le langage machine est trs difficile
programmer directement. Dchiffrer la signification d'instructions codes numriquement est fatigant
03 C3
C'est trs peu clair. Heureusement, un programme appel un assembleur peut faire ce travail laborieux
la place du programmeur.
Un programme en langage d'assembleur est stock sous forme de texte (comme un programme dans un
langage de plus haut niveau). Chaque instruction assembleur reprsente exactement une instruction
machine. Par exemple, l'instruction d'addition dcrite ci-dessus serait reprsente en langage assembleur
comme suit :
Ici, la signification de l'instruction est beaucoup plus claire qu'en code machine. Le mot ADD est une
mnmonique pour l'instruction d'addition.
Un assembleur est un programme qui lit un fichier texte avec des instructions assembleur et convertit
l'assembleur en code machine. Les compilateurs sont des programmes qui font des conversions
similaires pour les langages de programmation de haut niveau. Un assembleur est beaucoup plus simple
qu'un compilateur. "Cela a pris plusieurs annes aux scientifiques de l'informatique pour concevoir le
simple fait d'crire un compilateur, En effet, votre titre dinformation, la conversion du code source en
code machine est trs complexe. Elle implique de comprendre comment transcrire un ensemble
dinstructions de haut niveau en instructions machine de bas niveau, trs spcifiques. Lorsque le
processus est complet, un excutable est cre. Cest ce programme que vous pouvez excuter. Des
livres entiers existent sur la faon de convertir les langages de programmation de haut niveau en
langage machine. Heureusement pour vous, les vendeurs de compilateurs ont lu tous ces livres : vous
navez pas besoin de comprendre comment cela fonctionne Vous avez juste assembler votre code
avec un assembleur les programmes que vous avez crits" Si vous dsirez approfondir vos
connaissances dans le domaine de la compilation, vous devez essayer : Engineering a Compiler, Keith
Cooper, Linda Torczon. Advanced Compiler Design and Implementation, Morgan Kaufmann.
Chaque instruction du langage d'assembleur reprsente directement une instruction machine. Les
instructions d'un langage de plus haut niveau sont beaucoup plus complexes et peuvent requrir
beaucoup d'instructions machine. Une autre diffrence importante entre l'assembleur et les langages de
haut niveau est que comme chaque type de processeur son propre langage machine, il a galement
Comme vous avez srement d constater, chaque famille de processeur utilise un jeu d'instructions
diffrent. Il existe beaucoup de langages assembleurs, qui changent selon l'architecture (Intel x86,
MIPS, ARM, Motorola, Zilog, Transmeta, Texas Instruments, VIA, Atmel ) et dans une moindre mesure
selon les systmes d'exploitation (Linux, Windows...).
J'ai choisis de se concentrer sur le langage assembleur des processeurs x86 de la famille Intel parce
qu'il est utilis sur chaque PC dans le monde et largement le plus populaire de larchitecture des
processeurs.
Alors votre avis, de quels outils un programmeur a-t-il besoin ? Si vous avez attentivement suivi cette
introduction, vous devez en connatre au moins un !
Eh oui, il s'agit de lincontournable assembleur, sujet principal de ce guide, ce fameux programme qui
permet de traduire votre langage assembleur en langage machine. Mais cela ne suffit pas ! Il faut
dautres outils pour mettre au point les logiciels, quils soient petits ou grands.
Je ne vais pas vous laisser deviner plus longtemps. Voici le strict minimum pour un programmeur :
Un diteur de texte qui vous permet de modifier votre code source sans quitter
lenvironnement.
Un assembleur permettant de faire la traduction du langage assembleur en langage machine.
Un diteur de lien linker permettant la cration du fichier excutable.
Un diteur de ressources permettant de crer des ressources Windows telles que des bitmaps,
des icnes, des boites de dialogues et des menus.
Un dbuggeur pour vous aider traquer les erreurs dans votre programme.
Dtaillons ce baratin :
Le programme doit tre saisi dans un fichier texte dextension .asm non format c'est--dire sans
caractres en gras, soulign, avec des polices de caractres de diffrentes tailles, ... appel fichier
L'assembleur transforme le fichier source assembleur en un fichier binaire dit fichier objet (code en
langage machine, non excutable car incomplet). Il s'agit d'un fichier avec l'extension .obj. Ce fichier
contient des instructions et des donnes en langage machine, et chaque donne a un nom symbolique
par lequel elle est rfrence.
Lditeur de lien lie les codes objets et rsout les rfrences. Cest lui qui produit le fichier excutable. Il
li les modules objets, va chercher les fonctions situes dans des bibliothques de fonctions ou de
routines. Il permet galement de crer par exemples les librairies .lib, ou les .dll.
Si vous avez pass votre nuit sur un programme et que, au matin, rien ne fonctionne encore, vous avez
quatre possibilits :
Abandonner (dommage).
Vous procurer un ordinateur trs trs lent pour essayer de voir ce qui ne va pas durant
lexcution du programme (pas bon pas bon).
Remplir votre programme dinstructions daffichage de faon quun petit message saffiche aprs
lexcution de chaque ligne de code, pour vous annoncer que telle ligne vient dtre excut,
ce qui vous permettra de dterminer lendroit o quelque chose se droule mal (a fonctionne
mais cest ce quon appelle une galre).
Vous employer un dbogueur (cela fonctionne et ce nest pas une galre).
Ban, ds que votre programme dpassera quelques lignes, il est presque certain que vous vous heurtez
quelques problmes lors du premier assemblage. Si ce nest pas le cas, vous tes un super
programmeur ou vous avez recopi la source dans un livre. Un dbuggeur est un outil qui vous permet
dexcuter votre programme ligne par ligne. Cela facilite le contrle de la logique de votre programme et
la comprhension de son fonctionnement, la localisation et la correction des erreurs. Bien que le choix
du dbogueur soit personnel. Je suggre tous les dbutants de commencer avec un dbogueur
comme OllyDbg, qui est un analyser, debugger et assembleur 32 bits avec une interface intuitive. Il est
bien puissant et ses plugins lui permettent mme de rivaliser avec le grand SoftIce.
Pour faire bref, un programme crit en assembleur doit subir un certain nombre de transformations avant
de pouvoir tre excut. La figure suivante prsente les diffrentes tapes du traitement d'un
programme en langage d'assemblage.
Soit on rcupre chacun de ces programmes sparment. C'est la mthode la plus complique, mais
elle fonctionne. Dailleurs bon nombre de programmeurs prfrent, "utiliser ces programmes sparment"
et utiliser un simple fichier .bat pour lancer lassemblage, l'artillerie lourde n'est pas indispensable et les
logiciels avec surenchres de fonctionnalits inutiles, c'est juste bon perdre du temps. Une simple
fonction "Go To Line" la rigueur est tout ce qu'il faut pour eux. Je ne dtaillerai pas cette mthode ici,
je vais plutt vous parler de la mthode simple.
L'environnement de dveloppement intgr a t conu pour vous permettre de vous dplacer de fentre
en fentre et de fichier en fichier de diffrentes faons, selon vos prfrences ou impratifs de projet.
Vous pouvez choisir de parcourir tous les fichiers ouverts de l'diteur ou de parcourir toutes les fentres
Outil actives dans l'IDE. Vous pouvez aussi basculer directement vers tout fichier ouvert dans l'diteur,
indpendamment de son dernier ordre d'accs. Ces fonctionnalits peuvent contribuer accrotre votre
productivit lorsque vous travaillez dans l'IDE.
Bien que des IDE pour plusieurs langages existent. Bien souvent (surtout dans les produits
commerciaux) un IDE est ddi un seul langage de programmation. On peut galement trouver dans
un IDE un systme de gestion de versions et diffrents outils pour faciliter la cration de l'interface
graphique.
Il existe plusieurs environnements de dveloppement. Vous aurez peut-tre un peu de mal choisir celui
qui vous plat au dbut. Une chose est sre en tout cas: vous pouvez faire n'importe quel type de
programme, quel que soit l'IDE que vous choisissez.
Il m'a sembl intressant de vous montrer quelques IDE parmi les plus connus. Tous sont disponibles
gratuitement. Personnellement, je navigue un peu entre tous ceux-l et j'utilise l'IDE qui me plat selon
l'humeur du jour.
Un des IDE les plus connus : RadAsm est une petite merveille, convivial, riche en fonctionnalit,
rapide, et d'une taille ridicule par rapport d'autre EDI, il vous permettra de dvelopper de
vraies applications avec tout le confort que l'on peut esprer d'une application de qualit. Cest
celui l que nous utiliserons tout au long de ce guide.
Il existe WinAsm Studio qui ressemble trs fortement RadAsm avec peut-tre un peu moins
de fonctionnalits mais dont l'interface et beaucoup plus agrable et facile utiliser. De plus, il
se charge beaucoup plus vite et explique clairement comment fabriquer ses propres plugins.
AsmEditor est un EDI permettant la cration et la compilation de projets en langage assembleur.
Il inclut un contrle des compilateurs permettant de grer autant de chanes de compilations que
ncessaire (pour diffrentes plateformes par exemple).
Easy Code sous une apparence semblable celle de Visual Basic, me parait aussi quil ferra
parfaitement laffaire.
On va encore devoir faire un choix sur lassembleur quon devra implmenter dans RadAsm, en effet il
existe plus d'une douzaine de diffrents assembleurs disponibles pour le processeur x86 fonctionnant sur
PC. Ils diffrent en terme de fonctionnalits et de syntaxe. Certains sont adapts pour les dbutants,
certains sont destins uniquement aux programmeurs confirms. Certains sont trs bien documents,
d'autres ont peu ou pas de documentation. Certains sont enrichis par beaucoup dexemples de
programmation, certains ont trs peu d'exemples de code. Certains assembleurs sont toffs de tutoriels
et des livres disponibles qui utilisent leur syntaxe, d'autres en manquent. Certains sont trs basic,
d'autres sont trs complexes. Quel est le meilleur assembleur, alors?
Comme bon nombre de questions poses dans la vie, il n'y a pas de rponse simple la question
Quel est le meilleur assembleur ? La raison en est que diffrentes personnes ont des critres
diffrents pour valuer ce qui est le meilleur . A l'absence d'une chelle universelle pour juger les
diffrents assembleurs, il n'y a aucun moyen de choisir un seul assembleur et le dsigner le meilleur.
Historiquement, MASM, lassembleur de Microsoft, est une volution du premier assembleur 8088
dvelopp pour IBM. MASM a t pendant longtemps la seule solution pour le dveloppeur en
assembleur. La dernire version sappelle maintenant ML. Pendant longtemps, la seule vraie alternative a
t le Turbo Assembleur (TASM) de Borland, qui fut plbiscit ds sa mise disposition par une grande
majorit dutilisateurs pour sa rapidit et sa souplesse. Avec le passage Windows 9x, les outils de
dveloppement de type macro-assembleurs nont plus t une priorit pour les diteurs. Ces solutions
taient performantes mais payantes. Maintenant, et depuis quelque anne, grce lmancipation des
logiciels du monde libre, de nouveaux assembleurs tout aussi performants sont apparus. Le plus connu
de ces assembleurs libres est NASM (The Netwide Assembler). Mais il existe galement dautres
solutions comme FASM (Flat Assembler), GoAsm, RosAsm, HLA (High level assembly), Gas (GNU
Assembler) Autant le dire tout de suite : il n'y a pas de raison absolue pour prfrer MASM un autre
assembleur. Tous les exemples qui sont dvelopps dans ce guide seront spcifiques MASM en
particulier. MASM reste encore aujourd'hui un des assembleurs phare de la communaut des
programmeurs en assembleur pour la plateforme Win32, mais d'autres assembleurs rassemblent chacun
une communaut importante.
La dernire des exigences qui s'ajoutera celles ci-dessus sera remplie, soit en possdent l'ancien
fichier d'aide Win32.hlp ou par la mise jour MSDN (Microsoft Developer Network) des bibliothques
disponibles en ligne dans le cadre de la Plate-forme SDK (Software Development Kit) disponible en
tlchargement libre chez Microsoft.
Toutes les Informations que vous pourrez tirer profit dans la suite de ce guide vont se faire en deux
catgories principales:
MASM32 syntaxe - Comment crire correctement les instructions en ASM sous MASM.
L'architecture Windows et ses APIs.
Installation de Masm
Une fois que vous avez rcupr Masm, dcompresser o vous voulez, linstallation de Masm ne pose
pas de problme mais, pour que chacun soit bien rassur, nous en montrons ici les tapes. Pour
dmarrer, lancez install.exe, cette page devrait s'afficher :
Rien de particulier signaler. Cliquez sur OK autant de fois que ncessaire en laissant les options
par dfaut, peu de temps aprs, vous devriez avoir une fentre comme celle-ci :
Pour sassurer que linstallation sest passe sans encombre, vous devriez apparaitre le dossier masm32
dans C:\.
Configuration de RadAsm
Dabord, n'hsitez pas consulter le site de l'auteur http://www.radasm.com/ afin d'tre sr de bien
rcuprer tous les fichiers archive constituant l'application. Ceux qui nous intressent sont les suivants :
Vous devez maintenant avoir une archive contenant les trois fichiers. Dcompressez-les o vous voulez,
puis vous devriez avoir ceci :
Dans le fichier RadLNG, copier le fichier Language dans le fichier RadAsm . De mme mettez le
contenu du fichier Assembly dans le fichier RadAsm .
Oui, par dfaut RadAsm est en anglais. Vous pouvez le modifier en allant en haut dans le menu, Option
/ Language, choisissez Franais , et enfin Appliquer , OK.
Rendez-vous encore sur Option / Langage de programmation, supprimez HTML cala ne servira
absolument rien. Cliquez cependant sur le bouton "..." en bas droite. Une nouvelle fentre s'ouvre :
choisissez masm.
Maintenant que notre environnement est tout fait prt tre utilis. On peut passer l'utilisation. Au
dpart, rien ne saffiche. Il va falloir demander RadAsm de crer un nouveau projet. Un projet cest
lensemble de tous les fichiers source du programme. En effet, quand on programme, on spare souvent
notre code dans plusieurs fichiers diffrents. Ces fichiers seront ensuite combins par lassembleur qui
en fera un excutable. Justement, la gestion de projet fait partie des principaux caractristiques dun
IDE.
Retenez bien la marche suivre, car vous devrez faire cela la plupart du temps. Pour crer un nouveau
projet cest simple : allez dans le menu Fichier / Nouveau Projet. Vous devriez voir quelque chose qui
ressemble a :
Maintenant que ces quelques mots ont t dits, je vais maintenant vous faire faire un tour rapide de
l'interface que vous propose RadAsm, en gros, des lments dont nous allons nous servir dans ce
guide.
Avant de commencer, regardez bien les raccourcis clavier prsents dans les menus... Ils sont trs utiles
et peuvent vous faire gagner beaucoup de temps. On nest pas obligs bien sr, mais croyez-moi,
quand on y a got, on ne peut plus s'en passer
Ces 4 icnes sont sans aucun doute les plus utilises, et pour cause : ce sont elles qui permettent
dappeler lassembleur pour crer un excutable de votre projet. Dans lordre, de gauche droite, ces
icnes signifient :
Assembler : tous les fichiers source de votre projet sont envoys au compilateur qui va se charger de
crer un excutable. Sil y a des erreurs, lexcutable ne sera pas cr et on vous indiquera les erreurs
en bas RadAsm.
Construire : quand vous faites Assembler, RadAsm nassemble en fait que les fichiers que vous avez
modifis et pas les autres. Parfois, je dis bien parfois, vous aurez besoin de demander RadAsm de
vous recompiler tous les fichiers. On verra plus tard quand on a besoin de ce bouton, et vous verrez
plus en dtail le fonctionnement de la compilation dans un chapitre futur. Pour linstant, on se contente
de savoir le minimum ncessaire pour ne pas tout mlanger.
Excuter : cette icne lance juste le dernier excutable que vous avez assembl. Cela vous permettra
donc de tester votre programme et voir ainsi ce quil donne.
Construire & Excuter : videment, ce bouton est la combinaison des deux boutons prcdents. Cest
dailleurs ce bouton que vous utiliserez le plus souvent. Notez que sil y a des erreurs pendant
lassemblage (pendant la gnration de lexcutable), le programme ne sera pas excut.
Dans l'encadr bleu, je pense que vous avez devin... C'est ici que nous allons crire nos codes
sources.
Dans l'encadr rouge, c'est l que vous verrez apparatre le contenu de vos programmes ainsi que les
erreurs ventuelles.
Et enfin pour finir, dans l'encadr vert, ds lors que nous aurons appris coder nos propres fonctions,
c'est ici que la liste des mthodes et des variables sera affich
Notez enfin que vous pouvez allger la barre doutils en choisissant les groupes de boutons qui y
apparaissent. Pour cela, cliquez avec le bouton droit de la souris dans la barre doutils (mais pas sur un
bouton) :
Ce description ne prtend pas tre complte, il s'agissait tout d'abord d'effectuer un tour d'horizon de cet
EDI qui je l'espre vous aura permis de mieux le connatre et d'en apprcier la puissance. En outre,
certaines fonctionnalits ou options m'ont srement chapp et vous ne manquerez pas de les dcouvrir
par vous-mme.
Nous en savons prsent suffisamment pour commencer mettre pour de bon les mains dans le
cambouis. Ouvrons donc un nouveau projet appel Skeleton. Ce programme nous fournira une base de
dpart pour dvelopper n'importe quel programme. Si vous ne comprenez pas quelques-uns des codes,
ne paniquez pas. J'expliquerai chacun d'entre eux plus tard.
Nous analyserons maintenant ligne par la ligne. La plupart de ce code reprsente des directives.
Certains langages, dont lassembleur, comportent un grand nombre de directives ou instructions ddies
la gestion et au contrle des processus de compilation ou dassemblage. Ces directives dont le rle
est de contrler et de mettre, place les bons paramtres en vue des diffrentes phases de lassemblage,
sont rassembls en plusieurs groupes selon leur fonction. Il faut noter que la prise en charge et la
La diffrence entre majuscules et minuscules dans les noms des directives ne sont pas prises en
considration. Par exemple, lassembleur traitera dans la mme faon .include et .include.
.386
Ces directives permettent de choisir le processeur cible. Elles dterminent ainsi comment doit tre
analys le code qui le suivra. Lusage le plus frquent de ces directives est den crire une seule au
dbut du programme source, en privilgiant le dernier processeur de la srie. Cette directive ninfluence
pas le codage des mnmoniques, mais restreint lusage de certaines instructions. Par exemple, si la
directive .386 est utilis, vous pourrez employer les instructions spcifiques du 80386. Par contre,
soumettant lassemblage le mme code source, mais la directive .8086, il y aurait une erreur
chacune des instructions spcifiques du 80386 ! Mais, si dans le mme code source vous mettez des
instructions spcifiques au 80586, il y aura galement erreur car ces instructions ne sont supportes ni
par le 8086, ni par le 80386 ! Ces directives permettent dassurer un contrle lors dassemblage
descendant, cest dire de permettre le filtrage par rejet des instructions inexistantes sur danciens
processeurs. Il y a en ralit deux formes presque identiques pour chaque modle de directive.
.386/.386p .486/.486p Ces versions p sont ncessaires seulement quand votre programme
emploie des instructions privilgies. Les instructions privilgies sont des instructions rserves par le
systme du CPU / fonctionnement en mode protg.
.model est une directive d'assembleur a pour but de dterminer plusieurs caractristiques importante
dans un programme : le type de mmoire, la convention dappel des fonctions. La syntaxe de la
directive .model est la suivante :
MemoryModel spcifie le type de mmoire de votre programme. Sous Win32, il y a seulement un type,
le modle FLAT plat , vous vous souvenez ? On utilise un seul segment de 4 GB, bref, c'est une
ModelOptions signifie : appel standard, c'est--dire la faon dont sont transmis les paramtres la
fonction, autrement l'ordre de passage des paramtres de la pile vers un Call, de gauche droite
ou de droit gauche et aussi a quilibrera l'encadrement de la pile aprs l'appel de la fonction. La
plate-forme Win32 emploie exclusivement STDCALL, les paramtres sont transmis de la droite vers la
gauche car les APIs utilisent ce format.
.data
Cette section contient les donnes initialises de votre programme. Les variables que l'on donne une
valeur ds le dpart.
.data?
Cette section contient les donnes non initialises de votre programme. Parfois vous voulez juste prvoir
un espace mmoire pour contenir de futurs donnes, mais ne voulez pas l'initialiser (lui donner une
valeur initiale). C'est le but de cette section. L'avantage des donnes non initialises est que l'espace
est allou quand le programme est charg dans la mmoire mais la taille de fichier sur le disque n'est
pas augmente.
.const
Il arrive parfois que l'on ait besoin d'utiliser une variable dont on voudrait qu'elle garde la mme valeur
pendant toute la dure du programme. C'est--dire qu'une fois dclare, vous voudriez que votre
variable conserve sa valeur et que personne n'ait le droit de changer ce qu'elle contient. Ces variables
particulires sont appeles constantes, justement parce que leur valeur reste constante.
Vous n'tes pas forcment oblig d'employer ces trois sections dans votre programme. Dclarez
seulement la (ou les) section (s) que vous voulez utiliser. Par contre, il n'y a seulement qu'une section
pour le code : .code, cette section reprsente les instructions proprement-dites du programme.
<label>
end <label>
Contrairement DOS qui est un environnement mono-tche, mono-utilisateur par excellence, Windows
depuis la version 95 est un vrai un systme d'exploitation graphique et multitche pouvant ainsi grer
plusieurs "tches" simultanment. La programmation de logiciels sur cet OS ncessite donc quelques
notions de l'API WIN32.
Les API ne sont en fait que des fonctions semblables celles que vous pouvez crer dans votre
environnement de dveloppement : en rgle gnrale, on leur fournit un certain nombre de paramtres,
et elles renvoient quelque chose, ou ralisent une action prcise. Ces fonctions sont contenues dans des
fichiers dll, tels "user32.dll", "kernel32.dll", ou bien d'autres encore. Les fonctions les plus couramment
utilises sont celles qui constituent Microsoft Windows lui-mme. Ces procdures sont toutefois crites
en langage C, et doivent donc tre dclares avant de pouvoir les utilises avec d'autres langages.
Les API Windows sont plutt faciles utiliser, une fois que l'on connat leur dclaration et leurs
paramtres. Leurs difficults sont autres : les problmes se posent gnralement lorsqu'on cherche l'API
qui nous rendrait service, puisqu'on se trouve alors confront des milliers de fonctions aux noms pas
toujours trs explicites. Lorsquenfin on a trouv celle qui convient, on dcouvre qu'on est incapable de
l'utiliser, car on ne connat ni sa dclaration, ni ses paramtres, ni son utilisation ! Pour rsoudre ce
problme, il n'y a pas cinquante solutions : la premire est de chercher des exemples utilisant cette API,
la deuxime est dutiliser la MSDN Online sur le site de Microsoft (qui contient entre autres cette
Les programmes Win se lient dynamiquement avec ces DLLs, c'est--dire : Les codes des fonctions API
ne sont pas inclus dans le programme Win excutable. Dans votre programme, pendant son excution,
pour accder l'API dsire, vous devez dclarer cette information dans le fichier excutable.
L'information est dans une bibliothque d'importation. Vous devez lier vos programmes avec les
bibliothques d'importation correctes sinon ils ne seront pas capables de retrouver la fonction de l'API
souhaite.
Quand un programme Win est charg dans la mmoire, Windows lit l'information stocke dans le
programme. Cette information inclut les noms des fonctions et les DLLs o rsident ces fonctions. Ex : la
DLL "User32.dll" contient la fonction MessageBox (ainsi qu'une multitude d'autres fonctions).
L'information que cherchera Windows dans votre excutable ce sera quelque chose comme Call
USER32 ! MessageBox . Ds que Windows tombera sur un tel renseignement dans votre programme,
il chargera la DLL et excutera la fonction.
Il y a deux catgories de fonctions API : les uns pour ANSI et les autres pour Unicode. Les noms des
fonctions API pour ANSI sont suivis du suffixe "A", ex : MessageBoxA. Ceux pour Unicode ont le suffixe
"W". Windows 95 traite naturellement ANSI, et Windows NT Unicode.
D'habitude on se sert de la convention ANSI, qui pour l'ensemble des caractres proposs par votre
ordinateur sont termins par le caractre NULL. ANSI reprsente chaque caractre sur 1 octet. Il est
suffisant pour les langues europennes, mais il ne peut pas manipuler la plupart des langues orientales
qui ont plusieurs milliers de caractres uniques. C'est pourquoi UNICODE entre en jeu. Un caractre
UNICODE a une taille de 2 octets, ce qui lui permet d'avoir une srie de code de 65536 caractres
uniques.
Mais la plupart du temps, vous emploierez un fichier INCLUDE (*.inc) qui peut dterminer et choisir les
fonctions API appropries votre plate-forme suivant ce que doit faire votre programme. Rfrez-vous
juste aux noms de fonction API sans le suffixe.
Traditionnellement, les tutoriaux pour la programmation, dont le but est de faire la dmonstration rapide
d'un langage de programmation commence, avec une application qui affiche le message "Hello World"
dans une console. La fentres d'interface graphique quivalente cela est la fonction MessageBox. Dans
RadAsm pour, ouvrez un nouveau projet nomm MessageBox.
.option est une directive dassemblage qui indique que la diffrence entre majuscule et minuscule est
importante, ainsi par exemple, MessageBox et messagebox seront compltement diffrent.
Notez la nouvelle directive, include. Cette directive est suivie par le nom du fichier que vous voulez
insrer sa place. Dans cet exemple, quand Masm traite la ligne include windows.inc, Il ouvrira
windows.inc qui se trouve dans le rpertoire C:\MASM32\include, comme tout les autres fichiers .inc
dailleurs, et fera en sorte que son contenu (celui de windows.inc) soit coll dans votre programme
win32. Il ne contient pas de prototype de fonction. windows.inc n'est en aucun cas complet (c'est
comprhensif car on peut toujours y rajouter de nouvelles choses). windows.inc est un fichier matre,
MB_OK
NULL
Celles-ci peuvent tre utilises par leur nom pour amliorer la lisibilit de votre code source.
T'es bien gentil, mais c'est quoi, un prototype de fonction ? Celle-ci appelle immdiatement une autre,
cest quoi une fonction ?
En programmation, on dsigne par une fonction un morceau de code qui sert faire quelque chose de
prcis. Une fonction excute des actions et renvoie un rsultat. On dit qu'une fonction possde une
entre et une sortie. Schmatiquement, a donne quelque chose comme a :
Je vous l'ai dit ds le tout dbut de ce chapitre du cours, et je ne vous ai pas menti : les APIs Windows
sont aussi des fonctions. Ce sont en quelque sorte des fonctions toutes prtes qu'on utilise trs souvent.
Ces fonctions ont t crites par des programmeurs avant vous, elles vous vitent d'avoir rinventer la
roue chaque nouveau programme.
1. L'entre: on fait "rentrer" des informations dans la fonction (en lui donnant des informations
avec lesquelles travailler), on appelle a, ses arguments ou ses paramtres.
2. Les calculs : grce aux informations qu'elle a reues en entre, la fonction travaille.
3. La sortie : une fois qu'elle a fini ses calculs, la fonction renvoie un rsultat. C'est ce qu'on
appelle la sortie, ou encore le retour.
Le prototype d'une fonction correspond simplement son en-tte. On place donc le prototype en dbut
de programme (Si vous avez dj programm en C++, vous connaissez sans doute les prototypes de
fonctions, qui sont utiliss dans les dclarations des classes). Cette description permet lassembleur de
vrifier la validit de la fonction chaque fois qu'il la rencontre dans le programme, en lui
indiquant :
En rsum, la directive PROTO cre un prototype de procdure. Cest une sorte de pr-dclaration qui
mentionne le nom de la procdure et la liste de ses paramtres. Grce un prototype, vous pouvez
insrer des appels une procdure avant le corps de dfinition de cette procdure (Si vous avez dj
programm en C++, vous connaissez sans doute les prototypes de fonctions, qui sont utiliss dans les
dclarations de classes.). Le mot l proto est prcd du nom de la fonction puis suivi de la liste des
paramtres, spars par des virgules. Dans l'exemple, ci-dessous, on dfinit ExitProcess comme une
fonction qui prend seulement un seul paramtre de type DWORD.
includelib ne fonctionne pas comme include. C'est seulement une faon de dire Masm quelles
bibliothques d'importation sont employes par vos programmes. Quand Masm voit une directive
includelib, il met une commande de linker dans le fichier d'objet pour que le linker sache avec quelles
bibliothques d'importation votre programme a besoin de se lier. Vous n'tes pas forc d'employer
includelib quoique. Vous pouvez spcifier les noms des bibliothques d'importation dans la ligne de
commande du linker, mais croyez-moi, c'est ennuyeux et la ligne de commande ne peut contenir que
128 caractres.
Le programme que nous avons entre les mains fait appel deux apis MessageBox et ExitProcess
fessons partie respectivement aux librairies user32.lib et kernel32.lib, donc nous avons besoin d'inclure
le prototype de fonction de user32.dll et kernel32.dll. Ces fichiers sont user32.inc et kernel32.inc. Si
vous l'ouvrez avec un diteur de texte, vous verrez que c'est plein de prototypes de fonction. Si vous
n'incluez pas kernel32.inc par exemple, vous pouvez toujours appeler ExitProcess, mais seulement avec
la syntaxe d'appel simple (Push 0 puis Call ExitProcess). Vous ne serez pas capables d'invoker la
fonction (ExitProcess).
Permet non seulement de diminuer le nombre de lignes lors des appels de proc (push, push), mais
aussi de vrifier automatiquement la syntaxe de l'appel. Le nombre de paramtres passs la fonction
doit correspondre au nombre d'arguments attendus par la fonction. La taille des paramtres (dword,
byte...) doit correspondre la taille des arguments attendus par le proc. Si une des deux conditions
n'est pas remplie, il se produit une erreur lassemblage.
Aucune de ces erreurs ne se produit lorsqu'on utilise les push suivis d'un call. La sanction de la non
utilisation de invoke peut fort bien tre des heures et des heures de dbogage passs chercher les
arguments manquant ou mal dimensionns (bonjour la galre s'il existe plus d'une centaine d'appels
contrler, ce qui n'a rien d'norme).
Sans pousser un dword sur la pile (Push 0, avant d'appeler la fonction ExitProcess), l'assembler ne sera
pas capable de comprendre cette erreur votre place. Vous vous en apercevrez plus tard quand votre
programme plantera. Mais si vous employez :
Le linker vous informera que vous avez oubli de pousser un DWORD sur la pile vitant ainsi l'erreur.
Je vous recommande donc d'employer invoke au lieu d'un simple 'Call'.
Si vous tes intress par la programmation oriente objet, pensez toutes les fonctions dune mme
classe. Cest peu prs lquivalent dune collection de procdures et de donnes dfinis dans le mme
module de code source assembleur. Rappelons que le langage assembleur t cre bien avant la
programmation oriente objet. Il ne peut donc pas proposer une structure formelle du niveau du celle du
C++ ou de Java. Cest vous dimposer un peu de rigueur dans la structure de rdaction de vos
programmes.
Pour fonctionner, un programme gnralement besoin de pouvoir utiliser des donnes. Pour cela, il
doit pouvoir stocker les valeurs, et pouvoir y accder par la suite. Le programme pourra ensuite les
contrler, et pourquoi pas, les modifier.
Pour cela, il existe un moyen simple qui est l'utilisation des variables.
Il y a toutes sortes de choses que lon peut stocker au sein de variables : les informations concernant
un employ, la longueur dun morceau de musique, le nombre de bicyclettes commandes aujourdhui,
etc.
La variable est un concept important en programmation informatique. Intuitivement, il s'agit d'un nom qui
se rfre une chose. Informatiquement, c'est une rfrence une adresse mmoire. Il s'agit donc
Par exemple, le nom NombreDeChansons vous permet de savoir tout de suite que cette variable
reprsente le nombre de chansons couter dans le juke-box. En revanche, C3PO nest pas un nom
gnial pour une variable. Ce peut tre un numro de srie, un nom de robot ou qui sait quoi.
Masm dfinit plusieurs types de donnes intrinsques. Chaque type permet dexploiter un ensemble de
valeurs et de les affecter des variables et des expressions du mme type. Par exemple, une variable
de type intrinsque DWORD permet de stocker nimporte quelle valeur entire sur 32 bits. Il existe des
types plus contraignants, et notamment REAL4, qui ne peuvent accepter quune constante numrique
relle. Limage si dessous prsente tous les types de donnes pour les valeurs entires, except les
trois dernires. Pour celle-ci, la notation IEEE correspond au standard des formats de nombres rels (
virgule flottante) tels que publies par lassociation scientifique IEEE Computer society.
Les directives BYTE, WORD, DWORD, FWORD, QWORD, TBYTE servent dfinir des emplacements
de donnes, vous pouvez encore utiliser les directives DB (Define BYTE), DW (Define WORD), DD
(Define DWORD), DF (Define FWORD), DQ (Define QWORD), et DT (Define TBYTE) pour dclarer
vos variables.
En informatique, les rationnels sont souvent appels des flottants . Ce terme vient de en virgule
flottante et trouve sa racine dans la notation traditionnelle des rationnels. La directive REAL4 permet
de rserver un espace pour une variable relle sur 4 octets simple prcision. La directive REAL8
dfinit un rel double prcision sur 8 octets, et la directive REAL10 dfinie un rel prcision tendue
sur 10 octets. Chaque directive suppose la mention dun initialiseur constant rel dont la largeur
correspondant :
Pour dclarer une donne de type chane (un nom programmatiquement correct pour dsigner du texte),
vous devez dlimiter les caractres qui la constituent au moyen dapostrophes ou des guillemets. Les
chanes les plus rpandues en programmation se terminent par un octet dont la valeur est 0. Ces
chanes sont appeles chanes zro terminal, ou chanes AZT. Elles sont trs utilises dans les
langages C, C++ et Java, et par les fonctions de Windows.
A chaque caractre correspond un octet de stockage. Les chanes constituent une exception la rgle
qui veut que les valeurs de type octet soient spares les unes des autres par des virgules. Si cette
exception nexistait pas, la variable dans le code source aurait d tre dfinie comme ceci :
Vous pouvez distribuer une chaine de caractres en plusieurs lignes sans tre forc de rpter le label
au dbut de chaque ligne, comme le montre cet exemple :
Hourra !
Le caractre dextension de la ligne Masm est la barre oblique inverse \ . Il permet de tronquer
visuellement une ligne qui reste au niveau logique. Le symbole \ ne peut donc tre plac qu la fin
dune ligne. Au niveau du programme assembleur, les deux instructions suivantes sont absolument
identiques :
La porte d'une variable dsigne la zone du code dans laquelle la variable sera connue et donc
utilisable. On distingue deux portes diffrentes :
Si vous dclarez une variable ou une constante en dehors d'une dfinition de fonction (dans la section
.data, data?, ou .const), il s'agit d'une variable globales statiques. Le terme statique signifie que la
dure de vie de la variable est gale celle de lexcution du programme. Le terme global signifie
que la valeur de la variable est accessible et modifiable dans tout le programme. En revanche, si vous
dclarez une variable au sein d'une dfinition de fonction, il s'agit d'une variable locale. Elle est cre et
dtruite chaque fois que la fonction est excute ; il est impossible d'y accder en dehors de la fonction.
Sa dure de vie est donc bien infrieure la dure dexcution du programme. Attention : les variables
Voyons comment exploiter les variables locales en assembleur. Rappelons dabord les avantages du
local par rapport au global :
Laccs limit une variable local simplifie le dbogage, car les origines ventuelles dun
disfonctionnement sont moins nombreuses.
Une variable local utilise la mmoire de manire efficace, en loccurrence uniquement pendant
lexcution de la routine dans laquelle elle est dclare. Cela permet de rutiliser lespace pour
de nouvelles variables locales.
Une variable locale peut porter le mme nom qu'une variable globale, mais elle n'en reste pas
moins distincte. En consquence, si vous modifiez la valeur d'une variable, cela n'a aucun effet
sur l'autre. Au sein de la fonction dans laquelle la variable locale est dclare, seule la version
locale est significative. Ce concept porte le nom de visibilit.
Les variables locales sont cres sur la pile dexcution. Vous ne pouvez pas leur donner de valeur
initiale lors de lassemblage, mais vous tes libres dcrire une valeur initiale en dbut dexcution.
La directive LOCAL
La directive LOCAL dclare une ou plusieurs variables locales dans une procdure. Elle doit tre
mentionne sur la ligne qui suit immdiatement celle qui constitue louverture du bloc de dfinition dune
procdure. Elle doit tre introduite par la directive PROC. Voici sa syntaxe formelle :
LOCAL ListeVar
ListeVar correspond une liste de noms de variables spars par des virgules et pouvant stendre sur
plusieurs lignes. Chaque dfinition de variable respecte la syntaxe suivante :
Label : type
Label doit tre un identificateur autoris et type doit tre un des types standard WORD, DWORD, etc. ou
un type dfini par le programmeur. (Nous aborderons les structures de donnes et les types dfinis par
le programmeur directement aprs ce paragraphe).
La directive LOCAL alloue de la mmoire sur la pile pour des variables locales employes par la
fonction. La totalit des directives LOCALES doivent tre places juste au-dessous de la directive PROC.
Les variables locales ne peuvent pas tre employes l'extrieur de la fonction, elles sont crs et
seront automatiquement dtruites quand la fonction retourne l'appel. Un autre inconvnient est que
Exemple :
La procdure TriABulle dclare la variable local temp de taille double-mot (dword) et la variable
SwapFlag de taille BYTE :
On a appris que pour dclarer un prototype de procdure on utilise la directive PROTO, maintenant on
va voir comment dclarer la procdure elle-mme en utilisant la directive PROC. Au niveau lmentaire,
une procdure est un bloc contigu dinstructions portant un nom et se terminant par une instruction de
retour dexcution. Vous dclarer une procdure avec le couple de directives PROC et ENDP. La
directive PROC est essentielle : Elle peut comporter une liste de paramtres, comme le montre sa
syntaxe formelle simplifie :
Vous devez indiquer comme dernire instruction celle de retour RET. Elle oblige le processeur
poursuivre lexcution linstruction qui suit celle qui a constitu lappel au sous-programme. Les
paramtres peuvent tre placs sur une seule ligne :
Nomparam: type
Nomparam est un nom choisi par le programmeur. Le paramtre est accessible uniquement dans la
procdure courante (porte locale). Vous pouvez donc utiliser le mme nom de paramtre dans
plusieurs procdures, condition que a soit ni variable globale, ni un label de code. Pour le type,
choisissez lun des mots rservs suivants : BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD,
Voyons quelques dfinitions de procdure avec diffrents types de paramtres. Ne vous souciez pas du
corps de la fonction pour linstant.
Exemple 1
Exemple 2
Exemple 3
Exemple 4
La procdure suivante attend le pointeur sur un octet pTampon. Elle dclare localement la variable
fileHandle :
La directive ALIGN permet daligner une variable sur une frontire doctet, de mot, de double-mot ou de
paragraphe. Voici sa syntaxe :
ALIGN frontiere
frontiere peut tre gale 1, 2 ou 4. Si elle vaut 1, la prochaine variable est aligne sur une frontire
doctet (valeur par dfaut). Si la valeur est 2, la variable est aligne sur la prochaine adresse paire. Si
la frontire vaut 4, la prochaine variable est stocke la prochaine adresse multiple de 4 en partant du
dbut du segment. Pour assurer ce recadrage, lassembleur insre des octets vides avant la variable.
Vous pouvez vous demander quoi sert cet alignement. Cest parce que le processeur peut lire et crire
plus rapidement des objets stocks des adresses paires.
Prenons lexemple suivant. Nous savons que bVal est automatiquement stock une adresse offset
paire. Si nous ajoutons ALIGN 2 avant la directive wVal, cette variable sera place un dcalage pair
elle aussi. Nous allons par exemple choisir dimplanter la premire variable ladresse 00404000 :
Si dVal avait t place loffset 00404005, la directive ALIGN 4 laurait repousse jusqu loffset
00404008.
La directive symbolis par le signe = permet dassocier un nom de symbole une expression numrique
nom = expression
les occurrences de nom sont remplaces par expression dans une premire tape de prtraitement. Par
Dans lexemple prcdant, nous aurions pu viter de dfinir le symbole COMPTEUR, et ajouter
directement la valeur littrale 100 dans linstruction MOV. Lexprience montre que lutilisation de
symboles rend les programmes plus simples lire et maintenir. Imaginez que COMPTEUR soit utilis
dix fois dans le mme programme. Si vous avez besoin plus tard de modifier la valeur de COMPTEUR
Lorsque vous rassemblez le programme, tous les occurrences du symbole COMPTEUR sont
automatiquement remplaces par la valeur 200. Si ce symbole navait pas t dfini, il aurait fallu
modifier dix fois la valeur, au risque den oublier une. Cela provoquerait certainement un bogue.
Loprateur PTR
Loprateur PTR permet de passer outre la taille dclare lorigine pour un oprande. Vous nen aurez
besoin que lorsque vous devrez accder une variable avec un attribut de taille diffrent de celui utilis
lors de la dclaration de cette variable.
Par exemple, supposons que nous ayons besoin de copier les 16 bits de poids faible dune variable de
taille double-mot appele monDouble dans le registre AX. Le programme assembleur refuse la copie
suivante, car les tailles des deux oprandes ne correspondent pas :
Si nous insrons la mention WORD PTR, nous pouvons copier le mot de poids faible (5678h) dans
AX :
Le processeur peut accder la mmoire selon nimporte laquelle des trois approches, quelle que soit la
manire dont la variable a t dclare lorigine. Par exemple, si monDouble est situ loffset 0000,
la valeur sur16 bits stocke cette adresse est 5678h. Pour lire le mot suivant, 1234h, il faut utiliser la
mention monDouble+2, comme ceci :
Nous pouvons utiliser loprateur BYTE PTR pour rcuprer un seul octet de monDouble vers BL, par
exemple :
Vous avez remarqu que PTR doit toujours tre combin avec lun des noms de types de donnes
standard : BYTE, SBYTE, WORD, SWORD, DOWRD, SDWORD, FWORD, QWORD ou TBYTE.
Supposons que nous ayons besoin de copier deux valeurs de petite largeur vers un oprande de grande
taille. Dans notre exemple, le premier mot est copi dans la partie basse dEAX, et le second dans la
partie haute. Cela nest pas possible que grce loprateur DWORD PTR :
Loprateur TYPE permet de connatre la taille, en octets, dun lment isol dune variable complexe ou
dune variable simple. Par exemple, TYPE appliqu un octet renvoie 1 ; appliqu un mot, il renvoie
2 ; appliqu un double-mot, il renvoie 4 ; et appliqu un quadruple-mot, il renvoie 8. Voici des
exemples :
Les tableaux
Les tableaux sont certainement les variables structures les plus populaires. Ils sont disponibles dans
tous les langages de programmation et servent rsoudre une multitude de problmes. Imaginons que
dans un programme, nous ayons besoin simultanment de 12 valeurs (par exemple, des notes pour
calculer une moyenne). Evidemment, la seule solution dont nous disposons lheure actuelle consiste
dclarer douze variables, appeles par exemple Notea, Noteb, Notec, etc. Bien sr, on peut opter pour
une notation un peu simplifie, par exemple N1, N2, N3, etc. Mais cela ne change pas
fondamentalement notre problme, car arriv au calcul, et aprs une succession de douze instructions
Lire en algorithme distinctes. Cest tout de mme bigrement laborieux. Et pour un peu que nous
soyons dans un programme de gestion avec quelques centaines ou quelques milliers de valeurs traiter,
alors l cest le suicide direct. Cest pourquoi la programmation nous permet de rassembler toutes ces
variables en une seule, au sein de laquelle chaque valeur sera dsigne par un numro. En bon
franais, cela donnerait donc quelque chose du genre la note numro 1 , la note numro 2 , la
note numro 8 . Cest largement plus pratique, vous vous en doutez.
Un ensemble de valeurs portant le mme nom de variable et repres par un nombre, sappelle un
tableau, ou encore une variable indice. Le nombre qui, au sein dun tableau, sert reprer chaque
valeur sappelle surprise lindice. Chaque fois que lon doit dsigner un lment du tableau, on fait
figurer le nom du tableau, suivi de lindice de llment, entre parenthses. Comme dit ci-dessus, un
tableau est une collection squentielle de variables, toutes de la mme taille et de mme type, appeles
des lments. Vous pouvez avoir accs tous les lments dans un tableau autant qu'au premier
Donne une valeur de 1 Tab [0], une valeur de 3 Tab [1], et ainsi de suite. Cependant, dans des
tableaux avec des lments plus grands que 1 octet, les nombres d'indice (sauf le zro) ne
correspondent pas la position d'un lment. Vous devez multiplier la position d'un lment de sa taille
pour dterminer l'indice de l'lment. Ainsi, pour le tableau
Tab [4] reprsente le troisime lment (5), qui est de 4 octets depuis le dbut du tableau. De mme
l'expression Tab [6] reprsente le quatrime lment (7) et Tab [10] reprsente le sixime lment
(13).
Si vous devez dclarer un grand tableau, vous pouvez utiliser l'oprateur DUP, par exemple :
Plus encore :
A noter qune chaine de caractre est aussi un tableau de caractres qui prend 1 octet de mmoire pour
chaque caractre.
Loprateur LENGTHOF
Le tableau suivant prsente les valeurs qui sont renvoyes par chacune des expressions LENGHTOF.
Expression Valeur
LENGTHOF octet1 3
LENGTHOF tab1 30 + 2
LENGTHOF tab2 5*3
LENGTHOF tab3 4
LENGTHOF digitSt 9
Remarquez que lorsque nous utilisons des oprateurs de duplication DUP imbriqus dans une dfinition
de tableau, LENGTHF envoie le produit des deux compteurs dlments.
LENGHTOF est "myope" : lorsque vous dclarez un tableau sur plusieurs lignes sources, LENGHTOF
ne voit que les donnes de la premire ligne. Dans lexemple suivant, la mention LENGHTOF monTablo
renvoie la valeur 5 :
Pour pallier cette myopie, vous pouvez terminer la premire ligne par une virgule et poursuivre la liste
des valeurs sur la ligne suivante. Dans lexemple suivant, LENTGHOF monTablo renvoie la valeur 10 :
Les structures
Jusqu prsent, vous avez dcouvert les types de donnes simples et vous avez vu que lon peut
stocker une information dans une variable. Mais supposons que vous dsirez stocker quelque chose de
plus complexe quun simple type de donne : par exemple, le nom de lutilisateur, son adresse et son
numro de tlphone.
Le groupement dun ensemble de variables apparentes en une seule entit est appel structure. Les
structures sont une caractristique trs puissante de Masm32, et facilit lorganisation et le traitement
des informations.
Pour dclarer une structure, utilisez le couple de directives STRUCT prcd par le nom de la structure
et ENDS. Par exemple :
Dfinissez ensuite la variable (un cas de la structure de Date appele "Lundi") l'un ou l'autre avec des
donnes non initialises .data? :
Ou encore :
Finalement vous pouvez avoir accs la structure et ses champs directement du nom comme cela :
Dans une structure, les donnes membres sont places de manire contige en mmoire. Supposons
que dans notre ordinateur, un BYTE prenne un octet, un WORD en prenne 2 et un DWORD en prenne
4. Dfinissons alors notre struct comme ceci :
X Y Z
Elle occupe donc en mmoire la somme des tailles de ses membres. D'ailleurs, vous pouvez avoir la
taille de votre struct avec l'oprateur sizeof.
Il existe un autre type de structure de donnes, appel union. Une union se comporte extrieurement de
manire trs similaire la struct, mis part qu'elle ne peut tre passe comme argument une
fonction. En matire de syntaxe et d'accs aux donnes membres, rien ne change. Ce qui change, c'est
la rpartition en mmoire et les consquences qui en dcoulent quant l'utilisation des membres.
Vous constatez qu'il n'y a pas grand chose qui change. Par contre, voici sa rpartition en mmoire :
Du fait de cette superposition, vous ne pouvez charger qu'un seul type la fois. Si vous effectuez une
affectation l'un, les valeurs des autres membres ne sont plus retenues... ce n'est ni facile expliquer,
ni facile comprendre. Un bon moyen de retenir ce qui se passe, c'est de se dire qu'une union est
comme un ensemble de variables que vous ne pouvez jamais utiliser en mme temps : l'utilisation de
l'une de ces variables provoque la "disparition" de toutes les autres, jusqu' ce que vous r-effectuiez
une affectation avec une autre.
Je vous ai prsent ici les unions car elles existent. Cependant, je crois bien que je n'en ai utilis quun
nombre limit de fois dans ma vie, et tenter de les utiliser en pensant conomiser de la mmoire, c'est
se compliquer la vie pour rien. Tout ce qu'il vous faut savoir, c'est qu'elles existent, histoire que vous ne
soyez pas compltement dboussols si vous en croisez une dans un programme.
Les pointeurs
Tout le monde sait en gros ce qu'est un pointeur, mais parfois certaines ambiguts persistent et
je prfre rendre les choses claires ds le dbut. Avant de voir la notion de pointeur sur une
variable, peut-tre serait-il utile de bien se souvenir de ce qu'est une variable, justement. Alors une
variable, c'est un emplacement quelque part en mmoire qui sert stocker des valeurs ou des objets
(ou des pommes, des poires). Il faut viter de confondre le contenant, ou conteneur (la variable) du
contenu (la pomme). Si je dis a, c'est parce que souvent la syntaxe mme du langage les confond.
En algorithme
Var : c, d en entier
c <- 4
d <- c
La premire affectation place 4 (la pomme) dans c (le contenant). La seconde affectation copie le
contenu de c dans le contenant de d. Ca n'est pas du tout la mme chose ! Aprs la deuxime
Donc, prsent que nous faisons bien la distinction entre le contenant et le contenu, et que nous
savons qu'une affectation depuis une autre variable ne fait que copier le contenu d'une variable vers
l'autre variable, intressons-nous aux pointeurs proprement dits.
On se rappelle que la mmoire, c'est une suite d'octets, et que chaque octet peut tre numrot par
un nombre allant de 0 beaucoup. Du coup, une variable (le conteneur) peut tre dsigne par
l'indice du premier octet o se trouve ce conteneur, si l'on suppose que le conteneur se trouve plac
d'une manire continue en mmoire, ce qui sera toujours le cas. C'est ce qu'on appelle
l'adresse de la variable. Une adresse dsigne donc le conteneur qu'est une variable.
Un pointeur, c'est une variable dont le contenu est une adresse. Donc, c'est une variable dont le
contenu dsigne une autre variable. J'insiste sur le fait que c'est le contenu du pointeur qui dsigne
cette seconde variable, et pas le pointeur lui-mme.
L'OFFSET renvoie l'adresse d'une variable. Il est utilis pour spcifier la localisation plutt que le
contenu de la variable:
L'OFFSET peut aussi passer l'adresse d'une variable une fonction en invoquant une instruction.
Cependant, a fonctionnera seulement pour des variables globales dclares. Cela chouera avec des
variables. Ceux-ci n'ont aucune compensation comme ils sont crs sur la pile au moment de
l'excution. .
L'oprateur ADDR rsout ce problme. Il est utilis exclusivement avec invoke pour passer l'adresse
d'une variable une fonction. Pour des variables globales il rsume une simple instruction PUSH,
pareil que si l'OFFSET avait t utilise :
ADDR ne peut pas manipuler l'avance la rfrence tandis qu'offset le peut. Par exemple,
si la ligne o est rendu le programme, invoke un label qui est dfini quelque part plus loin
dans le code source, ADDR ne marchera pas.
MASM indiquera une erreur. Si vous utilisez OFFSET au lieu dADDR dans ce petit bout de
code, alors MASM l'assemblera avec succs.
ADDR peut manipuler des variables locales tandis quOFFSET ne le peut pas. Une variable
locale est seulement un petit espace rserv sur la pile. Vous ne connatrez seulement son
adresse que le temps de l'excution. OFFSET est interprt pendant le droulement du
programme par l'assembleur. Donc il est naturel qu'OFFSET ne travaille pas avec des
variables locales. ADDR est capable de manipuler des variables locales grce au fait que
l'assembleur vrifie d'abord si la variable mentionne par ADDR est globale ou locale. Si
c'est une variable globale, il met l'adresse de cette variable dans le fichier d'objet. cet
gard, il travaille comme offset. Si c'est une variable locale, il produit un ordre d'instruction
qu'il appelle en ralit avant la fonction :
Puisque LEA peut dterminer l'adresse d'un label pendant l'excution, a fonctionne trs bien.
Les crochets
Beaucoup de programmeurs utilisent par habitude des crochets avec des variables pour dnoter le
contenu ainsi cela rend le code source un peu plus lisible et il le rend plus facile au code d'tre
support par d'autres assembleurs.
Comme il a t dit ci-dessus, l' offset MaVariable & addr MaVariable les deux signifient
l'adresse de MaVariable. Quand c'est utilis avec les registres, cependant, les crochets font vraiment la
diffrence et ont tendance pointer l'adresse mmoire :
La fonction MessageBox
Faites sortir votre rfrence dAPIs (le fichier Win32.hlp), sinon, lMSDN est mise votre disposition. On
constate alors que lAPI MessageBox prend 4 paramtres comme nous le voyons.
hWnd est le handle ou la poigne de la fentre parente. Vous pouvez vous imaginer qu'un
Handle est un numro qui reprsente la fentre laquelle vous fates rfrence. Sa valeur n'a pas
d'importante pour vous. Vous vous rappelez seulement qu'il reprsente la fentre. Quand vous voulez
faire quelque chose avec la fentre, vous devez vous y rfrer par son 'handle' ou tout simplement
NULL si on ne veut lui associer aucune fentre.
En ce qui concerne les deux paramtres suivants de type texte, aucun problme. lpText pointe sur une
chane zro terminal afficher dans la bote, lpCaption pointe sur une chane zro terminal qui sert
de titre la bote. uType, le rle de cet argument est double : il doit indiquer d'une part quel est le jeu
de boutons souhait, parmi celle qui sont six disponibles. Il doit galement stipuler quelle illustration
viendra ventuellement gayer votre bote messages, parmi les quatre possibles (Critical, Exclamation,
Information, Question). Il est possible d'activer de surcrot quelques autres options, mais nous les
laisserons de ct provisoirement. Ce qui compte, c'est de comprendre comment a marche.
Le contrle de ces constantes est dfini dans le fichier windows.inc qui peut aussi tre ouvert dans
Pour se lancer dans le dveloppement dapplications pour Windows, il est indispensable de bien
connatre les spcificits de la programmation sous Windows, qui se distingue nettement de la
programmation traditionnelle. La programmation Windows passe obligatoirement par lAPI Win32, qui
rassemble tous les types de donnes et les fonctions qui sutilisent pour crer des programmes
Certains aspects de la programmation Win32 sont communs tous les programmes Windows quil
sagisse dun traitement de texte ou dun jeu. Ce sont surtout ces caractristiques communes qui sont
exposes dans ce chapitre. Une fois que vous laurez lu et assimil, vous aurez des bases solides qui
vous permettront dacqurir des connaissances valables pour toute sorte de programme.
Programmation vnementielle
Un des aspects les plus droutants de la programmation Windows pour les dbutants est la nature
vnementielle de cette programmation, plus simplement vnementielle signifie que les programmes
Windows rependent leur environnement. Le flux du programme est dirig par les vnements externes
au programme, comme des clics de souris et des frappes au clavier. Au lieu dcrire du code dtectant
les frappes du clavier, le programmeur Windows crit du code qui accomplit une action chaque fois
quune frappe au clavier est rapporte au programme. Au fur et mesure que vous vous familiarisez
avec le concept dvnements, vous pouvez constater que toute modification de lenvironnement peut
dclencher un vnement. Vous pouvez ainsi concevoir et crire vos programmes de manires quils
ignorent ou ragissent des vnements spcifiques.
La nature vnementielle de Windows a beaucoup voir avec le fait que Windows est un systme
dexploitation graphique. Windows a fort faire et effectue un traitement trs complexe pour permettre
plusieurs programmes dtre excuts simultanment et de partager le mme espace lcran, de la
mmoire, des priphriques dentre et, virtuellement, toute autre ressource systme. Lapproche
vnementielle de la gestion des interactions avec lutilisateur et des modifications systme est pour
beaucoup dans la flexibilit et la puissance de Windows. Dans le contexte de la programmation
dapplications, lapproche vnementielle permet de dcomposer les tches en fonction des vnements
qui se produisent. En dautres termes, un clic avec le bouton gauche de la souris, avec le bouton droit
de la souris, une criture dans une zone de texte, un choix dans une case d'option ou une case
cocher, le dplacement d'un objet et une frappe au clavier sont traits comme des vnements distincts.
Dans les programmes non graphiques traditionnels, le programme invoque une fonction systme pour
accomplir une tche donne. Dans les programmes Windows graphiques, ce scnario est pouss plus
avant, puisque Windows peut invoquer une fonction du programme. En effet, Windows peut envoyer un
Les messages sont adresss une fentre spcifique, qui est gnralement la fentre principale. Dans
une session Windows, plusieurs fentres cohabitent gnralement lcran, et chaque fentre reoit du
temps autre des messages informant des changements survenus. A chacune de ces fentres est
associe une procdure de fentre, qui est une fonction spciale charge de traitement des messages
envoyes par le systme dexploitation la fentre. Windows se charge dadresser les messages aux
procdures de fentre appropries. Il appartient au programmeur dcrire le code de la procdure de
fentre pour que le programme rponde certains messages.
A lge dor des jeux vido par exemple, les dveloppeurs de jeux crivaient souvent leurs programmes
dune manire telle quils utilisaient directement la mmoire de la carte graphique. Cette technique
rendait lexcution des jeux extrmement rapide, parce que les images des jeux taient directement
traites par la carte graphique. Windows noffre pas cette possibilit. De manire gnrale, Windows a t
volontairement conu pour empcher les utilisateurs dinteragir directement avec les composantes de
lordinateur, comme la carte graphique. De ce fait, les applications Windows sont dites indpendantes
vis--vis des priphriques, cest--dire quelles dessinent les images de manire indpendante des
priphriques utiliss cette fin. Lintrt de cette approche rside dans le fait que les applications
Windows peuvent fonctionner avec une vaste gamme de matriel sans aucune modification particulire.
Une telle compatibilit tait impensable dans lunivers DOS.
Lindpendance vis--vis de priphriques sous Windows est rendue possible par linterface de
priphrique graphique, ou GDI (Graphical Device Interface), qui est la partie de lAPI Win32 qui gre
laspect graphique. Linterface GDI intervient entre le programme et le matriel graphique physique. Au
niveau du GDI, les images sont dessines sur un priphrique virtuel de sortie. Cest ensuite Windows
quil appartient doprer la transition entre le priphrique de sortie virtuel et un priphrique rel
spcifique, via la configuration systme, les pilotes des priphriques et ainsi de suite. Bine que
linterface GDI a t expressment conue pour vous garder distance du matriel graphique, elle reste
trs performante. En fait, toutes les applications prsentes dans ce guide sont uniquement fondes sur
cette interface.
La plus grande difficult dans lapprentissage de la programmation Windows est peut tre de se sentir
laise avec les types de donnes tranges qui sont utilis dans tout programme Windows. Un des types
de donnes les plus communes est appel descripteur (handle). Sous Windows, un descripteur est un
nombre qui fait rfrence un objet Windows graphique, comme une fentre ou une icne. Les
descripteurs sont importants, parce que Windows dplace souvent les objets dans la mmoire et que les
adresses mmoire, de ce fait, sont des cibles mouvantes . Les descripteurs sont utiliss dans toute
lAPI Win32 pour manipuler les objets Windows. Ainsi formule, cette notion de descripteur vous semble
peut-tre abstraite et difficile saisir. Mais vous la comprendrez bien mieux ds lors que vous la verrez
mise en pratique dans un programme Windows.
Outre les descripteurs, lAPI Win32 introduit toute une gamme de nouveaux types de donnes, qui
peuvent sembler trange au novice. Tous les types de donnes Win32 tant crit en majuscules, ils sont
faciles identifier. Par exemple, RECT est un type de donnes assez simple et couramment utilis.
RECT reprsente une structure rectangulaire. HWND est galement un type de donnes assez courant,
qui reprsente la poigne dune fentre. Compte tenu du grand nombre de types de donnes utiliss
dans lAPI Win32, nous ne les passerons par tous symtriquement en revue dans ce chapitre. En
revanche, nous dcrirons les types de donnes de cette API au fur et mesure que nous les
rencontrons dans les programmes de ce guide.
Si vous avez dj jet un coup dil sur un programme Windows, vous vous tes peut-tre interrog sur
les noms des variables. Les programmeurs cherchent depuis toujours trouver le moyen dcrire du
code qui soit facile comprendre. Windows rend cette tche particulirement complexe, du fait du grand
nombre et de la diversit de ses types de donnes. Le programmeur Microsoft Charles Simonyi,
aujourdhui lgendaire, proposa une solution plutt astucieuse ce problme : la notation hongroise (M.
Simonyi est hongrois). Dans cette notation, les noms de variables commencent par une lettre ou des
lettres minuscules qui sont indicatives du type de donnes de la variable. Par exemple, tous les noms,
i : entier;
b : boolen (BOOL);
c : caractre;
s : chane;
sz : chane termin par zro;
p : pointeur;
h : descripteur (handle);
w : entier court non sign (WORD);
dw : entier long non sign (DWORD);
l : entier long.
BOOL, WORD et DWORD sont des types de donnes Win32 couramment utiliss.
La notation hongroise est facile appliquer. Par exemple, un compteur entier pourrait tre nomm
iCompt et un descripteur dicne, hIcone. De la mme manire, une chaine termine par un zro
stockant le nom dune quipe sportive pourrait tre appele szNomEquipe. Notez bien que cette notation
est totalement optionnelle, mais trs pratique. Nous lappliquerons dans tous les programmes de ce
guide, et vous pourrez ainsi juger rapidement de sa commodit.
Nous pourrions poursuivre ainsi notre expos thorique sur lAPI Win32. Toutefois, tant donn que
notre objectif est donc arriv le plus rapidement possible la pratique de lAPI Win32 en assembleur,
nous allons directement ltude dun programme Windows. Dans la prochaine section nous tudierons
les principaux aspects dun programme Windows, en examinant le code correspondant. A ce stade, il
nest pas capital que vous compreniez chaque ligne du code.
Ci-dessous voici le code source de notre programme ouvrant une simple fentre. Avant une plonge
dans les entrailles de la programmation Win32 assembleur, regardons quelques points importants qui
soulageront votre programmation.
Vous devez mettre tous les constants Windows, les structures et les prototypes de fonction dans un
fichier includeE (*.inc) et l'inclure au dbut de votre fichier .asm. Cela vous vitera de gros efforts de
rcriture par vous mme. Actuellement, la plupart des fichiers INCLUDE ,tel que windows.inc, sont
Les constants Windows, les structures et les prototypes de Fonction sont toutes des instructions
assembleur. Donc si vous n'avez pas compris, on crit seulement des bouts de programme en ASM
dans des fichiers *.inc et quand vous en avez besoin pour un de vos programmes, vos y faites
rfrence grce une instruction spciale :'INCLUDE'
Utilisez la directive includelib pour indiquer quelle bibliothque d'importation est employe par votre
programme. Par exemple, si votre programme appelle la fonction MessageBox, vous devez mettre la
ligne :
includelib user32.lib
Au dbut de votre fichier .asm. Cette directive informe MASM que votre programme utilisera certaines
fonctions dans cette bibliothque d'importation. Si vos fonctions d'appels de programme ne font pas parti
de la mme bibliothque, ajoutez juste un IncludeLib pour chaque bibliothque que vous employez. En
employant la directive IncludeLib, vous n'avez plus vous inquitez des bibliothques d'importations.
En dclarant des prototypes de fonction API, des structures, ou des constants pour les inclure dans vos
propres fichiers, essayez de respecter les noms d'origines employs par les fichiers INCLUDE de
Windows. a vous vitera bien des maux de tte chercher quelque article dans la rfrence Win32
API.
Les trois premires lignes sont ncessaires. .386 dit MASM que nous avons l'intention d'employer le
jeu d'instruction de processeur 80386 dans ce programme. .model flat, stdcall dit MASM que notre
programme emploie la mmoire plate adressant le modle. C'est pourquoi nous employions le paramtre
stdcall prenant par dfaut cette convention dans notre programme.
Ensuite c'est au tour du prototype de fonction de WinMain. Puisque nous appellerons WinMain plus tard,
nous devons dfinir son prototype de fonction d'abord, pour que nous puissions l'invoquer par la suite.
Nous devons inclure windows.inc au dbut du code source. Il contient les structures importantes et les
constants qui sont employs par notre programme. Le fichier INCLUDE, windows.inc, est simplement un
Notre programme appelle les fonctions API qui rsident dans user32.dll (CreateWindowEx,
RegisterWindowClassEx, par exemple) et kernel32.dll (ExitProcess), donc nous devons li notre
programme avec ces deux bibliothques d'importation. La question suivante : comment puis-je savoir qui
importe la bibliothque qui doit tre lie avec mon programme ? La rponse : Vous devez savoir o
rsident les fonctions API appeles par votre programme. Par exemple, si vous appelez une fonction API
dans gdi32.dll, vous devez vous lier avec gdi32.lib.
C'est l'approche spcifique de MASM. Pour TASM, la bibliothque d'importation qui est lie votre
programme est uniquement : import32.lib. C'est beaucoup, beaucoup plus simple.
Notez : En ralit sous win32, l'Instance Handle est l'adresse linaire de votre programme dans la
mmoire.
Aprs avoir fait appel une fonction de Win32 (une API), la valeur de retour de cette fonction, est
place dans eax. Toutes les autres valeurs sont renvoyes par des variables que vous avez vous-mme
dfini avant le Call qui appel cette fonction.
Une fonction Win32 (ou une procdure) que vous appelez (Call) souvent prservera les registres de
segment ebx, edi, esi et le registre ebp. Au contraire, ecx et edx sont considrs comme des registres
de travail et sont toujours indfinis aprs la sortie d'une fonction de Win32 (sortie d'une procdure).
Notez : n'esprez pas que les valeurs d'eax, ecx, edx soient prservs aprs un appel de fonction API.
La ligne qui suit un appel (un call) une fonction d'API, attend en retour une valeur dans eax. Ds que
vous appelez une fonction API de Windows, vous devez utiliser la rgle suivante : prservez puis
rtablissez les valeurs des registres de segment ebx, edi, esi et ebp aprs le retour de la fonction sinon
votre programme plantera peu de temps aprs, ceci est valable pour vos procdures Windows et pour
les fonctions de rappel de service Windows.
L'appel 'GetCommandLine' est inutile si votre programme ne traite pas de ligne de commande. Dans cet
exemple, je vous montre comment l'appeler dans le cas o vous en auriez besoin dans votre
programme.
Notez : Vous n'tes pas oblig de dclarer le nom de fonction en tant que : 'WinMain'. En fait, vous
avez une totale libert cet gard. Et mme, vous pouvez ne pas employer de fonction WinMain-
quivalent du tout. Le but est de placer votre code (votre vritable programme) l'intrieur de la
fonction WinMain ct de GetCommandLine et votre programme sera toujours capable de fonctionner
parfaitement.
A la sortie de WinMain, eax est rempli du code de sortie. Nous passons ce code de sortie comme
paramtre ExitProcess qui sert terminer notre programme.
La susdite ligne est la dclaration de la fonction WinMain. Notez l'ensemble des paramtres qui suivent
la directive PROC. Ce sont les paramtres que WinMain reoit de la fonction qui l'appelle. Vous pouvez
utiliser les noms de ces paramtres au lieu de vous servir de la pile pour pousser les valeurs de vos
paramtres.
La classe de fentre
Une 'Windows Class' ou classe de fentre n'est rien de plus que la premire bauche d'une fentre.
On dfinit donc plusieurs caractristiques importantes d'une fentre comme son icne, son curseur, la
fonction qui la contrle, sa couleur etc. Vous dfinissez la fentre grce sa 'Windows Class'. C'est en
quelque sorte le but de ce concept. Si vous voulez crer plusieurs fentres avec les mmes
caractristiques, il serait temps de penser stocker toutes ces caractristiques dans un unique endroit
(donc dans une procdure par exemple) et de s'y rfrer quand c'est ncessaire. Cet arrangement
conomisera pas mal de mmoire en vitant la duplication d'informations. Windows doit tre trs efficace
dans l'utilisation des ressources mmoires, qui restent encore rares.
Faisant le point : toutes les fentres gnres par un programme Windows sont cres partir dune
classe de fentre, qui est un modle dfinissant tous les attributs dune fentre. Plusieurs fentres
peuvent tre gnres partir dune mme classe de fentre. Par exemple, il existe une classe de
fentre Win32 standard qui dfinit les attributs dun bouton et qui est utilise pour crer tous les boutons
dans Windows. Pour crer une fentre de votre cru, vous devez enregistrer une classe de fentre, puis
crer une fentre partir de cette classe. Pour pouvoir crer de nouvelles fentres partir dune classe
de fentre, la classe de fentre doit tre enregistre auprs de Windows, en utilisant la fonction de lAPI
Win32 RegisterClass ou RegisterClassEx. Une fois quune classe de fentre a t enregistre, vous
pouvez lutiliser pour crer autant de fentres quil vous sied.
Quelques-uns des types de donnes tranges voqus prcdemment dans ce chapitre apparaissent
dans ce code. A ce stade, nous navons pas besoin dexpliquer ce morceau de code ligne par ligne.
Nous nous contenterons dexaminer quelques unes de ces lments les plus intressants :
Ces lments sont relatifs aux parties dune fentre les plus videntes. lpfnWndProc est probablement le
plus subtil comprendre, parce quil sagit dun pointeur sur la procdure de fentre de la classe de
fentre. Nous reviendrons un peu plus loin sur cette procdure de fentre. Les lments hIcon et
hIconSm sont utiliss pour dfinir les icnes de la classe de fentre : ils correspondent aux icnes de
programme qui sont visibles lorsquun programme est en cours dexcution sous Windows. hCursor
sutilise pour dfinir un pointeur de souris spcial pour la classe de fentre, qui se substitue au pointeur
flche standard. Et pour finir, hbrBackground sutilise pour dfinir larrire-plan de la classe de fentre.
Le blanc est utilis comme couleur darrire plan pour la majorit des fentres, mais vous pouvez trs
bien choisir une autre couleur.
Une fois encore, il nest pas ncessaire ce stade que vous compreniez en dtail la structure dune
classe de fentre. Lide est seulement ici de vous familiariser suffisamment avec la programmation
Win32 pour que nous puissions assembler un programme complet. Un peu plus loin dans ce chapitre,
nous ferons usage de la structure de classe de fentre pour crer un programme Windows minimal.
Aprs l'enregistrement de la classe de fentre, la cration dune fentre principale reprsente la partie
critique dun programme Windows. Pour crer une fentre, vous devez en passer par une classe de
fentre. Bien que les classes de fentre dfinissent les caractristiques gnrales dune fentre. Ces
attributs doivent tre spcifis sous la forme darguments de la fonction CreateWindowEx. Celle-ci est la
fonction de lAPI Win32 ddie la cration de la fentre. Lexemple qui suit montre comment crer une
Il nest pas vital que vous compreniez chacune des lignes de ce fragment du code. Nous allons nous
contenter den tudier les aspects les plus intressants. Tout dabord, dwExStyle cest le style de fentre
supplmentaire. C'est le nouveau paramtre qui est ajout la vieille fonction 'CreateWindow'. Vous
pouvez mettre des nouveaux styles de fentre pour Windows 9x & NT ici. En temps normal, vous
pouvez spcifier votre style de fentre ordinaire dans dwStyle, mais si vous voulez certains styles
spciaux pour une fentre 'tip top', vous devez les spcifier ici. Vous devez employer un NULL si vous
ne voulez pas de styles de fentre supplmentaires. Le nom de la classe de fentre est spcifi comme
argument, ClassName. Aprs vient le titre de la fentre, Lassembleur Win32 est super ! . Ce titre
apparatra dans la barre de titre de la fentre lexcution du programme. WSOVERLAPPEDWINDOW
est un style Win32 standard qui identifie une fentre traditionnelle redimensionnable. Les quatre styles
CW_USEDDEFAULT indiquent la position XY de la fentre lcran, ainsi que la hauteur et la largeur
de la fentre. Vous pouvez rgler ces paramtres sur des valeurs numriques, mais
CW_USEDDEFAULT indique Windows de choisir une valeur par dfaut raisonnable. hWndParent, c'est
l'Handle de la fentre parente de votre fentre (si celle-ci existe). Ce paramtre indique Windows si
Bon d'accord, elles sont lourdes... mais non, vous n'tes pas obligs de les retenir. Mais force de les
utiliser (vous verrez ), vous les connatrez par cur. "C'est en forgeant qu'on devient forgeron" ce
qu'il parat.
En retour couronn de succs de CreateWindowEx, l'Handle de la fentre est place dans eax. Nous
devons garder cette valeur pour une utilisation future. La fentre que nous venons de crer n'est pas
automatiquement affiche. Mais la fentre ne s'affichera pas pour autant. Elle est cre, mais c'est tout.
Pour l'afficher, il faut appeler la fonction ShowWindow ! Celle-ci prend en premier paramtre le handle
de la fentre dont on veut changer le mode d'affichage, et un DWORD dterminant son mode. Vous
pouvez soit utiliser le paramtre de WinMain modeDAffichage, soit utiliser la valeur qu'il prend d'habitude
: SW_SHOW. Maintenant que la fentre est en mode "affiche", il faut rafrachir l'cran afin de la
montrer l'utilisateur : c'est le rle dUpdateWindow, prenant comme seul paramtre le handle de la
Je souhaite que nous commencions par quelques explications sur la notion du test et des
boucles en MASM avant de continuer analyser notre code.
Les Tests
MASM dfinit une directive de haut niveau, nomm .IF (n'oubliez pas le point en prfixe), qui simplifie la
rdaction des instructions IF composes par rapport l'emploi de CMP et sauts conditionnels; voici la
syntaxe formelle:
Les crochets montrent que .ELSEIF et .ELSE sont facultatives alors que .IF et .ENDIF sont obligatoires.
Chaque condition est une expression boolenne qui utilise les mmes oprateurs que ceux du C++ et
de Java. L'expression n'est pas value que pendant l'excution. Voici quelques exemples de conditions
acceptables :
Voici maintenant quelques conditions composes. Nous supposons que val1 et val2 sont des variables
de type double-mot :
Oprateur Description
expr1 >= expr2 Renvoie Vrai si expr1 est plus grande ou gale expr2
expr1 < expr2 Renvoie Vrai si expr1 est plus petite que expr2
expr1 <= expr2 Renvoie Vrai si expr1 est plus petite ou gale expr2
Avec les directives de haut niveau telle que .IF et .ELSE, cest le compilateur dassembleur qui va crire
les instructions assembleur votre place. Partons par exemple d'une directive .IF qui cherche
comparer le contenu de EAX la variable val1:
Nous supposons que val1 et resultat sont des entiers non signs sur 32 bits. Lorsque le compilateur lit
les lignes prcdentes, il est considre comme des instructions assembleur :
Lorsque vous utiliser .IF pour comparer des valeurs, vous devez vous mfiez de la manire dont sont
gnrs les sauts conditionnels. Si c'est la comparaison concerne une variable non signe, c'est une
instruction de saut conditionnel non signe qui sera insre dans le code gnr. Voici un exemple trs
proche du prcdant avec comparaison entre eax et val1 qui est un double mot non sign :
L'assembleur comprend ces lignes en choisissant d'utiliser linstruction JBE (saut pour non sign) :
A partir de ces lignes l'assembleur va gnrer du code utilisant l'instruction JLE qui permet un
branchement en comparant des valeurs signes :
Que se passe-t-il si on veut comparer deux registres ? Il est vident que l'assembleur ne pas en
dduire ltat sign ou non sign des valeurs :
Dans ce cas le programme assembleur opte pour la comparaison non sign. Autrement dit la directive
.IF utilise pour comparer deux registres donne lieu linjection dune instruction JBE.
Expressions composes
Nous avons dj rencontr les expressions composes au dbut de chapitre. La plupart des expressions
boolennes composes sarticulent autour des deux oprateurs OR et AND. Si vous utilisez la directive
.IF, le symbole || reprsente loprateur OR :
Les boucles
Et a y est, on y est, on est arrivs, la voil, cest Broadway une autre structure : a est les boucles. Si
vous voulez pater vos amis, vous pouvez galement parler de structures rptitives, voire carrment de
structures itratives. Ca calme, hein ? Bon, vous faites ce que vous voulez, ici on est entre nous, on
parlera de boucles.
Bon, alors nous avons vu jusqu'ici les notions de base, les variables, les oprateurs, ainsi que les
structures conditionnelles. Mais il manque encore quelques points importants afin de faire un programme
digne de ce nom. En effet, les programmes ont parfois besoin de rpter une ou plusieurs instructions
pour effectuer une certaine tche. C'est mme encore plus frquent que vous ne pourriez l'imaginer.
Les directives .REPEAT et .WHILE offrent une solution alternative pour mettre en place des boucles avec
CMP et des instructions de saut conditionnel. Elles acceptent les expressions de saut conditionnelles
vues au tableau des oprateurs relationnels et logique dexcution.
La directive .REPEAT excute les instructions du corps de la boucle avant de tester la condition de
boucle qui est place derrire la directive .UNTIL
Le test de condition tant ralis la fin, les instructions qui font partie de la boucle .REPEAT sont
toujours excutes au mois une fois. Au contrario, dans la boucle WHILE, si le teste est faux ds le
dbut, les instructions ne seront jamais excutes.
La directive .WHILE est un peu linverse de la prcdente : elle teste la condition avant dexcuter le
premier tour de boucle :
Exemples
Lextrait suivant fait la somme des 100 premiers nombres entiers au moyen de la directive .WHILE :
Lextrait suivant fait la somme des 100 premiers nombres entiers au moyen de la directive .REPEAT :
Lextrait suivant fait la somme des 100 premiers nombre entiers au moyen de la directive .WHILE en
sauvegardant la somme des 50 premiers dans une variables res.
Sortir de la boucle
Il peut tre prfrable, dans certains cas, de sortir de la boucle avant que la condition d'arrt n'ait eu
lieu. Si vous voulez sortir d'une boucle dans laquelle vous tes directement (c'est--dire que vous n'tes
pas dans une sous-boucle, boucle imbriqu), vous avez votre disposition la directive .BREAK. Cette
directive sort directement de la boucle dans laquelle vous tes, autrement dites, elle permet de briser la
structure de contrle qui l'encadre.
Sachez cependant que la directive .BREAK ne sort que de la boucle dans laquelle vous vous trouvez
directement. Il vous faudra avoir recours d'autres astuces pour sortir de toutes les boucles embotes
d'un coup. Mais je pense que le jour o vous aurez besoin de faire cela, vous trouverez vous-mme la
solution. Je ne vais donc pas en rajouter pour le moment; voici la syntaxe formelle:
Il existe galement une autre directive pour contrler une boucle : .CONTINUE. Comme la directive
.BREAK, .CONTINUE ne peut tre plac que dans le corps dune boucle. Cette instruction saute
directement aprs la dernire instruction de la boucle, mais sans en sortir. On passe donc directement
l'itration suivante ; voici la syntaxe formelle:
La directive Goto
La directive goto est son tiquette peuvent se trouver dans des blocs de code diffrents, mais doivent
toujours faire partie de la mme fonction.
Syntaxe :
Cette fois-ci, notre fentre est sur l'cran. Mais elle ne peut pas recevoir d'informations extrieures
(comme une saisie de texte ou bien la dtection de la pression d'un bouton). Donc nous devons
l'informer de ce qui se passe. Nous faisons a avec une boucle de message.
Prcdemment dans ce chapitre, nous avons vu que Windows communique avec les programmes en
leur transmettant des messages. Nous allons maintenant tudier de plus en dtail le fonctionnement de
ces messages Windows. Trois lments information sont associs un message :
une fentre ;
un identificateur de message ;
des paramtres de message.
La fentre associe un message est la fentre laquelle est adress le message. Lidentificateur de
message est un nombre qui identifie la nature du message envoy. Dans lAPI Win32, une constante
numrique est associe chaque message. Par exemple, WM_CREATE, WM_PAINT et
Les paramtres de message consistent en deux lments dinformation, qui sont entirement spcifiques
au message envoy. Ces paramtres 32 bits sont appels wParam et lParam. La signification de ces
paramtres dpend du message en cours de traitement. Par exemple, le paramtre wParam du message
WM_SIZE contient des informations relatives au type de dimensionnement possible sur la fentre, tandis
que le paramtre lParam contient les nouvelles valeurs de la largeur et de la hauteur de la zone interne
de la fentre (galement appele zone client de la fentre). La largeur et la hauteur sont stockes dans
les mors bas et haut de la valeur lParam 32 bits. Ce mode de stockage est lapproche classiquement
utilise dans Win32 pour stocker deux lments dinformation en un mme emplacement. Si la notion du
mot haut et bas ne vous est pas familire, ne vous inquitez pas : nous verrons un peu plus loin, quand
nous en aurons besoin, comment extraire du paramtre les informations lParam utiles.
Lorsquun message est transmis par Windows un programme, il est trait dans ma fonction WndProc
(). Si WndProc () est charg de traiter les messages pour une classe de fentre donne, cest au
programme quil appartient dacheminer les messages vers les procdures de fentre appropries. Pour
cela, on utilise une boucle de message au cur de la fonction WinMain ():
Il y a seulement une boucle de message pour chaque module. Cette boucle de message vrifie
continuellement les messages de Windows grce un 'Call GetMessage'. GetMessage passe une
donne une structure de MESSAGE de Windows. Cette structure de messagesera remplie de
l'information du message que Windows veut envoyer une fentre dans le module. La fonction
GetMessage ne retournera pas (ne reviendra pas votre programme mais au contraire restera dans
Kernel ou User) tant qu'un message (ex : appui sur un bouton) ne sera pas transmis pour une fentre
dans le module. Pendant ce temps-l, Windows peut donner le contrle d'autres programmes. C'est en
quelque sorte le fonctionnement en Multigestion de la plate-forme Win16. GetMessage renverra une
erreur si le Message WM_QUIT est reu dans la boucle de message, et ainsi nous termineront la boucle
et irons vers la sortie du programme.
TranslateMessage est une fonction utile qui saisie les entres de clavier ( la vole) et produit un
nouveau Message WM_CHAR qui est plac sur la file d'attente des messages. Le message avec
'DispatchMessage' redirige les donnes d'un message (ex : envoi : on vient d'appuyer sur le bouton)
la procdure responsable de la fentre spcifique.
Si la boucle de message se termine, le code de sortie est stock dans le membre wParam de la
structure de MESSAGE. Vous pouvez stocker ce code de sortie dans eax pour le rendre Windows.
Actuellement, Windows ne se sert pas de la valeur de retour, mais c'est mieux de respecter les rgles.
La procdure de fentre
C'est notre procdure Win. Vous ne devez pas la nommer WndProc. Le premier paramtre, hWnd, est
l'Handle de la fentre pour laquelle le message est destin. uMsg est le message. Notez qu'uMsg n'est
pas une structure de message. C'est juste un numro (nombre). Windows dfinit des centaines de
messages, dont la plupart ne seront pas intressants pour vos programmes. Windows enverra un
message appropri une fentre seulement si quelque chose d'intressant arrive cette fentre. La
procdure qui traite vos fentres reoit le message et y ragit intelligemment. wParam et lParam sont
juste des paramtres supplmentaires pour l'utilisation de certains messages. Certains messages
envoient des donnes d'accompagnement en plus du message lui-mme. On passe ces donnes la
procdure de fentre au moyen de wParam et lParam.
Vient ici la partie cruciale. C'est l'endroit o la plupart de l'intelligence de votre programme rside. Les
codes qui rpondent chaque message de Windows sont dans la procdure de fentre (la procdure
Et voil : vous tes prts pour crer votre premire fentre ! En combinant le tout, vous obtenez cette
uvre magnifique :
Enfin, presque. Vous aurez srement une barre de titre diffrente, cause du thme de Windows.
Voil, ce dernier chapitre est termin, j'espre qu'il vous a plu. Ne vous dcouragez surtout pas face
la longueur du code, car cela en vaut la peine, et cela va rentrer progressivement en tant
qu'automatisme ;)
C'est ici ou s'achve notre petite introduction l'assembleur, merci de l'avoir lue! Il vous reste tout
dcouvrir, l'API Win32 en ASM est loin d'tre ce que vous avez lu, mais un peu de volont et de
motivation vous serez capable dtre un programmeur ASM confirm ;) seule la pratique permettant de
faire des progrs et c'est comme ceci que les choses rentrent le mieux, vos claviers !
Je tiens vous dire que "crire" est quelque chose de trs dur, pour cela je remercie inconcevablement
tous ceux qui rdigent des tutoriaux et qui les mettent notre disposition, tous ceux qui combattent pour
vulgariser l'information et tous ceux qui partagent leurs connaissances par la seule et unique motivation :
Le plaisir.
Javoue que je me suis inspir de certains livres/ezines/ebooks principalement ceux des trois auteurs
Kip Ivrine Assembleur x86 , Jean-Bernard Emond Le tout en poche Assembleur x86 , Michal
Morrison, Programmation des jeux . Ce guide est galement inspire de quelques billets savoir
notre chre ami la Wiki, du site : http://win32assembly.online.fr/, merci Iczelion, son crateur.
Je tiens remercier aussi toute personne ayant contribu la ralisation de ce guide que ce soit de
manire directe ou indirecte. Jentends par l : Benot-M, Rmi Coquet, Obsidian, Alcatz, MrGh0st,
N@bilX, DaBDouB-MoSiKaR, Mz Sarah, Oussama Fatihi, Yassine Tahiri, Alaa Dounassre, Othmane
Basbas, Metal-, lquipe FAT (Kaze, Baboon, Tuna, Ed, Silmaril, Poco, Codasyl), CiM
(Esp!onLeRaVaGe!, r007, Willingness, DrNitro, Mr L, X-Crk,, BlackPirate, FiRe, xsp!der, Le_Maudit, ),
ForumCrack (BeatriX2004, Squallsurf, Virtualabs, rAsM, ), AT4RE (Mouradpr, GamingMaster, Zeak47,
), Logram-Project (Youscef, Azerty, SteckDennis ) et la liste est longue donc tous ceux que jai
oubli.
Vos remarques, suggestions, conseils et critiques me seraient trs utiles pour lamliorer encore ; vous
pouvez les envoyer Noteworthy@live.fr.
Rfrences bibliographiques
[French]
http://fat.next-touch.com/forum/: le forum du site, o rgne une excellente ambiance, qui vous aidera
lorsque vous rencontrez des problmes, vous pourrez galement y demander des conseils
http://www.forumcrack.com/forum/
http://www.winasm.net/forum/
http://www.masm32.com/board/
http://www.asmcommunity.net/
Code Source
http://win32assembly.online.fr/source.html Masm32
http://www.magma.ca/~wjr/
http://asmsource.cjb.net/
http://www.asmfr.com/
http://www.geocities.com/SiliconValley/Heights/7394/
http://rs1.szif.hu/~tomcat/win32/ Win32Nasm
http://pagesperso-orange.fr/vombonjour/myprogs.html
http://www.team-x.ru/guru-exe/index.php?path=Sources/
Autres cours