I. PREMIER EXEMPLE : LES FICHIERS COM
Voici un petit programme COM qui écrit le message « Bonjour,
monde ! » à l’écran.
Ce code source commence par des directives.
Une directive est une information que le programmeur fournit au
compilateur. Elle n’est pas transformée en une
instruction en langage machine. Elle n’ajoute donc aucun
octet au programme compilé.
La directive “.386“ indique au compilateur que
le programme est destiné à tourner sur des processeurs
INTEL de modèle 386 (ou supérieur). Cela nous autorise
à utiliser certaines instructions qui ne sont pas disponibles
sur les modèles antérieurs, comme PUSHA ou POPA. Dans
cet exemple, cette directive aurait très bien pu être
omise.
La ligne
code segment use16
sert à déclarer un segment que l’on appelle “code”.
On aurait tout aussi bien pu le nommer “marteau”
ou “voiture”. Ce sera le segment de notre
programme. N’oubliez pas qu’un fichier COM ne peut
comporter qu’un seul segment. Cette ligne ne sera pas
compilée : elle ne sert qu’à indiquer au
compilateur le début d’un segment.
Le mot “use16” indique que les adresses de segment et
d’offset sont codées sur 16 bits et non sur 8 bits. Vous
devez systématiquement l’écrire.
La directive
assume cs:code, ds:code, ss:code
informe le compilateur que tout au long du programme, CS, DS et SS pointeront
de façon privilégiée vers le segment “code”,
ce qui est évident d’ailleurs puisque c’est le
seul segment… Vous comprendrez le sens exact de “assume”
dans la troisième partie du cours.
Enfin, les mots
org 100h
signifient qu’il faudra ajouter 100h (soit 256) à tous les offsets.
Pourquoi ? Souvenez-vous de la structure d’un programme
COM en mémoire. Si vous n’écrivez pas cette
ligne, TASM considérera que le programme débute à
l’offset 0000. Or, lors de l’exécution, le DOS le
chargera après le PSP, c’est-à-dire à
l’adresse 100h. C’est pourquoi il est nécessaire
de recalculer les offsets : l’offset 0000 deviendra 0100.
Cette directive est en quelque sorte le trait caractéristique
des fichiers COM.
Nous en arrivons au programme proprement dit. Il commence par un label :
debut :
Lui non plus n’est pas compilé. Il ne sert qu’à
représenter l’adresse de l’instruction qui le
suit, c’est-à-dire :
mov ah, 09h
Cette ligne demande au processeur de charger la valeur 9 dans le registre
AH. C’est le numéro de la fonction de l’interruption
21h qui écrit une chaîne de caractères à
l’écran. L’offset de cette chaîne est
attendu dans DX. D’où la ligne suivante :
mov dx, offset message
Le mot-clé “offset” sert à extraire l’offset
du label “message” qui représente quant à
lui l’adresse du message à écrire (il contient
donc une adresse de segment ET un offset). L’adresse de segment
de la chaîne doit être transmise dans DS. Mais il est
inutile de changer ce registre, car il pointe déjà vers
notre segment.
Il nous reste à appeler l’interruption 21h :
int 21h
et à rendre la main au DOS :
ret
Lorsque nous aborderons les procédures, vous comprendrez mieux le sens
de ce mot et ce qu’il fait exactement. Pour l’instant,
sachez simplement que seul un fichier COM peut se terminer avec cette
instruction.
Nous arrivons à la ligne :
message db “Bonjour, monde !”, ‘$’
Il s’agit d’une définition de données. Le mot
“db” (« define byte »)
signifie que le compilateur devra écrire les octets qui
suivent tels qu’ils sont dans notre code source. Il va donc
écrire le code ASCII du ‘B’, puis celui du ‘o’,
etc… Il terminera en écrivant le code ASCII du signe
‘$’. C’est ainsi que la fonction 9 de
l’interruption 21h reconnaît la fin de la chaîne à
écrire. Si vous oubliez ce signe, elle écrira tous les
octets de la RAM jusqu’à ce qu’elle tombe par
hasard sur lui.
Le mot “message” placé en début de
ligne est un label de données. Il représente l’adresse
du code ASCII du ‘B’. Remarquez
qu’il n’y a pas de caractère ‘:’ après
un label de données.
La ligne
code ends
indique la fin du segment “code”, et enfin
end debut
informe le compilateur que le fichier est fini, tout comme le “END.”
du PASCAL. Le nom du label “debut” est mentionné :
ce sera le point d’entrée de notre programme. C’est
vers lui que pointera CS:IP avant l’exécution.
Remarque :
vous n’êtes pas tenu de rendre aux registres la valeur
qu’ils avaient au début de votre programme. De toute
façon, avant de charger un programme, le DOS sauvegarde le
contenu de tous les registres puis met le contenu des registres
généraux (ainsi que SI, DI et BP) à zéro.
Il les restaurera quand vous lui rendrez la main.
Sommaire
Suite
|