Chapitre 4 Structure General

Vous aimerez peut-être aussi

Vous êtes sur la page 1sur 11

I.

Structure général d’un programme en assembleur :


Comme tout programme, un programme écrit en assembleur comprend des définitions de données et
des instructions, qui s’écrivent chacune sur une ligne de texte.
Les données sont déclarées par des directives, mots clef spéciaux que comprend l’assembleur. Les
directives qui déclarent des données sont regroupées dans le segment de données, qui est délimité
par les directives SEGMENT et ENDS.
Les instructions sont placées dans un autre segment, le segment de code.
La première instruction du programme (dans le segment d’instruction) doit toujours être repérée par
une étiquette. Le fichier doit se terminer par la directive END avec le nom de l’étiquette de la
première instruction (ceci permet d’indiquer à l’éditeur de liens quelle est la première instruction à
exécuter lorsque l’on lance le programme). Les points-virgules indiquent des commentaires.

II. Déclarations :
II.1 Variables de 8 ou 16 bits
Les directives DB (Define Byte) et DW (Define Word) permettent de déclarer des variables de
respectivement 1 ou 2 octets.
Exemple :
A DW 15 ; 2 octets initialises a 15
B DW ? ; 2 octets non initialises
C DB ? ; 1 octet non initialise
D DB -1 ; 1 octet initialise a -1 ; recevera la valeur en Cà2 : 11111111
E DW 0F0AH ; en hexa
F DB 01110000b ; en binaire

II.2 Les Tableaux


Il est aussi possible de déclarer des tableaux, c’est à dire des suites d’octets ou de mots consécutifs.
data SEGMENT
Tab1 db 10, 0FH
Tab2 db -2, ’ALORS’
Tab3 DB 5 dup (15) ; 5 octets valant 15 chacun
Tab4 DW 3 dup (?) ; 5 mots de 16 bits non initialises
data ENDS

Après chargement, la mémoire aura le contenu suivant :

Adresse Contenu mémoire


Début data segment Tab1 0A
Tab1 + 1 OF
Tab2 FE
Tab2 + 1 41
Tab2 + 2 4C
Tab2 + 3 4F
Tab2 +4 52
Tab2 + 5 53
Tab3 0F
Tab3 + 1 0F
Tab3 + 2 0F
Tab3 + 3 0F
Tab3 +4 0F
Tab4 00
Tab4 + 1 00
Tab4 + 2 00
Tab4 + 3 00
Tab4 +4 00

Si l’on veut écrire un caractère B à la place du A de ALORS, on pourra écrire :


MOV Tab2+1, ‘B’

Pour accéder à un élément du tableau on utilise la directive de l’assembleur, offset.

Exemple :
data SEGMENT
tab DB ’operating system’, ’$’
data ENDS

code SEGMENT
ASSUME DS:data, CS:code

debut: MOV AX, data


MOV DS, AX

MOV BX, offset tab ; adresse debut tableau


repet: MOV AL, [BX] ; lis 1 caractere
AND AL, 11011111b ; force bit 5 a zero
MOV [BX], AL ; range le caractere
INC BX ; passe au suivant
CMP AL, ’$’ ; arrive au $ final ?
JNE repet ; sinon recommencer

MOV AH, 4CH


INT 21H ; Retour au DOS
code ENDS
END debut

III. La pile :
La pile est une zone mémoire qui sert à stocker temporairement des valeurs. Elle fonctionnant en
mode LIFO (Last In First Out : dernier entré, premier sorti). Deux opérations sont possibles sur la
pile :
• empiler une donnée : placer la donnée au sommet de la pile ;
• dépiler une donnée : lire la donnée se trouvant au sommet de la pile.

Le sommet de la pile est repéré par un registre appelé pointeur de pile (SP : Stack Pointer) qui
contient l’adresse de la dernière donnée empilée. La pile est définie dans le segment de pile dont
l’adresse de départ est contenue dans le registre SS.

Deux nouvelles instructions, PUSH et POP, permettent de manipuler la pile.


PUSH registre/var : empile le contenu du registre sur la pile.
POP registre/var : retire la valeur au sommet de la pile et la place dans le registre spécifié.

Exemple : transfert de AX vers BX en passant par la pile.


PUSH AX ; Pile <- AX
POP BX ; BX <- Pile

La pile est souvent utilisée pour sauvegarder temporairement le contenu des registres :
; AX et BX contiennent des données à conserver

