Vous êtes sur la page 1sur 56

Langage assembleur

Imane HALKHAMS

1
Introduction
• Lorsque l'on doit lire ou écrire un programme en langage machine, il est
difficile d'utiliser la notation hexadécimale. On écrit les programmes à
l'aide des instructions en mnémonique comme MOV, ADD, etc. Les
concepteurs de processeurs, comme Intel, fournissent toujours une
documentation avec les codes des instructions de leurs processeurs, et les
symboles correspondantes.
• L'assembleur est un utilitaire qui n'est pas interactif, (contrairement à
l'utilitaire comme debug). Le programme que l'on désire traduire en
langage machine (on dit assembler) doit être placé dans un fichier texte
(avec l'extension .ASM).
• La saisie du programme source au clavier nécessite un programme appelé
éditeur de texte.

2
Introduction
• L'opération d'assemblage traduit chaque instruction du programme source en
une instruction machine. Le résultat de l'assemblage est enregistré dans un
fichier avec l'extension .OBJ (fichier objet).

• Le fichier .OBJ n'est pas directement exécutable. En effet, il arrive fréquemment


que l'on construise un programme exécutable à partir de plusieurs fichiers
sources. Il faut (relier) les fichiers objets à l'aide d'un utilitaire nommé éditeur de
lien (même si l'on a qu'un seul). L'éditeur de liens fabrique un fichier exécutable,
avec l'extension .EXE.

• Le fichier .EXE est directement exécutable. Un utilitaire spécial du système


d'exploitation, le chargeur est responsable de la lecture du fichier exécutable, de
son implantation en mémoire principale, puis du lancement du programme.

3
Introduction
• Donc en conclusion pour assembler un programme on doit passer
par les phases suivantes :

- Saisie du code source avec un éditeur de texte.

- Compiler le programme avec un compilateur.

- Editer les liens pour avoir un programme exécutable.

4
Pourquoi faire de l'assembleur ?
• Ecrire un compilateur
• Environnements embarqués, micro-controlleurs
• Systèmes temps-réels durs
Avantages
• Meilleure compréhension des langages
• Meilleure compréhension des machine

5
La machine
• Deux fonctions
✓ Calculer : rôle du (micro)-processeur
✓ Stocker : rôle de la mémoire
• Langage spécifique
✓ Un langage par processeur, appelé jeu d'instructions
✓ Une référence commune : le binaire

6
Processeur: Registres
• Mémoires de calcul
✓ Les calculs se décomposent en opérations élémentaires
✓ Ces opérations ont besoin de stocker des résultats intermédiaires
✓ Le processeur contient de petites mémoires appelées registres
• Registres sur 8086
✓ 8 Registres généraux (16 bits)
▪ ax, bx, cx, dx, si, di, bp et sp
✓ 4 Registres de segments (16 bits)
▪ cs, ds, es et ss
✓ 2 Registres spéciaux (16 bits)
▪ ip et flags

7
Processeur: Registres
• Sous-registres:
• Les registres A, B, C et D se décomposent en deux sous-registres de 8
bits chacun
• h (partie haute) et l (partie basse).
• Par exemple, ax se décompose en ah et al

8
Structure de la mémoire
• La mémoire se comporte comme un grand tableau d'octets

• Accéder à la mémoire consiste à accéder à une case du tableau en indiquant son


indice, appelé adresse

• Un accès mémoire se fait selon une certaine taille : on peut accéder à plusieurs octets
contiguës en une seule fois

▪ On peut lire l'octet situé à l'adresse 123h

▪ On peut écrire deux octets situés à l'adresse 456h


Le premier va dans la case 456h et le deuxième dans la case 457h

9
Les modes d’adressages
• Ce sont les diverses manières de définir la localisation d’un opérande. Les
trois modes d’adressage les plus courant sont :

• Adressage immédiat: On parle de mode d'adressage immédiat lorsque le code


opérande contient une donnée. La taille de la donnée peut varier entre 1 et 2
octets.

• Exemple :
• LDA #$12 charger la valeur $12 dans l’accumulateur A
➔Le symbole ‘#’ signifie immédiat dans la syntaxe assembleur.
• LDX #$E000 charger la valeur $E000 dans le registre d’index X

10
Les modes d’adressages

11
Les modes d’adressages
• Ce sont les diverses manières de définir la localisation d’un opérande. Les
trois modes d’adressage les plus courant sont :

• Adressage direct (ou absolu): Dans ce mode d'adressage, l'adresse de la


donnée en mémoire (RAM, ROM ou port d'E/S s'il est intégré à la mémoire) est
donnée. Dans ce mode, le champ opérande de l'instruction contient l'adresse
effective de l'opérande et on doit faire un accès à la mémoire pour obtenir ce
dernier.

12
Les modes d’adressages

13
Les modes d’adressages

• Adressage indirect: Dans ce mode d'adressage, le champ adresse de


l'instruction ne contient plus l'adresse de l'opérande, mais l'adresse d'une
position mémoire qui, elle, contient l'adresse de l'opérande. Dans ce mode
d'adressage, l'adresse de la donnée se trouve dans un registre spécial du
processeur (le registre BX) (du même nombre de bits que son bus
d'adresses), le pointeur de données. L'avantage, comparé à l'adressage
direct, est que l'adresse peut être manipulée commodément, par exemple
pour accéder à une suite de données consécutives en mémoire. Ceci est
spécifiquement utile quand on manipule des données stockées dans un
tableau.

14
Les modes d’adressages

15
Les modes d’adressages
• Implicite :
• Le mode d'adressage implicite correspond à une instruction ne
comportant pas d'opérande.
• L'instruction est composée du code opération uniquement et sa taille
peut varier entre 1 octet et 2 octets selon l'opération.
• Ex. ADD AX, BX

• Relatif :
• Ce type de mode d'adressage met en jeu un champ opérande
contenant un entier relatif (sa taille est donc un octet).
• On l'utilise pour les opérations de saut, l'entier relatif est appelé
déplacement, il correspond à la longueur du saut que le processeur doit
effectuer dans les instructions.

16
Jeu d'instructions
Instructions:

Les instructions permettent de spécifier les opérations à effectuer. Elles


sont données au processeur sous la forme d'une chaine binaire.
En assembleur, on les écrit sous forme de mnémoniques.
On utilise un programme d'assemblage pour transformer les
mnémoniques en binaire.
La traduction binaire d'un mnémonique est appelée un opcode.

17
Exemples d'instructions

18
Exemples d'instructions

19
Exemples d'instructions
• Quelques instructions:
• L’instruction MOV:
• L'instruction MOV attend deux opérandes, le premier indique la destination du
déplacement de la donnée, le second opérande indique la source.
• La destination peut être un registre, une adresse mémoire ou un registre de
segment (sauf pour le registre CS qui ne peut jamais être une destination).
• La source peut être un registre, une adresse mémoire, un registre de segment ou
une valeur immédiate.

20
Exemples d'instructions
• Le tableau ci-dessous inventorie quelques les manières d'utiliser l'instruction
MOV:

r1 reçoit la valeur identique à celle contenue


MOV r1 , r2
dans r2
Le registre r est initialisé avec une valeur
MOV r , i
immédiate
MOV m , i Ecriture d'une valeur immédiate en mémoire
MOV m , r Ecriture en mémoire à partir du registre r
Echanges entre registres généraux et registres de segment
MOV s , r
MOV r , s

21
Exemples d'instructions
• D’autres instructions:
• Les instructions MOV ont été utiles pour illustrer les modes d'adressage mais
avec les MOV il est juste possible de déplacer les données d'un endroit à l'autre. Il
faut d'autres instructions pour faire des opérations arithmétiques et logiques, des
sauts, des appels à des fonctions, à des interruptions etc. Voici donc quelques
instructions:
• Opérations arithmétiques et logiques élémentaires : ADD SUB CMP AND
TEST OR XOR
* TEST: Cette instruction permet d'effectuer un «Et binaire» sur une opérande cible
sans modifier sa valeur et définit les drapeaux d'état SF, ZF et PF en fonction du
résultat.

22
Exemples d'instructions
• Multiplications et divisions: MUL IMUL DIV IDIV
• Exemples : MUL BYTE PTR Valeur AX := AL x Valeur
DIV BYTE PTR Valeur AL := AX / Valeur
• Incrémentation, décrémentation, inversion logique, négation: INC DEC NOT NEG
• Appel d'un sous-programme : CALL label
• Sauts inconditionnels: JMP label
• Sauts conditionnels : JZ (=JE) JNZ ( = JNE) JC JNC JS JNS (voir diapo suivante)

*NEG: Cette instruction permet d'effectuer le complément à 2 d'une opérande.

23
Sauts (Branchements)
• On appelle saut (ou branchement) en assembleur le fait de passer à une instruction
autre que celle qui suit celle en cours en mémoire. En effet, en temps normal (c'est-
à-dire sans instruction contraire) le processeur exécute les instructions
séquentiellement, il exécute l'instruction située à l'emplacement mémoire suivant.
• C'est le registre spécial (le registre IP) qui indique l'adresse de l'instruction suivante à
exécuter. Dans certaines conditions il peut être intéressant de « choisir » la
prochaine instruction à effectuer.
• Ce type de condition peut notamment se rencontrer dans les structures
conditionnelles (saut si...) ou bien dans les structures de boucle (en effet dans le cas
où on désire exécuter un grand nombre de fois une instruction il peut être
intéressant d'utiliser une instruction de branchement, qui indique au processeur
l'adresse de la prochaine instruction à exécuter au lieu de gaspiller la mémoire en
stockant plusieurs fois la même instruction en mémoire).

24
Sauts (Branchements)
• Lors de l'exécution « normale » d'un programme, le processeur lit l'adresse contenue
dans le registre IP, incrémente celui-ci pour qu'il pointe vers l'instruction suivante,
puis exécute l'instruction contenue à l'adresse qu'il vient de lire. Lorsqu'il rencontre
une instruction de saut (ou branchement), celle-ci va lui faire modifier le contenu du
registre IP pour qu'il pointe à l'adresse d'une autre instruction.
• On distingue ces instructions de saut en deux catégories suivant que :
✓ le saut est effectué quoi qu'il arrive (saut inconditionnel)
✓ le saut est effectué ou non selon l'état d'un registre (saut conditionnel)

25
Sauts (Branchements)
• Saut inconditionnel
• L'instruction JMP permet d'effectuer un saut inconditionnel, c'est-à-dire que cette
instruction va stocker dans le registre IP l'adresse de l'instruction que l'on veut
exécuter. L'opérande de cette instruction (le paramètre) est donc l'adresse de
l'instruction à laquelle on veut sauter. Une fois l'instruction de branchement
exécutée le processeur lit le contenu du registre IP et saute donc directement à
l'adresse de l'instruction que l'on vient de définir.
La taille de l'instruction JMP est de 1 bit.
• On appelle déplacement (en anglais offset) le nombre d'octets (car il s'agit d'un
nombre entier relatif codé sur 8 bits) qui séparent l'instruction suivante de
l'instruction visée.

26
Sauts (Branchements)
• Saut inconditionnel
Voyons cela sur le programme suivant :

Adresse Instruction en assembleur Commentaire


copie le contenu de la case mémoire à l'adresse 0120H
0100 MOV AX, [120]
dans le registre AX
0103 JMP 0100H saute à l'adresse 0100H
0104 MOV [120], BX instruction non exécutée à cause du saut précédent...

La valeur du déplacement est ici de: 0100H - 0104H = -4

27
Sauts (Branchements)
• Saut conditionnel
• Les instructions de saut conditionnel permettent d'effectuer un saut suivant une
condition. Si celle-ci est réalisée le processeur saute à l'instruction demandée, dans
le cas contraire il ignore cette instruction et passe automatiquement à l'instruction
d'après, comme si cette instruction n'existait pas.
• Les conditions pour chacune de ces instructions sont fonction de l'état des registres
spécifiques appelés indicateurs (en anglais flag, ce qui signifie drapeau).

28
Sauts (Branchements)
• Saut conditionnel
• Les indicateurs: Ce sont des registres dont l'état est fixé par l'UAL après certaines
opérations. Les indicateurs font partie de ce que l'on appelle le registre d'état qui n'est
pas directement accessible par les autres instructions, seules des instructions
spécifiques permettent de les manipuler. Voyons certains de ces indicateurs :
• CF (Carry Flag) : c'est l'indicateur de retenue. Il intervient lorsqu'il y a une retenue après
une addition ou une soustraction entre des entiers naturels. Lorsqu'il y a une retenue il
est positionné à 1, dans le cas contraire à 0.
• OF (Overflow Flag) : cet indicateur (indicateur de débordement : overflow =
débordement) intervient lorsqu'il y a un débordement, c'est-à-dire lorsque le nombre de
bits sur lesquels les nombres sont codés n'est pas suffisant et que le résultat d'une
opération n'est pas codable avec le nombre de bits spécifiés (il peut par exemple arriver
dans ces conditions que la somme de deux nombres positifs donne un nombre négatif).
Dans ce cas l'indicateur OF est positionné à 1.
29
Sauts (Branchements)
• Saut conditionnel
• SF (Sign Flag) : c'est l'indicateur de signe. SF donne tout simplement le signe du bit de
poids fort. Or, le bit de poids fort donne le signe du nombre (1 si le signe est négatif, 0
s'il est positif). Il simplifie le test du signe d'un entier relatif.
• ZF (Zero Flag) : l'indicateur de zéro permet de savoir si le résultat de la dernière
opération était nul. En effet, dans ce cas, l'indicateur ZF est positionné à 1 (0 dans le cas
contraire). Il permet notamment de déterminer si deux valeurs sont égales, en
effectuant leur soustraction, puis en observant l'état de l'indicateur de zéro.

30
Sauts (Branchements)
• Saut conditionnel
Voyons les états de ces indicateurs sur un exemple :

•OF=1 (la somme de deux nombres positifs est négative)


•ZF=0 (le résultat 1011 n'est pas nul)
•SF=1 (le signe du résultat est négatif)
•CF=0 (il n'y a pas de retenue)
0 1 1 0
+ 0 1 0 1
- - - -
1 0 1 1

31
Sauts (Branchements)
• Instruction de comparaison
• L'instruction CMP permet de tester la valeur d'un registre (AX) avec une autre valeur.
Sa seule action est de positionner l'indicateur ZF à 1 en cas d'égalité, ou plus
exactement lorsque la soustraction des deux valeurs donne un résultat nul. En ce
sens il effectue la même chose que SUB à la seule différence près qu'il ne modifie
pas les opérandes.
• Par exemple, l'instruction :
CMP AX, 2
positionne à 1 l'indicateur ZF si la valeur contenue dans le registre AX vaut 2, dans le
cas contraire il le met à zéro.

32
Sauts (Branchements)
• Instruction de comparaison
• Les sauts conditionnels
• Les branchements conditionnels (ou sauts conditionnels) permettent au processeur
de traiter l'instruction située à un emplacement mémoire indiqué si une certaine
condition est vérifiée. Dans le cas contraire (condition non réalisée), le processeur
ignorera cette instruction, il traitera donc l'instruction suivante.
• La (ou les) condition(s) à satisfaire dépend(ent) de l'état d'indicateurs. Ainsi les
branchements conditionnels doivent généralement être placés après une opération
qui va modifier l'état d'un ou plusieurs indicateurs (une instruction CMP ou autre).

33
Sauts (Branchements)
• Selon l'intitulé de l'instruction, les conditions à satisfaire sont différentes :
• JA (Jump if above, ce qui signifie saute si au-delà)
effectue un saut si ZF=0 et CF=0
• JB (Jump if Below, ce qui signifie saute si en deçà)
effectue un saut si CF=1
• JBE (Jump if Below or Equal, ce qui signifie saute si en deçà ou égal)
effectue un saut si ZF=1 ou CF=1
• JE (Jump if Equal, ce qui signifie saute si égalité)
effectue un saut si ZF=1
• JG (Jump if Greater, ce qui signifie saute si supérieur)
effectue un saut si ZF=0 et SF=OF
• JLE (Jump if Lower or Equal, ce qui signifie saute si inférieur ou égal)
effectue un saut si ZF=1 ou SF différent de OF
• JNE (Jump if Not Equal, ce qui signifie saute si non-égalité) 34
effectue un saut si ZF=0
Les piles (Stack)
• En informatique, nous pouvons utiliser une pile pour y stocker n’importe quel
objet. L’intérêt d’une pile est qu’elle constitue une structure où l’accès à un objet
est uniquement réalise sur le dernier objet empilé (comme pour une pile
d’assiettes, on prend la dernière assiette posée sur la pile).
• En termes de programmes, quand un appel de sous-programme est effectué, on
doit sauvegarder l’adresse de retour.
• Plaçons-la sur une pile. Si ce sous-programme fait lui-même appel à un autre
sous-programme, plaçons également l’adresse de retour sur la pile (c’est-`a-dire,
au-dessus de l’adresse de retour empilée précédemment).

35
Les piles (Stack)
• Quand ce sous-programme termine son exécution, consultons le sommet de la
pile : elle contient l’adresse de retour de sous-programme. Dépilons-la et
continuons l’exécution du programme à cette adresse.
• Quand ce sous-programme termine également son exécution, consultons à
nouveau le sommet de la pile ; elle contient l’adresse de retour de ce sous-
programme. Si nous la dépilons et que nous reprenons l’exécution du programme
à cette adresse, nous serons revenus dans le premier programme appelant. Nous
pouvons maintenant itérer le processus et avoir des sous-programmes qui
appellent des sous-programmes qui appellent des sous-programmes.
• Le retour de sous-programme est réalisé simplement en dépilant le sommet de la
pile et en plaçant cette valeur dépilée dans le registre IP.

36
Les piles (Stack)

37
Segment de mémoire
• Un modèle de mémoire segmentée divise la mémoire système en groupes de segments
indépendants, référencés par des pointeurs situés dans les registres de segment.
• Chaque segment est utilisé pour contenir un type de données spécifiques:
• Segment stack: pour garder la pile du program.
• segment data: pour stocker les éléments de données
• Segment code: contient les instruction codes

38
Segment stack
• Segment stack:
• représenté par .stack
• il définie un endroit de mémoire qui stockes les codes d’instructions. Cette
partie est aussi fixe.
• Il contient aussi les données passées en fonctions ou procédures dans le
programme.

39
Segment data
• Segment data:
• Il est représenté par .data
• Il permet la déclaration des données (variables) et la mémoire ou elles sont
stockées en mémoire pour être utilisées en programme.

• Exemple: les variables sont val1, val2, st1


.data
val1 db 30
val2 db 10
st1 db "hello world","$"

40
Les variables
• Les noms de variables (étiquettes) peuvent être de 1 à 31 caractères
de longueur et peuvent se composer de lettres, chiffres et caractères
spéciaux comme ? . @ _ $ %
• Les noms de variables ne peuvent pas commencer par un chiffre
• L’Assembleur n’est pas sensible à la casse (MOV ou mov sont les
mêmes)

41
Les variables
• Exemples de noms de variables correctes
• COUNTER1
• @character
• SUM_OF_DIGITS
• $1000
• DONE?
• .TEST
• Exemples de noms de variables incorrectes
• TWO WORDS contains a blank
• 2abc begins with a digit
• YOU&ME contains an illegal character

42
Segment code
• segment code
• représenté par .code
• Il définit un endroit en mémoire qui stocke les codes d’instructions.
• Exemple:
.code ;;au moins une procédure a écrire
main proc
.startup ;;début du programme
mov dx, offset string
mov ah, 09h ;;cherche le contenu du registre dx
int 21h ;; Arrêt et affichage du contenu du registre
.exit
main endp
43
Exemple1: Hello world
org 100h
.model small
.stack ;how much memory was allocated by default 1024B
.data ; data we want to specify
string db "hello world","$ " ;string is the variable, $ obligatory at the end
.code ;at least one procedure to be written
main proc
.startup ;directory to start the program
mov dx, offset string
mov ah, 09h ;always seek for the content of the dx register
int 21h ;affichage
.exit
main endp
end

44
Exemple1: Hello world

45
La directive DB
• [nom] DB constante [, constante]
• Reserve et initialise un octet (8 bits).
• nom est un symbole permettant d’accéder a cet octet.
• Par exemple, les 4 lignes suivantes :
OCTET DB 36 ;;constante octet contenant 36
DEUX_OCTETS DB 43, 26 ;;donnée codée sur un octet dont la valeur sera
initialisée a 43, l’octet suivant étant initialise avec 26. On peut considérer
que DEUX_OCTETS reférence un tableau de 2 octets ;
LETTRE DB ’e’ ;;constante lettre contenant e
CHAINE DB ’hello world !’, 13, 10, ’$’ ;;13 indique le retour au debut de la
ligne, 10 indique la ligne suivante, $ fin de chaine de caractere CHAINE
TABLEAU DB 10 dup (0) ;;un tableau nommé TABLEAU de dimension 10
initialisé a 0
46
La directive DW
• [nom] DW constante [, constante]
• Reserve et initialise un mot (16 bits). nom est un symbole permettant d’accéder a ce mot.
Ainsi, les lignes suivantes définissent :
MOT DW 1559
TMOT DW 20 DUP (0)

• Le symbole MOT qui référence une donnée codée sur un mot (Word) et qui sera initialisée
avec la valeur 1559 ;
• Le symbole TMOT qui référence un tableau de 20 mots initialises avec la valeur 0

47
Types de données numériques
• Décimale -100
• Binaire-100b
• Hexadecimale-100h
• ASCII-‘100’ ou " 100 "

48
Les tableaux
• Nom_tableau DB vl1, val2, val3, ….

• Exemple:
• Tab DB 2,4,6,8,9
• Tab[bx]

49
Les boucles (LOOP)
Next
Instructions
.
.
.
instructions
Incrementation/decrementation du compteur (ex: Inc bx, dec bx)
Loop next

50
Les Conditions
• Pour exprimer une condition on effectue une comparaison puis une action
• CMP: comparaison
• Exemple:
CMP AL,BL
JNBE cas1 ;cas ou AL n’est pas inferieur ou égale a BL (AL>BL)
MOV DL,AL
JMP DISPLAY
cas1:
instructions
DISPLAY:
instructions

51
Les Interruptions
• Les interruptions sont en quelque sorte des services de type matériel
(BIOS) ou logiciel .
• On retrouve un ensemble de services de tout genre: affichage,
horloge, clavier, souris, gestion des fichiers, gestion de la mémoire,...
• Pour appeler une interruption manuellement, on utilise le mnemonic
INT avec comme seule opérande le numéro de l'interruption.

52
Les Interruptions

53
Les Interruptions

54
Exemples:
1Dh = paramètres vidéo
01h =mode pas à pas
02h = erreur mémoire 1Eh = paramètre disquette
03h = point d'arrêt 1Fh = caractères graphiques vidéo
04h = dépassement de capacité 20h = routine de terminaison
05h = impression d'écran
21h = appel à MSDOS
08h = mise à jour du compteur d'heure
09h = gestion du clavier 22h = adresse de la routine de terminaison
10h = routine de gestion vidéo 23h = adresse de la routine de gestion du Ctrl + C
12h = détermination de la mémoire disponible 24h = adresse de la routine de gestion des erreurs critiqu
13h = gestion des unités de disque
14h = gestion du port série 25h et 26h = lecture et écriture absolue sur disque
16h = gestion du clavier 27h = installation d'un programme en mode résident
17h = gestion de l'imprimante 28h = MSDOS en attente
19h = redémarrage de l'ordinateur
2Fh = impression en tâche de fond (spooler)
1Ah = gestion de l'heure et de la date
1Bh = gestion du Ctrl-Break 33h = gestion de la souris
1Ch = incrémentation de l'heure 41h et 42h = paramètres des disques durs 55
Utilisation de AH
• On utilise AH plutôt que AX car AL est souvent utilisé pour passer un
paramètre à la fonction appelée.
• Pourquoi AX plutôt que BX ?
• Car AX est l'accumulateur le plus indiqué à l'origine pour passer et
recevoir des valeurs.
• ex.: ah est le code fonction qui sera utilisé par l'interruption 21 -
Système MS-DOS.

ah = 01 => Lecture au clavier (mov ah,1)


ah = 09 => Affichage d'une chaîne de caractère (mov ah,9)
ah=02=>affichage d’un résultat en dl
Pour les différentes opérations, il est essentiel de commencer par le
registre AX.
56

Vous aimerez peut-être aussi