• Aucun résultat trouvé

Structure d’un programme en Assembleur 8

programmation système

3. Structure d’un programme en Assembleur 8

Un programme en Assembleur se compose en général de 3 parties définissant les différents segments :

1. le segment de code (pointé par CS), 2. le segment de données (pointé par DS), 3. le segment de pile (pointé par SS).

3.1. Déclaration des segments

La déclaration d’un segment se fait selon la syntaxe suivante : Nom_Segment SEGMENT PARA ;Début du segment

<<*** Instructions ou données appartenant au segment ***>> Nom_Segment ENDS ;Fin du segment

NB. : Tout ce qui se trouve après le point-virgule (;) est considéré comme commentaire Exemple : Déclaration d’un segment de code

MonCode SEGMENT PARA

MOV AX,1200h

ADD AX,[5E00h]

MOV AX,4C00h

INT 21h

MonCode ENDS

3.2. Déclaration des données et de la pile

Le segment de données est réservé aux données que le programme utilise pendant son exécution. Ces données sont représentées sous forme d’octets, de mots, de tableaux ou de chaînes de caractères et peuvent être traîtés comme des constantes ou des variables. Chaque donnée est stockée en mémoire sous forme hexadécimale.

Les variables peuvent recevoir une valeur initiale attribuée par le programme comme elles peuvent rester sans initialisation et c’est pendant l’exécution qu’elles reçoivent des valeurs.

La syntaxe de définition des données au sein du segment de données dépend de leur nature : 3.2.1. Définition d’un octet

Nombre DB 18h

Label Valeur initiale

Les valeurs initiales peuvent être exprimées en décimal, en hexadécimal (h) ou en binaire (b). Le compilateur se charge de faire la conversion. Ainsi les déclarations suivantes sont identiques :

Décimal Hexadécimal Binaire Nombre DB 24 Nombre DB 18h Nombre DB 00011000b

Pour définir un octet sans lui affecter de valeur initiale, on utilise le symbole ? Nombre DB ?

3.2.2. Définition d’un mot (16 bits) Prod DW 5C0Fh Label Valeur initiale 3.2.3. Définition d’un tableau d’octets

Tab DB 15h,5Ah,21h,7Ch,82h

Dans cet exemple, si le label Tab désigne l’adresse 45F0h, La case mémoire 45F0h contient 15h, la case 45F1h la valeur 5Ah, ... etc

Pour définir un tableau de 10 octets sans initialisation, on écrit : Tab DB 10 DUP (?)

Pour définir un tableau de 7 octets contenant des valeurs identiques (2Ah par exemple), on écrit : Tab1 DB 7 DUP (2Ah)

Cette définition est parfaitement identique à la définition suivante : Tab1 DB 2Ah, 2Ah, 2Ah, 2Ah, 2Ah, 2Ah, 2Ah 3.2.4. Définition d’un tableau de mots

TabM DW 15EEh, 5A00h, 12FFh, 8B00h

Si l’adresse pointée par le label TabM est 1200h, le contenu de la mémoire sera:

1200h 1201h 1202h 1203h 1204h 1205h 1206h 1207h EEh 15h 00h 5Ah FFh 12h 00h 8Bh

3.2.5. Définition d’une chaîne de caractères MaChn DB 'Ceci est un exemple' Chn2 DB 'FIN',0Dh,0Ah

Une chaîne de caractères est stockée sous forme d’octets représentant le code ASCII de chaque caractère. La chaîne est écrite entre guillemets et c’est le compilateur qui se charge de convertir chaque caractère en code ASCII.

On peut définir des chaînes de caractères contenant des caractères spéciaux (caractères non imprimables mais qui ont une signification particulière pour l’ordinateur). Ces caractères sont représentés par leur code ASCII dans la définition de la chaîne. Ainsi dans le deuxième exemple, la chaîne de caractère "FIN" est suivie de deux caractères spéciaux de code ASCII : 0Dh (retour chariot) et 0Ah (retour à la ligne).

Si le label Chn2 désigne l’adresse 8000h, le contenu de la mémoire sera le suivant : 8000h 8001h 8002h 8003h 8004h

46h 49h 4Eh 0Dh 0Ah "F" "I" "N"

L’affichage de cette chaîne sur l’écran provoquera un retour à ligne après l’apparition du mot "FIN".

3.2.6. Déclaration du segment de données

La syntaxe est identique à celle du segment du code. Dans un segment de données on regroupe toutes les données utilisées par le programme.

Les variables déclarées sont placées l'une après l'autre dans la mémoire. Chacune prend l'espace mémoire nécessaire.

Exemple

Donnees SEGMENT PARA ; Début du segment

Var1 DB 12h ; 1 octet

Mot1 DW 15E4h ; 2 octets (mot de 16 bits) Table DB 5 DUP(1Ch) ; 5 octets (taille du tableau) Chaine DB 'Test',0 ; 5 octets (longueur de la chaîne) Donnees ENDS ; Fin du segment

Si le premier octet du segment de données se trouve à l'offset 0000, le contenu de la mémoire sera:

0000h 0001h 0002h 0003h 0004h 0005h 0006h 0007h 12h E4h 15h 1Ch 1Ch 1Ch 1Ch 1Ch

Var1 Mot1 Table

0008h 0009h 000Ah 000Bh 000Ch 54h 65h 73h 74h 00h

Chaine