Exemple :
PUSH AX
PUSH BX

MOV BX, truc ; on utilise AX


ADD AX, BX ; et BX
MOV truc, BX

POP BX ; recupere l’ancien BX


POP AX ; et l’ancien AX

L’instruction PUSH effectue les opérations suivantes :


– SP ← SP - 2
– [SP] ← valeur du registre 16 bits.
Notons qu’au début (pile vide), SP pointe “sous” la pile.

L’instruction POP effectue le travail inverse :


– registre destination ← [SP]
– SP ← SP + 2
Si la pile est vide, POP va lire une valeur en dehors de l’espace pile, donc imprévisible.

Pour utiliser une pile en assembleur, il faut déclarer un segment de pile, et y réserver un espace
suffisant.

Exemple :
Déclaration d’une pile de 200 octets :
stack SEGMENT; mot clef stack car pile
DW 100 dup (?)
ENDS

Le registre SP va pointer sur la base de la pile.

IV. Les procédures :


Les procédures structurent les programmes en donnant un nom à un traitement et en
réduisant la taille des programmes qui utilisent plusieurs fois la même séquence de code.

IV.1 Instructions CALL et RET


L’appel d’une procédure est effectué par l’instruction CALL.
CALL adresse_debut_procedure
L’adresse est sur 16 bits, la procédure est donc dans le même segment d’instructions.

L’instruction CALL effectue donc les opérations :


– Empiler la valeur de IP. A ce moment, IP pointe sur l’instruction qui suit le CALL.
– Placer dans IP l’adresse de la première instruction de la procédure (donnée en
argument).

Et l’instruction RET :
– Dépiler une valeur et la ranger dans IP.
IV.2 Déclaration d’une procédure
On déclare une procédure dans le segment d’instruction comme suit :

Calcul PROC ; procedure nommee Calcul


... ; instructions
RET ; derniere instruction
Calcul ENDP ; fin de la procedure

Le mot clef PROC commence la définition d’une procédure.

Exemple :
stack segment
dw 128 dup(0)
ends
code segment
start:
mov ax, data
mov ds, ax

mov ax,20 ; sp=0100h


call somme ; sp=00FEh
mov cx,54

somme proc ; ax <- ax + bx


add ax, bx
ret ; sp=0100h
somme endp
……

IV.3 Passage de paramètres


En général, une procédure effectue un traitement sur des données (paramètres) qui sont fournies par
le programme appelant, et produit un résultat qui est transmis à ce programme.

Plusieurs stratégies peuvent être employées :


1. Passage par registre : les valeurs des paramètres sont contenues dans des registres du processeur.
C’est une méthode simple, mais qui ne convient que si le nombre de paramètres est petit (il y a peu
de registres).
2. Passage par la pile : les valeurs des paramètres sont empilées. La procédure lit la pile.

A. Passage par registre


Le mode de passage de paramètres le plus simple consiste à passer la valeur dans un registre :
l’appelant charge un registre avec la valeur à passer ; l’appelé récupère la valeur dans ce même
registre.

Exemple :
On va écrire une procédure “SOMME” qui calcule la somme de 2 nombres naturels de 16 bits.
Convenons que les entiers sont passés par les registres AX et BX, et que le résultat sera placé dans
le registre AX.
La procédure s’écrit alors très simplement :
SOMME PROC ; AX <- AX + BX
ADD AX, BX
RET
SOMME ENDP

et son appel, par exemple pour ajouter 6 à 8 :


MOV AX, 6
MOV BX, 8
CALL SOMME
MOV var, AX

B. Passage par la pile


Cette technique met en œuvre un nouveau registre, BP (Base Pointer), qui permet de lire des
valeurs sur la pile sans les dépiler ni modifier SP.

Le registre BP permet un mode d’adressage indirect spécial, de la forme :


MOV AX, [BP+6]

Cette instruction charge le contenu du mot mémoire d’adresse BP+6 dans AX.

Ainsi, on lira le sommet de la pile avec :


MOV BP, SP ; BP pointe sur le sommet
MOV AX, [BP] ; lit sans depiler

et le mot suivant avec :


MOV AX, [BP+2] ; 2 car 2 octets par mot de pile.

L’appel de la procédure “SOMME2” avec passage par la pile est :


PUSH 6
PUSH 8
CALL SOMME2

