Sommaire
1. Déclaration de variables
2. Traitement tableaux et chaines de caractères
3. Vecteurs d’entiers
4. Tableaux a deux dimensions (matrices)
5. Les entrées sorties en ASM (interruptions)
6. L’équivalent de quelques instructions du langage C en
assembleur
7. Quelques instructions de base
8. Comparaison
9. Mode d’adressage
10. Quelques remarques
11. Les piles
Manuel
Déclaration de variables
Les variables se déclarent comme suit:
donnee1 db ? ; donnee1 est un byte (octet) non initialisé
donnee2 db 0FFh ; donnee2 est un byte initialisé à FF (255 en hexadécimal)
donnee3 dw ? ; donnee3 est un word (16 bits)
donnee4 db 5 dup (?) ; donnee4 est un tableau de 5 bytes (octets) non initialisés
donnee5 dw 10 dup (15) ; donnee5 est un tableau de 10 byte (octets) initialisés à 15
De manière générale:
DB : 1 byte (8 bits) (Declare Byte)
DW : 1 word (16 bits) (Declare Word)
DD : 2 words (32 bits) (Declare Double)
Les constantes peuvent être écrites en:
- décimal: 1, 2, 3, 123, 45
- hexadécimal : 1h,2h,3h,12h,0Fh,0AD4h (noter la présence du 0 quand le le premier
chiffre du nombre en hexadécimal commence par une lettre)
- binaire : 1b,0b,1010b,111101b
Traitement des tableaux et chaînes de
caractères
Une chaîne de caractères ASCII est constiuée d’une suite de caractères
terminée par le ‘$’. Ce type de caractères est utilisé par le MS DOS. Une
chaîne de caratères ASCII se déclare à l’aide de la directive DB
Exemple:
mesg DB ‘bonjour$’
Message DB 'Bonjour$' est la même chose que
Message DB 'B', 'o', 'n', 'j', 'o', 'u', 'r', '$' ou que
Message DB 66, 111, 110, 106, 111, 119, 114, 36
La seule obligation est le caractère '$' qui indique la fin de la chaîne (sinon
les octets situés à la suite du message en mémoire sont aussi affichés
comme caractères).
Zone DB 30 DUP(?), ‘$’; chaîne de 30 caratères de valeur non définie
Tamp DB 25 DUP (‘ ‘); chaîne de 25 espaces blancs
Les registres SI, DI, BX peuvent être utilisés pour
accéder aux éléments d’une chaîne.
• La déclaration d’une chaîne de caractères est mise en
'' '' ou ' ' .
• Le caractère '$' indique la fin d’une chaîne de caractères. Son omission
implique que les octets en mémoire qui viennent après cette chaîne sont
aussi affichés comme des caractères.
• L’assembleur ne fait pas de différence entre une majuscule et une
minuscule dans l’écriture de ses instructions et la notation des registres.
Vecteur d’entiers
Le principe est le même pour un vecteur d’entiers où chaque élément est stocké
sur un entier. Pour un vecteur d’entiers stockés sur deux octets nous devons tenir
compte de la longueur d’un élément du vecteur.
Exemple:
T dw 1, 4, 7,-1; vecteur de 4 entiers initialisés respectivement
; aux valeurs 1, 4, 7 et -1
T1 dw 100 dup (?); vecteur de 100 éléments non initialisés.
Il est impossible d'affecter une variable directement à une
autre variable, il faut obligatoirement passer par un
registre.
Il est également impossible d'affecter une constante
directement à une variable, il faut également passer par
un registre.
…………………………………………………………………………………………………………………………
Tableau à deux dimensions
• Pour représenter un tableau de taille nxm, je réserve n*m
bytes (ou word ..) :
N EQU 12
M EQU 32
tableau DB N*M DUP (?)
• J ’accède à l ’élément (i,j) :
MOV SI,i
MOV DI,j
MOV AL,tableau[SI*M+DI]
……………………………………………………..
Affectation d’une adresse d’un tableau ou chaine de caractère
Mov registre, offset tab
Ou bien
Lea registre, tab
Mov registre(par exemple BX),offset (veut dire adresse) tab(le tableau)
Lea (instruction de chargement d’adresse) registre, tab (le tableau « il
ne faut pas mette offset »)
Les entrées Sorties en assembleur
Pour réaliser les opérations standards (affichage, saisie), le système d’exploitation
(ici DOS) fournit les fonctions pré-écrites suivantes:
Affichage d’un caratère: mov DL, “A”; caractère A est transfére dans DL
mov AH, 2; fonction no. 2
int 21h ; appel au DOS
Affichage d’une chaine de caractères:
mov DX, offset chaine; pointe vers l’adresse du premier
caractère de la chaîne de caractères chaine
mov AH, 09h; fonction no. 9
int 21h;
Saisie d’un caratère:
mov AH, 01h; fonction no. 1 (avec écho)
int 21h ; résultat est mis dans AL
Saisie d’un caractère
mov AH, 07H; fonction no. 7 (sans écho) (sans écho=veut dire sans affichage a
l’ecran (non visible))
int 21h ; résultat dans AL
Arrêt de programme: (retoure au DOS)
mov AX, 4C00h;
int 21h;
À mettre à la fin de chaque fin programme; c’est l’équivalent du
return (0) en C. Ces instructions ont pour effet de retourner au DOS
L’équivalent de quelques instructions du langage C en
assembleur
• if then else Assembleur
If ax =1 if: CMP AX, 1
bx = 10; JNZ Else
else {
bx = 0; Then: MOV BX,10
cx = 10; JMP endif
} Else: MOV BX,0
MOV CX,10
endif: ..............
• La boucle FOR Assembleur
For (k=0; k<=10; k++) MOV BX,0
bx = bx + k; MOV CX,0
For: CMP CX,10
JA Endfor
ADD BX,CX
INC CX
JMP For
Endfor:
WHILE Assembleur
bx = 5 MOV BX,5
while (bx >0) while: CMP BX,0
bx = bx -1; JLE Endwhile
DEC BX
JMP while
Endwhile:
Écrire le code de l’instruction En assembleur
if (a>b) && (c <= d) if: cmp a, b
{ jng endif
................
} cmp c, d
jnle endif
..............
endif:
Quelques instructions de base
• Affectations
; Registres <-- Valeurs
MOV AX, 65535 ; (décimal)
MOV Cl, 01101b ; (binaire)
MOV DH, 0FAh ; (hexa)
; Entre registres
MOV AX, BX
MOV CL, DH
; Entre Registres et Variables
MOV CX, variable_de_deux_octets
MOV variable_de_un_octet, DL
;Registres <-- Adresses Mémoire
Mov AX, Offset variable ; AX <- adresse de variable
Mov CX, [ 5Ah ] ; CX <- valeur à l'adresse 5A en hexa
Quelques instructions de base
• Arithmétique
; Incrémentation
INC AX ; AX <- AX + 1
Inc ma_variable
; Décrémentation
DEC AX
Dec ma_variable
; Addition
ADD AX, 5 ; AX <- AX + 5
ADD BH, t ; BH <- BH + t
Add t, Cx ; t <- t+ Cx
; Soustraction
SUB AX, 5 ; AX <- AX – 5
SUB BH, t ; BH <- BH – t
SUB t, CX ; t <- t - CX
Quelques instructions de base
• Logique
; AND bit à bit
MOV AH, 0101b ; AH <- 5
MOV BH, 1001b ; BH <- 9
AND AH, BH ; AH <- AH AND BH; AH vaut 0001b, soit 1
; OR bit à bit
MOV AH, 0101b ; AH <- 5
MOV BH, 1001b ; BH <- 9
Or AH, BH ; AH <- AH OR BH; AH vaut 1101b, soit 13 (8+4+1)
; XOR bit à bit
MOV AH, 0101b ; AH <- 5
MOV BH, 1001b ; BH <- 9
XOR Ah, BH ; AH <- AH XOR BH; AH vaut 1100b, soit 12 (8+4)
; NOT bit à bit
MOV AH, 0101b ; AH <- 5 Not AH ; AH <- NOT AH; AH vaut 1010b, soit
10 (8+2)
Comparaison:
; Egalité (Jump if Equal)
CMP AX, 5
JE label_1 ;label_1==etiquette
; Différence (Jump if Not Equal)
CMP AX, ma_variable
JNE label_2
;Inférieur, Supérieur, Inf. ou égal, Sup. ou égal
; (Jump if Lower, Greater, Lower or Equal, Greater or Equal)
CMP CH, 0
JL label_1
CMP DH, Ah
JG label_2
CMP AL, 01001b
JLE label_3
JZ Saut si zéro. JNZ
JE Saut si égal. ZF = 1 JNE
JC Saut si Retenue (inférieur). JNC
JB Saut si inférieur. JNB
JNAE Saut si ni supérieur ni égal. CF = 1 JAE
JS Saut si signe négatif. SF = 1 JNS
JO Saut si débordement. OF = 1 JNO
JPE Saut si parité paire.
JP Saut si parité. PF = 1 JPO
JNZ Saut si pas zéro. JZ
JNE Saut si différent. ZF = 0 JE
JNC Saut si pas de retenue. JC
JNB Saut si pas inférieur. JB
JAE Saut si supérieur ou égal. CF = 0 JNAE
JNS Saut si aucun signe (positif). SF = 0 JS
JNO Saut si pas de débordement. OF = 0 JO
JPO Saut si parité impaire. JPE
JNP Saut si pas de parité. PF = 0 JP
Modes d’adressage
• Mode immédiat
L’opérande est codée avec l’instruction
mov AX, 568
• Mode registre
L’opérande est un registre de donnée ou d’adresse
mov AX,BX
• Mode mémoire direct
L’opérande est désigné par l’adresse donnée dans l’instruction
mov [adresse],AL
Modes d’adressage pour accéder aux données
• Mode mémoire indirect
L’opérande est désignée par une adresse placée dans les registres d’adresses
donnée dans l’instruction
mov AX,[SI] BX,BP,SI,DI peuvent servir de registre
pointeur
1. Indirect avec déplacement
L’adresse = contenu du registre d’adresse + déplacement (le registre d’adresse
n’est pas modifié)
mov AX, [DI]
mov BX,[DI+6]
Indirect avec index
L’adresse = contenu du registre d’adresse + contenu du registre d’index (le
registre d’adresse n’est pas modifié)
mov [BP][DI],AX
les couples possibles sont BP-DI,
BP-SI, BX-DI, BX-SI
Quelques remarques
La directive ASSUME permet d'indiquer à l'assembleur où se situe le segment de
données et le segment de code. Puis il s'agit d'initialiser le segment de données à
l’intérieur du segment de code:
MOV AX, nom_du_segment_de_donnees
MOV DS, AX
On peut transcrire une boucle à l’aide de l’instruction LOOP nécessitant
l’utilisation implicite du registre CX.
MOV CX, val ;initialisation du cx=contient le nombre d’iterations
Boucle:
…… ; le corps de la boucle
LOOP Boucle ;cx est automatiquement décrémenté (grace a « loop »,
cependant il doit être initialisé comme dans cet exemeple )
Cela signifie que le corps de la boucle est exécuté tant que la valeur de CX n’est
pas nulle. A chaque itération, CX est décrémenté d’une unité.
Exemple :
En C
for (cx=5; cx>0; cx--)
ax = ax + cx
En Assembleur
MOV AX,0
MOV CX,5 ; CX est le compteur de boucle
for:; for==label de l’etiquette (on peut mettre ce qu’on veut come label)
ADD AX,CX ; fait le calcul
LOOP for ; décrémente d’une unité CX.
; si CX > 0 fait le saut à for
« ; » permet d’écrire un commentaire en ASM
On peut aussi utiliser LOOPE/LOOPZ/LOOPNE/LOOPNZ pour signifier :
a.LOOPE (« Loop while Equal ») Monlabel
Décrémente CX, puis, si CX <> 0 et ZF = 1, fait un saut à MonLabel.
Mnémonique équivalent : LOOPZ
b. LOOPNE (« Loop while not Equal ») Monlabel
Décrémente CX, puis, si CX <> 0 et ZF = 0, fait un saut à
• MonLabel.
La directive EQU
La directive EQU a un rôle voisin de celui des macros. Elle permet de remplacer
un simple mot par d’autres plus complexes. Son intérêt est qu’elle peut être
invoquée en plein milieu d’une ligne.
Exemple :
Longueur EQU (fin – debut)
Message EQU “Bonjour messieurs ! Comment allez-vous ?”, ‘$’
Version EQU 2
Quitter EQU ret
Quitter2 EQU int 20h
Mettre_dans_AH EQU mov ah,
Interruption_21h EQU int 21h
La pile
• Utilité d'une pile
Une pile est une zone de mémoire dans laquelle on peut stocker temporairement des
registres. Il s'agit d'un moyen d'accéder à des données en les empilant, telle une pile de
livre, puis en les dépilant pour les utiliser. Ainsi il est nécessaire de dépiler les valeurs
stocker au sommet (les dernières à avoir été stockées) pour pouvoir accéder aux valeurs
situées à la base de la pile.
En réalité il s'agit d'une zone de mémoire et d'un pointeur qui permet de repérer le
sommet de la pile.
La pile est de type LIFO (Last In First Out), c'est-à-dire que la première valeur empilée
sera la dernière sortie (Si vous empilez des livres, il vous faudra les dépiler en
commençant par enlever les livres du dessus. Le premier livre empilé sera donc le
dernier sorti!).
• Les instructions PUSH et POP
Les instructions PUSH et POP sont les instructions qui servent à empiler et dépiler
les données.
- PUSH registre met le contenu du registre dans la pile (empilement)
- POP registre récupère le contenu de la pile et le stocke dans le registre (dépilage
Ainsi, l'instruction
PUSH BX
empile le contenu du registre BX,
et l'instruction
POP AX
récupère le contenu du sommet de la pile et le transfère dans AX.
Exemple :
Utilisation de la pile sur un exemple
• Dans l'exemple suivant, que l'on imaginera au milieu d'un programme, on
stocke les valeurs contenues dans AX et BX pour pouvoir utiliser ces deux
registres, puis une fois l'opération accomplie on remet les valeurs qu'ils
contenaient précédemment...
• PUSH AX
• PUSH BX
• MOV AX, [0140]
• ADD BX, AX
• MOV [0140], BX
• POP BX
• POP AX
• Les registres SS et SP Les registres SS et SP sont deux registres servant à
gérer la pile:
• SS (Stack Segment, dont la traduction est segment de pile) est un registre 16
bits contenant l'adresse du segment de pile courant.
• Il doit être initialisé au début du programme
• SP (Stack Pointer, littéralement pointeur de pile) est le déplacement pour
atteindre le sommet de la pile (16 bits de poids faible).
• SP pointe vers le sommet, c'est-à-dire sur le dernier bloc occupé de la pile.
Lorsque l'on ajoute un élément à la pile, l'adresse contenue dans SP est
décrémentée de 2 octets (car un emplacement de la pile fait 16 bits de
longueur).
• En effet, lorsque l'on parcourt la pile de la base vers le sommet, les adresse
décroissent.
Par contre l'instruction POP incrémente de 2 octets (16 bits) la valeur de
SP.
• PUSH: SP <- SP - 2
• POP: SP <- SP + 2
• Ainsi, lorsque la pile est vide SP pointe sous la pile (la case mémoire en-
dessous de la base de la pile) car il n'y a pas de case occupée. Un POP
provoquera alors une erreur...
Déclaration d'une pile
Pour utiliser une pile en assembleur, il faut déclarer un segment de pile, et
y réserver un espace suffisant. Ensuite, il est nécessaire d'initialiser les
registres SS et SP pour pointer sous le sommet de la pile. Voici la
déclaration d'une pile de 200 octets :
segment_pile SEGMENT stack ; mot clef stack pour pile
DW 100 dup (?) ; réserve espace
base_pile EQU this word ; etiquette base de la pile segment_pile ENDS
Noter le mot clef ``stack '' après la directive SEGMENT, qui indique à
l'assembleur qu'il s'agit d'un segment de pile.
Afin d'initialiser SP, il faut repérer l'adresse du bas de la pile; c'est le rôle de
la ligne base_pile EQU this word (voir figure suivante).
La déclaration d'une procédure
Etant donnée qu'une procédure est une suite d'instructions, il s'agit de regrouper
les instructions composant la procédure entre des mots clés. L'ensemble de cette
manipulation est appelée déclaration de procédure.
Ces mots clés permettant la déclaration de la procédure sont le une étiquette (qui
représente le nom de la fonction) précédant le mot clef PROC marquant le début
de la procédure, suivi de near (qui signale que la procédure est située dans le
même segment que le programme appelant) et RET désignant la dernière
instruction, et enfin le mot-clé ENDP qui annonce la fin de la procédure. Ainsi une
déclaration de procédure ressemble à ceci:
Etiquette PROC near
instruction1
instruction2
...
RET
Etiquette ENDP
Appel d'une procédure
C'est l'instruction CALL qui permet l'appel d'une procédure. Elle est suivie soit
d'une adresse 16 bits, désignant la position du début de la procédure, ou bien du
nom de la procédure (celui de l'étiquette qui précède le mot clé PROC).
L'appel de la procédure se fera comme suit:
PUSH parametre1 ; où parametre1 correspond à une valeur ou
une adresse
PUSH parametre2 ; où parametre1 correspond à une valeur ou
une adresse
CALL procedure
La procédure commencera par l'instruction suivante:
MOV BP, SP ;permet de faire pointer BP sur le sommet de la
pile
Puis pourra contenir des instructions du type:
MOV AX, [BP] ;Stocke la valeur contenue dans le sommet de
;la pile dans AX, sans dépiler
MOV BX, [BP+2] ;Stocke la valeur contenue dans le mot suivant de la
;pile dans BX (un mot fait 2 octets), sans dépiler