Les labels qui identifient chaque variable reçoivent l'offset de celle-ci dans le segment de données : Label Offset attribué

Var1 0000h Mot1 0001h Table 0003h Chaine 0008h

3.2.7. Utilisation des données dans le programme

Comme on vient de voir, chaque donnée est repérée par un label. Celui-ci reçoit l'adresse logique (sur 16 bits) de la donnée dans la mémoire.

Pour faire référence à une donnée définie dans le segment de données, on utilise tout simplement son label.

Exemple 1

Soit la variable Var1 de type octet définie précédemment dans le segment de données (voir ci- dessus):

Var1 DB 12h

Pour charger le contenu de la variable Var1 dans le registre AL, on écrit : MOV AL,Var1

Pour écraser le contenu de Var1 et la charger par la valeur 45h, on écrit : MOV Var1,45h

Remarque

Var1 représente l'adresse logique de la variable, en réalité, Var1 désigne l'adresse logique 0000h. Au moment de la compilation, le compilateur remplace l'instruction MOV AL,Var1 par MOV AL,[0000h].

Exemple 2

Soient deux tables de 5 valeurs dont le début est désigné par les labels XVect et YVect. La deuxième table n'est pas initialisé.

XVect DB 12h,3Ah,15h,4C,2Dh YVect DB 5 DUP (?)

Le programme suivant permet de copier dans la deuxième table le contenu de la première en utilisant SI et DI comme registres d'index :

LEA SI,XVect ;Charger SI par l'adresse désignée par XVect LEA DI,YVect ;Charger DI par l'adresse désignée par YVect

MOV AH,5

suite: MOV AL,[SI] MOV [DI], AL INC SI INC DI DEC AH CMP AH,0 JNE suite

L'instruction LEA (Load Effective Adress) permet de charger dans un registre l'adresse désignée par un label.

Exemple

Si XVect désigne l'adresse 2B07h :

LEA BX,XVect aura pour résultat BX=2B07h,

MOV BX,XVect aura pour résultat BX=3A12h (premières valeurs de la table XVect). Remarque

LEA BX,XVect est équivalente à MOV BX,offset XVect (charger BX par l'offset de XVect) 3.2.8. Déclaration du segment de pile

La pile est une zone mémoire qui doit être réservée pour le programme (gestion des appel aux sous-programmes et aux interruptions, ...), et pour d'autres usages généraux (sauvegarde de données temporaires, passage de paramètres à une procédure, ...)

Dans le plupart des cas, la déclaration d'un segment de pile est obligatoire surtout en présence de sous-programmes.

La taille de la pile varie selon les applications. Un programme récursif aura besoin d'une pile de taille beaucoup plus importante qu'un programme ordinaire.

La réservation d'une zone mémoire pour le segment de pile se fait de la manière suivante : MaPile SEGMENT PARA STACK

DB 256 DUP (?) MaPile ENDS

Ici, la taille de la pile est de 256 octets. Ce qui est suffisant pour des petits programmes en assembleur.

3.3. Exemple de programme

Pile SEGMENT PARA STACK ; Définition du segment de pile DB 256 DUP ('P') ; Pile de 256 octets remplie par

Pile ENDS ; le caractère 'P'

Donnees SEGMENT PARA ; Définition du segment de données Table DB 11 DUP (00) ; Table de 11 octets initialisée par 0 Donnees ENDS

Code SEGMENT PARA ; Définition du segment de code ASSUME CS : Code ; Affectation des registres ASSUME DS : Donnees ; de segments

ASSUME SS : Pile

Debut: MOV AX,Donnees ; Initialisation du registre DS

MOV DS,AX

LEA BX,Table ; BX reçoit l'adresse logique de Table

XOR AL,AL ; AL = 0

Boucle: MOV Byte Ptr [BX],AL ; Byte Ptr [BX] veut dire octet ...

INC BX ; ... pointé par BX

INC AL

CMP AL,0Bh ; Teste la fin de la boucle

JNE Boucle ; AL ≠ 0Bh ⇒ aller à Boucle

MOV AH, 4Ch ; Appel à la fonction 4C de

INT 21h ; l'interruption 21h(Retour au DOS) Code ENDS

END Debut ; END indique la fin du programme ; Debut désigne le label de la ; première instruction du programme Remarque

Les registres CS et SS sont automatiquement affectés aux segments Code et Pile respectivement. Par contre, le registre DS doit être initialisé dans le programme

3.4. Appel aux fonctions du DOS et du BIOS

L'appel des fonctions du DOS et du BIOS se fait par le biais des interruptions logicielles. Avant d'appeler l'interruption, on charge les éventuels paramètres dans les registres du microprocesseur. Certaines fonctions renvoient des résultats après l'exécution de l'interuption. Ceux-ci sont en général stockés dans les registres du microprocesseur.

Comme le nombre des fonctions disponibles est très grand, il n'est pas possible de donner des explications détaillées dans le cadre de ce document (voir à ce sujet les ouvrages spécialisés).

Exemple : Affichage d'un caractère sur l'écran Interruption : 21h

Paramètres :

• AH = 02h (fonction n°2)

• DL = Code ASCII du caractère à afficher

Le programme suivant permet d'afficher le caractère "A" sur l'écran : MOV DL,41h ;Code ASCII du caractère "A" MOV AH,2 ;Fonction n°2

INT 21h ;Appel de l'interruption 21h

Documents relatifs