La procédure SOMME2 va lire la pile pour obtenir la valeur des paramètres. Pour cela, il faut bien
comprendre quel est le contenu de la pile après le CALL :

Le sommet de la pile contient l’adresse de retour (ancienne valeur de IP empilée par CALL).
Chaque élément de la pile occupe deux octets.

La procédure SOMME2 s’écrit donc :


SOMME2 PROC near ; AX <- arg1 + arg2
MOV BP, SP ; adresse sommet pile
MOV AX, [BP+2] ; charge argument 1
ADD AX, [BP+4] ; ajoute argument 2
RET
SOMME2 ENDP
La valeur de retour est laissée dans AX.
V. Macro :
Une macro-instruction ou macro est une séquence d'instructions que l'assembleur traite quand
il rencontre le nom de la macro dans un programme.
On remplace du code fréquemment utilisé par une macro. Ceci rend le code source plus rapide à
écrire et plus compact. Le code objet n'est cependant pas plus court que si l'on n'utilisait pas de
macros, contrairement à un sous-programme utilisé plusieurs fois dans un programme.

Exemple :
ma macro ; declaration de la macro
mov bx,1
add ax,bx
endm

ma ; appel de la macro

VI. Traitement des chaînes de caractères


Plusieurs instructions existent pour le traitement de séquences de données. Le registre SI pointe
implicitement vers la chaîne source, le registre DI vers la chaîne destination.

VI.1 LODS
LODSB charge le registre AL (respectivement, AX pour l’instruction LODSW) avec l’octet
(respectivement le mot) pointé par le registre SI. SI est automatiquement incrémenté.

VI.2 STOS
STOSB écrit en mémoire l’octet (respectivement le mot pour l’instruction STOSW) se trouvant
dans le registre AL (respectivement dans le registre AX) en mémoire à l’adresse pointée par le
registre DI. Le segment destination est forcément ES. DI est automatiquement incrémenté.

Exemple :
Data segment
TABLEAU DW 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
Data ends
Extra segment
RES DW 10 DUP (0)
Extra ends
Code segment
Start :
mov ax, data
mov ds, ax
mov ax, extra
mov es, ax

lea si, TABLEAU


lea di, RES

mov cx, 10
BOUCLE: lodsw
mov bl, 2
mul bl
stosw
loop BOUCLE
Exercice :
Soit la chaine « SYSTEM ». Donner un pgm qui la met en minuscule.
Data segment
chaine DB ‘SYSTEM’
Data ends
Extra segment
Result Db 6 DUP (?)
Extra ends

Code segment
Start :
mov ax, data
mov ds, ax
mov ax,extra
mov es, ax

lea si, chaine


lea di, Result

mov cx, 6
BOUCLE: lodsb
OR AL, 00100000b ; force bit 5 a un
stosb
loop BOUCLE

VI.3 MOVS
Transfert d’un élément entre deux chaînes. Il copie l’octet (respectivement le mot pour l’instruction
MOVSW) pointé par SI vers l’octet (respectivement le mot) pointé par ES:DI. SI et DI sont
automatiquement incrémentés.

VI.4 CMPS
CMPSB compare l’octet (respectivement le mot pour l’instruction CMPSW) pointé par SI à l’octet
(respectivement le mot) pointé par ES:DI. SI et DI sont automatiquement incrémentés.

VI.6 SCAS
SCASB compare la valeur de l’octet (respectivement le mot pour l’instruction SCASW) contenu
dans le registre AL (respectivement AX) à l’octet (respectivement le mot) pointé par ES:DI. DI est
automatiquement incrémenté.

VI.7 REP
C’est une instruction qui permet d’itérer sur toute une chaîne les opérations élémentaires vues
précédemment. On dit que l’instruction préfixe l’opération à itérer. REP ne peut préfixer que les
instructions LODS, STOS, MOVS. Un compteur (registre CX) indique le nombre d’itérations à
effectuer.

– REP MOVS copie CX éléments de la chaine pointée par SI vers la chaine pointée par ES:DI
– REP LODS charge CX éléments de la chaine pointée par SI dans AL (ou AX)
– REP STOS écrit CX éléments de la chaine pointée par ES:DI avec la valeur contenue dans AL
(ou AX)
Exemple : Copie un tableau de caractères dans un autre tableau.
Data segment
CHAINE db ’system’ ; chaine source
RES db 6 dup (?) ; chaine cible
Data ends
Code segment
….
lea di, RES ; offset chaine cible
lea si, CHAINE ; offset chaine source
mov cx, 6 ; longueur de la chaine
rep movsb ; copie
….

