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
|