Tutorial 1 : les bases

Ce tutorial suppose que le lecteur sache comment employer MASM. Si vous n'êtes pas familiers avec MASM, téléchargez win32asm.exe et étudiez le texte à l'intérieur du ZIP avant la suite des Tutoials. Bon. Vous êtes maintenant prêts. On y va!

Théorie:

Les programmes Win32 fonctionnent en mode protégé depuis le 80286. Mais le 80286 c'est maintenant de l'histoire ancienne. Donc nous devons seulement nous intéresser au 80386 et à ses descendants. Windows dirigent chaque programme Win32 séparément. Ceci signifie que chaque programme Win32 aura à sa disposition ses propres espaces de mémoire. Cependant, cela ne signifie pas que chaque programme win32 a 4GB de mémoire physique, mais seulement que le programme peut adresser n'importe quelle adresse dans cette gamme. Windows fera tout le nécessaire pour adresser les vraies références (physiques) du programme aux adresses (mémoires) valables 00401000… qu'il utilise. Bien sûr, le programme doit respecter les règles de Windows, autrement il causera une Erreur de Protection Générale tant redoutée. Chaque programme est seul dans son espace d'adresse. C'est la différence 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 réduisent la chance d'une écriture du code d'un programme par dessus les données d'un autre.
Le modèle de mémoire est aussi résolument différent des vieux jours du monde du 16 bits. Désormais, sous Win32, nous ne sommes plus concernés par le modèle de mémoire en plusieurs segments! (0001.xxxx puis 0002.xxxx puis 0003.xxxx ….)Il y a seulement un seul modèle de mémoire : le modèle de mémoire uniforme (Flat). Il n'y a plus de segments de plus 64Ko (différence *.com / *.exe). La mémoire est un seul espace continu. Ça veut dire aussi que vous n'avez plus besoin de jouer avec les différents registres concernant les segments [ES et SS]. Vous pouvez employer n'importe quel registre de segment pour adresser n'importe quel point dans l'espace de mémoire (ouf !). C'est une GRANDE aide pour les programmeurs. C'est ce qui fait de l'assembleur Win32 une programmation aussi facile que le C.
Quand vous programmez sous Win32, vous devez respecter quelques règles importantes. Une règle{*Majeure*} est que Windows emploie lui-même ESI, EDI, EBP et EBX et les valeurs de ses registres changent, en même temps qu'une autre application tourne en parallèle avec Windows. Rappelez-vous donc cette règle {*Primordiale*} d'abord : si vous employez chacun de ces quatre registres à l'intérieur d'une procédure, n'oubliez jamais de les reconstituer{*rétablir*} avant le contrôle de retour à Windows. L'exemple évident 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 rétablir ces registres après un call.

Contenu:

Voici le squelette de n'importe quel programme. Si vous ne comprenez pas quelques-uns des codes, ne paniquez pas. J'expliquerai chacun d'entre eux plus tard.

.386
.MODEL Flat, STDCALL
.DATA
    <Vous initialisez les data>
    ......
.DATA?
   <Vous initialisez les data>
   ......
.CONST
   <Vous initialisez vos constantes>
   ......
.CODE
   <label>
    <Vous initialisez votre code(début du segment Code)>
   .....
    end <label>


C'est tout! On va analyser le squelette de ce programme.

.386
C'est une directive d'assembleur, disant à l'assembleur d'employer le jeu d'instructions du 80386. Vous pouvez aussi employer .486 .586 mais l'important c'est d'utiliser au minimum les fonctions à partir du .386. Il y a en réalité deux formes presque identiques pour chaque modèle de directive. .386/.386p.486/.486p. Ces versions "p" sont nécessaires seulement quand votre programme emploie des instructions privilégiées. Les instructions privilégiées sont des instructions réservées par le système du CPU / FONCTIONNEMENT en mode protégé. Elles peuvent seulement être employés par le code privilégié, comme les conducteurs de dispositif virtuels. La plupart du temps, votre programme travaillera dans le mode non-privilégié donc c'est presque sûr que vous n'emploierez pas les versions -p.

.MODEL FLAT, STDCALL
.MODEL est une directive d'assembleur qui spécifie le type de mémoire de votre programme. Sous Win32, il y a seulement un type, le modèle FLAT (mémoire un en seul bloque).
STDCALL dit à MASM quel est l'ordre de passage des paramètres de la pile vers un Call. De " gauche à droite " ou " le droit à gauche " et aussi ça équilibrera l'encadrement de la pile après l'appel de la fonction.
Sous Win16, il y a deux types de convention d'appel, la convention C et le PASCAL
La convention C passe les paramètres de la pile de droit à gauche, c'est-à-dire le paramètre extrême droit est poussé d'abord. L'interlocuteur est responsable du balancement de l'encadrement de pile après l'appel. Par exemple, pour appeler une fonction nommée foo (int first_param, int second_param, int third_param) dans la 'convention d'appel C', les codes d'asm ressembleront à cela :

push  [3e_paramètre]               ; Pousse le 3e paramètre sur la pile
push  [2e_paramètre]            ; Suivi par le second
push  [1er_paramètre]                ; Et du 1er
call    Procédure_foo
add    sp, 12                            ; La fonction appelante équilibre le remplissage de la pile
la convention d'appel PASCAL est le contraire de la convention C. elle passe les paramètres de la pile de gauche à droite et le Call est responsable de équilibre (de l'état) de la pile après l'appel.
Win16 adopte la convention
PASCAL parce qu'il produit des codes plus petits. La convention C, est utile quand vous ne savez pas combien de paramètres on passera à la fonction comme dans le cas de wsprintf (). Dans le cas de wsprintf (), la fonction n'a aucune façon de déterminer à l'avance combien de paramètres seront préservés sur la pile, donc on ne peut pas déterminer l'état de la pile.
STDCALL est l'hybride de la Convention de Pascal et C. Il passe les paramètres de droit à gauche. La plate-forme Win32 emploie exclusivement STDCALL . Sauf dans un cas : wsprintf (). Vous devez employer la convention C avec wsprintf ()

.DATA
.DATA?
.CONST
.CODE

Ces quatre directives servent a appeler la section (00401000……). Vous n'avez pas de segments (0001.xxxx, 0002.xxxx,…) dans Win32, vous vous souvenez ? Mais vous pouvez diviser votre espace d'adresse (00401000 à 00620000 par exemple) en sections logiques, exemple : " le code de 00401000 à 005F0000 " et "les DATA de 005F0000 à 00620000 ". Le début d'une section dénote la fin de la section précédente. Il existe deux groupes de section : données et code. Les sections de données sont divisées en 3 catégories :

Vous n'êtes pas forcément obligé d'employer ces trois sections dans votre programme. Déclarez seulement la (ou les) section (s) que vous voulez utiliser.

Il n'y a seulement qu'une section pour le code : .CODE. C'est celle où vos lignes de code résident.

<label>
end <label>
Où <label> représente n'importe quelle étiquette arbitraire, et est employé pour indiquer le début et la fin de votre code. Les deux 'label' doivent être identiques.  Toutes vos lignes de code doivent se trouver entre <label> et end <label>


[Iczelion's Win32 Assembly HomePage]


Traduit par Morgatte