VI.8 REPE et REPNE


Les préfixes REPE et REPNE ne peuvent préfixer que les instructions CMPS et SCAS.

A. REPE CMPS compare au plus CX éléments de la chaine pointée par ES:DI avec ceux de la
chaine pointée par SI. Les itérations sont poursuivies tant que les éléments des deux chaines
sont égaux (sont différents pour REPNE) et tant que le compteur n’est pas nul. Dès que
l’une de ces conditions n’est plus vérifiée, l’instruction REPE CMPS est terminée

B. REPE SCAS compare au plus CX éléments de la chaine pointée par ES:DI avec la valeur du
registre AL, ou AX selon le cas. Les itérations sont poursuivies tant que les éléments de la
chaine sont égaux (sont différents pour REPNE) à la valeur du registre et tant que le
compteur n’est pas nul. Dés que l’une de ces conditions n’est plus vérifiée, l’instruction
REPE SCAS est terminée.

Exemple : Recherche d’un caractère dans une chaine de caractères en utilisant l’instruction SCAS

CHAINE db ‘system’
….
mov al, ’t’
lea di, CHAINE
mov cx,6
repne scasb
...

A l’issue de l’exécution de cette séquence d’instructions, le registre DI pointe sur le caractère qui se
trouve après le ’t’ dans la chaine de caractère, c’est-à-dire ’e’. Puisque l’offset de CHAINE vaut 0,
di vaut 4 à l’issue de l’exécution de repne scasb.
VII. L’accès aux fichiers :
Pour pouvoir accéder aux données d’un fichier, que ce soit en lecture ou en écriture, il faut d’abord
l’ouvrir. A l’ouverture, le programme récupère une poignée. Ensuite, toutes les opérations sur ce
fichier seront effectuées en spécifiant cette poignée.
Les appels ou interruptions pour effectuer les traitements de base sur les fichiers :

VII.1 Ouverture d’un fichier :


L’appel d’ouverture se fait par :
mov ah, 3dh
int 21h

Avant l’appel le registre al contient le mode d’accès : 0 pour lecture, 1 pour l’´ecriture, 2 pour les
deux ;
Et dx pointent sur le nom de fichier. C’est une chaine de caractères terminée par un caractère ASCII
de code 0.

Exemple :
Data segment
nomfichier DB ’blida.txt’, 0
data ends

CODE segment
mov ax,data
mov ds,ax
;
; ouverture du fichier
;
mov al,0 ; accès en lecture
lea dx, nomfichier
mov ah,3dh ; ouverture du fichier
int 21h
…. …

VII.2 Fermeture d’un fichier


L’appel a le format suivant :
mov ah, 3eh
int 21h

Avant l’appel bx contient la poignée du fichier à fermer

Exemple :
….
lea dx, nomfichier
mov ah,3dh ; ouverture du fichier
int 21h

mov bx, ax ; sauvegarde de la poignée

mov ah, 3eh


int 21h
VII.3 Lecture dans un fichier
L’appel a le format suivant :
mov ah, 3fh
int 21h

Avant l’appel :
- bx contient la poignée du fichier
- cx contient le nombre de caractères à lire
- dx contient l’adresse du buffer ou il faut stocker les caractères lus.

Après l’appel :
- ax contient le nombre de caractères lus.

Exemple :
Data segment
nomfichier DB ’blida.txt’, 0
Buffer db 100 dup (?), ’$’
data ends

CODE segment
mov ax,data
mov ds,ax
;
; ouverture du fichier
;
mov al,0 ; accès en lecture
lea dx, nomfichier
mov ah,3dh ; ouverture du fichier
int 21h

mov bx, ax ; sauvegarde de la poignée


lea dx, Buffer

mov cx, 100 ; lecture des 100 caractères suivants du fichier


mov ah, 3fh ; lecture du fichier
int 21h
….

VII.4 écriture dans un fichier


L’appel a le format suivant :
mov ah, 40h
int 21h

Avant l’appel
- bx contient la poignée du fichier
- cx contient le nombre de caractères à écrire ;
- ds:dx pointent sur le buffer contenant les caractères à écrire.

Vous aimerez peut-être aussi