PAR FAISEUR
MISE EN PLACE DE MASM32
Question:
Pourquoi choisir Masm32 ?
Réponse:
Plusieurs assembleurs de qualité sont disponibles sur internet. Masm32 utilise un standard éprouvé par de très longues années et profite d'une énorme contribution faite de la part de la communauté; notamment concernant les exemples fournis en démonstration, sélectionnés avec soin, ainsi que par les librairies et les macros développées par des programmeurs talentueux depuis des décennies.
C'est également l'assembleur fournit avec le kit de développement Visual Studio de Microsoft (mais amputé de la possibilité d'utiliser des macros). Cela dit, Fasm par exemple, un des derniers arrivés, est devenu populaire car la syntaxe en est plus épurée, avec moins de fioritures et donc un peu plus simple à lire. Le choix reste ici de profiter de l'énorme contribution des programmeurs sur Masm qui en a fait un outil de référence. Le débutant trouvera toujours des sources Masm pour l'aider dans sa progression. Pour ceux qui auraient peur de l'avenir de cet assembleur avec l'arrivée du 64 bits sachez que le codage en 64 bits est rendu totalement accessible grâce à JWasm, entièrement compatible avec le codage de Masm (les macros comprises) et avec Linux.
Pour travailler en assembleur commencez par mettre en place le projet Masm32 sur votre ordinateur. Téléchargez Masm32 v10 sur le site de Hutch :
http://www.masm32.com/masmdl.htm
Laissez faire l'installeur, qui va également compiler les librairies.
Remarques:
- Il est préférable d'installer le package Masm32 dans un répertoire racine.
- Evitez tout ce qui contient des espaces dans les répertoires de vos projets. Si par exemple votre projet Masm32 se trouve dans le répertoire "Masm 32" plutôt que "Masm32" vous risquez de ne pas pouvoir compiler votre code si vous utilisez un fichier bat.
UTILISATION DE L'IDE QEDITOR
L'utilisation d'un éditeur performant et complet est important pour se sentir à l'aise et sera même déterminant lorsque nous aborderons le travail avec des boîtes de dialogue (gui). Mais pour bien débuter sans perdre son temps à configurer un outil complexe Qeditor est un bon choix. Il se trouve inclus avec le package Masm32 et vous n'aurez, en principe, rien à modifier dans ses réglages pour compiler les exemples fournis, les modifier, les exécuter, etc. Pour des projets plus lourds nous verrons plus tard la mise en place d'un autre IDE: RadAsm.
Visualisons un exemple simple fournit dans Masm32 avec Qeditor:
- Commencez par lancer Qeditor. Il se trouve dans le répertoire Masm32.
- Dans son menu choisissez "File" -> "Open", puis cherchez le répertoire "masm32\examples\exampl01" et chargez le fichier "minimum.asm".
- Le code contenu dans le fichier "minimum.asm" s'affichera dans Qeditor. Bien que l'exécutable soit déjà fourni essayez de compiler ce code pour vérifier que tout fonctionne. Il suffit de sélectionner "Project" -> "Build all". Une console va s'ouvrir et signaler que tout s'est bien passé.
- Enfin exécutez le code avec "Project" -> "Run Program". C'est tout ! Le programme sera exécuté et une MessageBox va s'afficher.
ANALYSE DU SQUELETTE DE "MINIMUM.ASM"
Etudions donc "minimum.asm", l'exemple fournit dans le package Masm32.
Voici le contenu de minimum.asm:
- Code:
; #########################################################################
.386
.model flat, stdcall
option casemap :none ; case sensitive
; #########################################################################
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
; #########################################################################
.code
start:
jmp @F
szDlgTitle db "Minimum MASM",0
szMsg db " --- Assembler Pure and Simple --- ",0
@@:
push MB_OK
push offset szDlgTitle
push offset szMsg
push 0
call MessageBox
push 0
call ExitProcess
; --------------------------------------------------------
; The following are the same function calls using MASM
; "invoke" syntax. It is clearer code, it is type checked
; against a function prototype and it is less error prone.
; --------------------------------------------------------
; invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_OK
; invoke ExitProcess,0
end start
Passons en revue le squelette du programme. Ce squelette sera toujours semblable pour vos projets avec Masm.
Partie 1
- Code:
.386
.model flat, stdcall
option casemap :none ; case sensitive
Vous n'aurez rien à modifier dans cette partie pour la plupart de vos projets, sauf si vous utilisez des jeux d'instruction particuliers tels que MMX ou SSE2. Par exemple pour utiliser des instructions MMX le code ".386" sera remplacé par ".586" et une ligne supplémentaire ".MMX" sera ajoutée juste ensuite.
Partie 2:
- Code:
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
Nous définissons ici ce que Masm doit inclure (include) comme librairies pour notre programme. Les API Windows les plus courantes utilisent kernel32.dll. Mais évidemment ce n'est pas tout; viennent s'y ajouter d'autres librairies qui s'occupent de fonctions ciblant un domaine précis. C'est le cas de user32.dll qui inclut la fonction "MessageBox", que l'on ne trouvera pas sur kernel32. C'est pourquoi "minimum" inclut ces deux dll dans ses définitions: user32 pour utiliser l'API "MessageBox" et kernel32 pour utiliser l'API "ExitProcess". Ce sont ces deux dlls que vous trouverez incluses le plus régulièrement dans un programme.
Avec Masm il est nécessaire de préciser deux types de fichiers concernant ces dlls:
- Code:
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
Les fichiers ".inc" contiennent les définitions "PROTO" (prototypes) des fonctions d'appel des dll. Masm peut ainsi comprendre comment les définir dans le code. Il s'agit donc d'un fichier propre à Masm qu'il est nécessaire d'inclure pour chaque dll.
- Code:
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
Ces fichiers contiennent les bibliothèques d'importation des dll. Il est nécessaire de les lier au programme, autrement celui-ci ne sera pas capable de retrouver la fonction API qui sera demandée.
Enfin, ce fichier doit toujours être présent dans vos projets et placé au début !
- Code:
include \masm32\include\windows.inc
Partie 3:
- Code:
.code
Il faut définir ce que l'on appelle un "
- Code:
szDlgTitle db "Minimum MASM",0
szMsg db " --- Assembler Pure and Simple --- ",0
Comme nous l'avons vu précédemment, le saut empêche Masm d'exécuter ces deux lignes de code au début du programme. Masm permet différentes formes d'écriture, dont la possibilité d'inclure les chaînes de caractère dans la partie "code" de votre script, autrement dit sans avoir besoin de les ajouter dans la section ".data". Masm les insérera lui-même dans la section appropriée lors de la compilation du programme. C'est un choix qui reste assez peu usité mais tout à fait propre et c'est pourquoi cet exemple est montré dans le package Masm.
Les textes placés après un ";" ne sont pas ajoutés lors de la compilation, il s'agit de notes pour le lecteur. Le fichier "minimum.asm" explique une autre manière de coder dans la note suivante:
- Code:
; invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_OK
; invoke ExitProcess,0
Ces deux lignes de code suffisent à remplacer les 7 lignes précédentes en se servant de la fonction "Invoke". Mettons cela en pratique !
En tenant compte de l'utilisation de la fonction "invoke" voici comment vous pouvez écrire tout cela de manière plus "classique":
- Code:
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
szDlgTitle db "Minimum MASM",0
szMsg db " --- Assembler Pure and Simple --- ",0
.code
start:
invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_OK
invoke ExitProcess,0
end start
L'exemple "minimum" a pour but de montrer la souplesse offerte par Masm dans la mise en forme de votre code. Vous avez différents choix possibles, sans compter l'utilisation de macros évoluées qui seront abordées dès le Tutoriel suivant. Ce que nous pouvons retenir avec cet exemple au stade où nous en sommes:
1. La fonction "Invoke" définit en une ligne la séquence d'appel d'une fonction API. C'est-à-dire qu'elle remplace une instruction call et les différents paramètres placés avec l'instruction push. De plus, invoke vous signale une erreur si vous oubliez un paramètre avant l'appel d'une fonction, ce qui ne sera pas signalé par un call (un push en moins ou en trop avant un call, etc). C'est pourquoi utilisez "invoke" pour vos appels de fonctions API.
2. Vous pouvez déclarer des variables - ou des chaînes de caractère - à l'intérieur d'une procédure en ajoutant un "jmp" pour ne pas les exécuter. Cela peut rendre votre code plus lisible dans certains cas. Une fois que Masm va compiler le code les variables et chaînes de caractères placées entre les sauts seront insérées dans la section ".data".
3. En assembleur il est normalement nécessaire de définir un étiquette de destination pour un saut comme:
jmp suite <-- saute à "suite"
suite: <-- arrivée du saut
Masm vous permet de simplifier cette procédure en utilisant les raccourcis suivants: @F - @B - @@
Exemple pour sauter à l'étiquette suivante:
- Code:
@@:
jmp @F <-- saut à l'étiquette SUIVANTE
@@: <-- arrivée
Exemple pour sauter à l'étiquette précédente:
- Code:
@@: <-- arrivée
jmp @B <-- saut à l'étiquette PRECEDENTE
@@:
Donc:
jmp @F <-- saut à l'étiquette @@ SUIVANTE (F pour Forward)
jmp @B <--saut à l'étiquette @@ PRECEDENTE (B pour Back)
UTILISATION DE .IF .ENDIF
Maintenant poursuivons en ajoutant une condition à notre programme "minimum". En fonction de la réponse reçue dans la MessageBox le programme se comportera différemment. Voici le code:
- Code:
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
szDlgTitle db "Minimum MASM",0
szMsg db "Choisissez Oui ou Non",0
szMsgYes db "Oui",0
szMsgNon db "Non",0
.code
start:
invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_YESNO
.if eax == IDYES ; si réponse "Oui" alors affiche ceci
invoke MessageBox,0,ADDR szMsgYes,ADDR szDlgTitle,MB_OK
.else ; sinon affiche cela
invoke MessageBox,0,ADDR szMsgNon,ADDR szDlgTitle,MB_OK
.endif
invoke ExitProcess,0
end start
Nous avons ajouté la condition "IF-ELSE-ENDIF" (si - sinon - fin de condition), une routine de haut niveau qui permet d'agir en fonction de certains critères. Si l'utilisateur clique sur "Oui" la valeur renvoyée par MessageBox est "IDYES" et l'on traite alors notre réponse. Si l'utilisateur clique sur "Non" la valeur renvoyée par MessageBox sera différente de IDYES, dans ce cas nous traitons une autre réponse placée dans "else". On peut donc résumer l'"intelligence" du code à faire ceci:
Si réponse "Oui" alors exécute ceci
Sinon exécute cela
Nous avons également utilisé notre premier registre: eax. Pourquoi ? Simplement parce que les valeurs de retour des API Windows pointent toujours dans le registre eax; il s'agit d'une convention qui à ma connaissance ne souffre d'aucune exception. Autrement dit, si nous souhaitons traiter une valeur de retour envoyée par la fonction API MessageBox il nous faut analyser ce que contient le registre eax. C'est dans ce registre que nous allons trouver la réponse de l'utilisateur, la constante correspondant à la valeur "IDNO" ou "IDYES", la sélection du bouton.
Note: si vous cherchez à connaître les différentes possibilités offertes par une fonction consultez sans hésiter la MSDN de Microsoft ! Cette bible est disponible en ligne. Par exemple pour la fonction MessageBox:
http://msdn.microsoft.com/en-us/library/...85%29.aspx
Tou y est décrit, ainsi que la dll nécessaire pour utiliser une fonction API.
UTILISATION DE .WHILE .ENDW
.WHILE - .ENDW est une condition de haut niveau qui vous permet d'effectuer une boucle. Cela peut s'avérer très pratique. Si une fois rendu à .ENDW la condition de .WHILE est remplie, le code reprend la boucle. Voici un exemple reprenant minimum.asm en ajoutant cette condition:
- Code:
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
szDlgTitle db "Minimum MASM",0
szMsg db "Souhaitez-vous reprendre la boucle ?",0
.code
start:
mov eax,IDYES
.While eax == IDYES ; si réponse "Oui"
invoke MessageBox,0,ADDR szMsg,ADDR szDlgTitle,MB_YESNO
.Endw
invoke ExitProcess,0
end start
Notre exemple est un peu bidon mais il va vous permettre de bien assimiler le principe. Voici l'"intelligence" du code:
mov eax,IDYES <-- on place la valeur IDYES pour valider la séquence de la boucle
.WHILE <-- Si eax a la valeur IDYES exécute les instructions qui suivent
.ENDW <-- Renvoie à .While. Si eax a TOUJOURS la valeur IDYES on reprend la boucle, sinon on saute
Conséquence: notre programme va afficher "Souhaitez-vous reprendre la boucle ?" tant que l'utilisateur n'aura pas cliqué sur "Non".
Juillet 2010 - Faiseur
0 commentaires:
Enregistrer un commentaire