TROISIEME PARTIE

LE LANGAGE ASSEMBLEUR



    I. DEFINITION DE DONNEES ET ADRESSAGE
    1. Les définitions de données

Les mots “db” (« define byte »), “dw” (« define word »), ”dd” (« define double word ») permettent de déclarer et d’initialiser une variable. Il faut bien comprendre que leur seule action est d’écrire les données dans l’exécutable à l’endroit même où elle se trouvent dans le code source.

Pour accéder à ces données (appelées « variables »), il suffit de connaître leur adresse. Pour cela, on peut les faire précéder d’un label de données.

Exemple :

TOTO dw 1982

Dans la ligne précédente, TOTO représente l’adresse du nombre 1982 qui est défini juste après. Comme ce nombre est codé sur deux octets (word = 16 bits), c’est le premier octet qui est adressé par TOTO.

Le compilateur se contentera d’écrire le nombre 1982 à l’endroit où se trouve la déclaration.

Remarque : en C, on écrirait ceci :

int TOTO = 1982;

En BASIC ou en PASCAL, cette définition n’a pas d’équivalent, puisque les variables ne peuvent être initialisées lors de leur déclaration. Il est donc obligatoire d’ajouter une ligne de code pour le faire.

Dans la partie précédente, nous avons eu à définir le message qui serait affiché à l’écran. Voici la ligne que nous avons écrite :

message db “Bonjour, monde !”, ‘$

Lorsqu’il rencontre une chaîne de caractères, le compilateur écrit les codes ASCII de tous les caractères, les uns à la suite des autres.

Voici une autre manière d’écrire cette définition de données. Le résultat (i.e. le programme compilé) est EXACTEMENT LE MÊME :

message db 42h, 111, ‘nj

db ‘our, mo

db ‘nde !$

Pour définir plusieurs fois à la suite les mêmes données, on utilise “DUP” (« duplicate ») de la manière suivante :

TOTO db 100 dup(“TOTO EST BEAU”)

Cela revient à écrire :

TOTO db “TOTO EST BEAU

TOTO db “TOTO EST BEAU

TOTO db “TOTO EST BEAU

;… etc (100 fois) …

Il est fréquent que de nombreuses données n’aient pas besoin d’être initialisées à une valeur précise. Dans ce cas, on les regroupe à la fin du programme et on les remplace par le caractère ‘?’. Les adresses des labels seront calculées de la même façon mais aucune données ne sera écrite dans le fichier (et a fortiori dans la RAM). On dit que l’on met ses variables sur le « tas » (« heap » en anglais). La seule différence avec une définition classique est qu’au début de l’exécution, nos variables n’auront pas de valeur définie. Leurs valeurs seront « aléatoires » en ce sens qu’on ne peut les connaître au moment de la compilation.

Exemple :

Remarque : Si elles ne sont pas regroupées en fin de programme, le compilateur sera obligé d'écrire les données dans le fichier afin de ne pas fausser les adresses des variables (ou du code) qui suivent. Il remplira alors les points d’interrogation avec des zéros.

Pour indiquer qu’un chiffre est noté en base hexadécimale, on lui ajoute la lettre ‘h’. La lettre ‘b’ signifie que le chiffre est codé en binaire, la lettre 'o' en octal et la lettre ‘d’ en base décimale (base par défaut).

    2. L’adressage
    a) l’adressage immédiat

On appelle « adressage immédiat » l’adressage qui ne fait intervenir que des constantes.

Considérons cette partie de programme qui stocke le nombre 125h dans une variable appelée TOTO, lui ajoute 15 puis charge le résultat dans AX.

La ligne

mov word ptr ds:[TOTO], 125h

charge le nombre 125h dans le mot de la RAM adressé par DS et l’offset de “TOTO”. La ligne suivante ajoute 15 au contenu de ce mot.

L’expression “word ptr” devant l’adresse, obligatoire ici, indique la taille de la variable dans laquelle doit être stocké le nombre 125h.

Si on avait mis “dword ptr”, ce nombre aurait été codé sur 32 bits (00000125h) au lieu de 16 bits (0125h) : on aurait donc écrasé les deux octets qui suivent la variable. Si on avait mis “byte ptr”, la compilation aurait été impossible car un octet ne peut contenir un nombre supérieur à FFh.

Le compilateur n’a en effet aucun moyen de connaître cette taille. La variable “TOTO” n’a pas de taille (malgré le mot “dw”) : ce n’est en fait qu’un pointeur vers le premier octet du word qu’elle représente.

En revanche, la troisième instruction ne fait pas apparaître l’expression “word ptr”. Cette fois-ci elle est facultative du fait que la destination (AX = 16 bits) impose la taille.

On peut évidemment remplacer “TOTO” par une constante numérique :

mov word ptr ds:[004Ch], 125h

Le mot 125h sera alors écrit à l’adresse DS:4C.

Une question se pose à présent : que se passe-t-il si le programmeur n’écrit pas le registre de segment dans l’adresse ?

C’est là qu’intervient la directive “assume”. Le compilateur va devoir trouver lui-même quel registre l’utilisateur a voulu sous-entendre.

Si on a utilisé un label, alors le segment sera celui dans lequel est déclaré le label. Mais le compilateur veut un REGISTRE de segment. Il va donc prendre celui qui est censé pointer vers le bon segment et pour le savoir, il examine la directive assume.

Voilà pourquoi cette dernière peut nous épargner d’écrire pour chaque variable l’expression “ds:”.

Comprenez bien que cette directive ne sert à rien d’autre qu’à cela et qu’en aucune façon elle ne force les registres de segment à prendre quelque valeur que ce soit.

    b) l’adressage indexé et/ou basé

Comme nous l’avons déjà expliqué, il est possible d’utiliser des registres de base ou d’index pour adresser un octet.

On appelle « base » les registres BX et BP et « index » les registres SI et DI. La différence est que la base est censée être fixe tandis que l’index varie automatiquement lorsqu’on utilise certaines opérations, telles que MOVSB.

Remarque : BX, BP, DI et SI peuvent tous être utilisés comme des registres généraux.

Voici les adressages possibles:

  • Constante seule (= adressage immédiat) :

Exemples :

MOV AH, byte ptr [TOTO]

MOV BX, word ptr ds:[1045h]

MOV ES:[10 + TOTO x 2], BL

  • Base seule :

Exemple :

MOV dword ptr ds:[BP], 15

  • Index seul :

Exemple :

MOV dword ptr es:[DI], 142

  • Base + Constante :

Exemples :

MOV byte ptr ds:[BP + 1], 12

MOV ds:[BX + (TOTOBOBO)/10], AX

  • Index + Constante :

Exemples :

MOV CX, [TOTO + DI]

MOV AL, ds:[1 + SI]

  • Base + Index :

Exemple :

MOV ds:[BP + SI], AH

  • Base + Index + Constante :

Exemple :

MOV AX, word ptr [TOTO + BX + DI + 1]

Remarque : si la constante n’est pas un label, il est parfois impératif de spécifier le registre de segment ! Tout dépend du contexte…



Sommaire

Suite