Vous êtes sur la page 1sur 18

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