Chapitre 3.
Techniques de programmation (4 semaines)
Modes d’adressage. Etude du jeu d’instructions. Introduction au traitement programmé (Algorithme,
Organigramme, Structure d’un programme). Programmation en langage assembleur. Gestion de la pile.
Gestion des interruptions.
3.1. Introduction
Un système à base du microprocesseur est développé afin de gérer le monde externe selon un
programme, ce programme qui n’est qu’une suite d’instructions rangées dans la mémoire en langage
machine ou codes binaire, est réalisé en se basant sur un certain nombre de techniques de
programmation qu’il est indispensable de connaitre pour rassurer l’utilisation du microprocesseur d’une
manière efficace. Dans ce chapitre l’étude de programmation prend comme référence le model de la
famille Intel x86
3.2. Les modes d’adressage
Les instructions du programme écrit en langage assembleur sont stockées en mémoire après
assemblage sous forme d’octets ; ces octets sont pointés par le contenu du compteur IP (Instruction
Pointer) par rapport au contenu du registre de segment CS (Code-Segment).
Les données manipulées par les instructions du programme sont aussi des octets, mais elles ne sont
pas toujours disponible immédiatement, c a d, ils ne se trouvent pas toujours dans le même segment
que le programme. Elles sont sélectionnés par une autre quantité binaire de 16 bits appelée adresse
effective (AE) par rapport au contenu du registre segment différent de CS et dépend de la forme de
AE. (Tableau 3.1).
Tableau 3.1 calcul de l’adresse effective et segment de référence
AE Par rapport au
(Adresse Effective) segment
DEP (Déplacement) DS
(BP) Interdit
(BX) DS
(SI) DS
(DI) DS
(BP)+DEP SS
(BX)+DEP DS
(SI)+DEP DS
(DI)+DEP DS
(BP)+(SI) SS
(BP)+(DI) SS
(BX)+(SI) DS
(BX)+(DI) DS
(BP)+(SI) +DEP SS
(BP)+(DI)+DEP SS
(BX)+(SI) +DEP DS
(BX)+(DI) +DEP DS
La structure la plus générale d’une instruction est la suivante : INST op1, op2, L’opération est
réalisée entre les 2 opérandes et le résultat est toujours récupéré dans l’opérande de gauche. Il y a
aussi des instructions qui agissent sur un seul opérande Les opérandes peuvent être des registres,
des constantes ou le contenu de cases mémoire, on appelle ça le mode d’adressage :
Dans la suite on utilisera les abréviations suivantes (tableau 3.2) dans la les déférents modes
d’adressage.
Tableau 3.2 les abréviations utilisées
INST Instruction
R Registre quelconque
Rseg Registre Segment
Roff Registre d’offset
Adr Adresse
[ adr] contenu Mémoire
Off Offset de l’adresse
Im donnée (constante)
Dep déplacement (constante)
Op Opérande
Os Opérande source
Od opérande destination
• Adressage registre (R) : L'opération se fait sur un ou 2 registres (INST R, R ; INST R)
Exp : INC AX : incrémenter le registre AX ; MOV AX, BX : Copier le contenu de BX dans AX
• Adressage Immédiat (IM) : Un des opérandes est une constante : INST R, im, INST taille [adr], im
Exp : MOV AX, 243 : charger le registre AX par le nombre décimal 243 ; ADD AX, 243h : additionner
le registre AX avec le nombre hexadécimal 243.
MOV AX, 0xA243 : Quand le chiffre de gauche du nombre hexadécimal est une lettre, il est
préférable d'utiliser le préfix 0x pour l'hexadécimal
MOV AL, 'a' : Charger le registre AL par le code ASCII du caractère 'a'
MOV AX, 'a' : Charger le registre AH par 00 et le registre AL par le code ASCII du caractère 'a'
MOV AX,'ab' : Charger AH par le code ASCII du caractère 'a' et AL par le code ASCII du
caractère 'b'
• Adressage direct (DA) : Un des deux opérandes se trouve en mémoire. L’adresse effective ou
l’offset est précisé directement dans l’instruction. L’adresse adr doit être placée entre [ ], si le
segment n’est pas précisé, DS est pris par défaut
INST R, [adr] ; INST [adr], R ; INST taille [adr], im
Exp : MOV AX, [243] : Copier le contenu de la mémoire d'adresse DS:243 dans AX
MOV [123], AX : Copier le contenu de AX dan la mémoire d'adresse DS:123
MOV AX, [SS:243] : Copier le contenu de la mémoire SS:243 dans AX
• Adressage indirect (IR) : Un des deux opérandes se trouve en mémoire. L’adresse effective n’est
pas précisé directement dans l'instruction, il se trouve dans l’un des 4 registres BX, BP, SI ou DI et
c’est le registre qui sera précisé dans l’instruction : [Rseg : Roff].
INST R , [Rseg : Roff]
INST [Rseg : Roff] , R
INST taille [Rseg : Roff] , im
Exp : MOV AX, [BX] ; Charger AX par le contenu de la mémoire d'adresse DS:BX
MOV AX, [BP] ; Charger AX par le contenu de la mémoire d'adresse SS:BP
MOV AX, [SI] ; Charger AX par le contenu de la mémoire d'adresse DS:SI
MOV AX, [DI] ; Charger AX par le contenu de la mémoire d'adresse DS:DI
MOV AX, [ES:BP] ; Charger AX par le contenu de la mémoire d'adresse ES:BP
• Adressage Basé (BA) : L’offset se trouve dans l’un des deux registres de base BX ou BP. On peut
préciser un déplacement qui sera ajouté au contenu de Roff pour déterminer l’offset
INST R , [Rseg : Rb+dep]; INST [Rseg : Rb+dep] , R; INST taille [Rseg : Rb+dep] , im
Exp : MOV AX, [BX] : Charger AX par le contenu de la mémoire d'adresse DS:BX
MOV AX, [BX+5] : Charger AX par le contenu de la mémoire d'adresse DS:BX+5
MOV AX, [BP-200] : Charger AX par le contenu de la mémoire d'adresse SS:BX-200
MOV AX, [ES:BP] : Charger AX par le contenu de la mémoire d'adresse ES:BP
• Adressage Indexé (X) : L’offset se trouve dans l’un des deux registres d’index SI ou DI. On peut
préciser un déplacement qui sera ajouté au contenu de Ri pour déterminer l’offset
INST R , [Rseg : Ri+dep]; INST [Rseg : Ri+dep], R; INST taille [Rseg : Ri+dep], im
Exp : MOV AX, [SI] ; Charger AX par le contenu de la mémoire d'adresse DS:SI
MOV AX, [SI+500] ; Charger AX par la mémoire d'adresse DS:SI+500
MOV AX, [DI-8] ; Charger AX par la mémoire d'adresse DS:DI-8
MOV AX, [ES:SI+4] ; Charger AX par la mémoire d'adresse ES:SI+4
•Adressage Basé Indexé (BXI) : l’offset de l’adresse de l'opérande est la somme d'un registre de
base, d'un registre d'index et d'un déplacement optionnel. Si Rseg n'est pas spécifié, le segment par
défaut du registre de base est utilisé :
INST R , [Rseg : Rb+Ri+dep]; INST [Rseg : Rb+Ri+dep], R; INST taille [Rseg : Rb+Ri+dep] , im
Exp : MOV AX,[BX+SI] ; AX est chargé par la mémoire d'adresse DS:BX+SI
MOV AX,[BX+DI+5] ; AX est chargé par la mémoire d'adresse DS:BX+DI+5
MOV AX,[BP+SI-8] ; AX est chargé par la mémoire d'adresse SS:BP+SI-8
MOV AX,[BP+DI] ; AX est chargé par la mémoire d'adresse SS:BP+DI
3.3. Taille des échanges avec la mémoire
La mémoire est organisée en octets.
Quand on fait une instruction entre un registre et une donnée qui se trouve en mémoire, c’est le
registre qui détermine la taille de l’opération. Si le registre est un registre simple (8 bits), l’opération
se fera avec une seule case mémoire.
MOV [adresse], AL donne Adresse AL
Si le registre est un registre double (2 octets), l’opération se fera avec deux cases mémoires
MOV [adresse], AX donne Adresse AL
donne Adresse +1 AH
Quand on fait une opération entre une constante et une case mémoire, il y a ambiguïté, le processeur
ne sait pas s’il faut considérer la constante sur 8 bits ou sur 16 bits. Il faut utiliser les préfixes BYTE
et WORD pour préciser le nombre d’octets á écrire :
MOV BYTE [adresse],4Ah ; On écrit 4A dans la position adresse
MOV WORD [adresse],4Ah ; On écrit 004A, 4A adresse, et 00 adresse+1
3.4. LE jeu d’instructions du 8086
3.4.1 Les instructions de transfert
MOV Od, Os copie l'opérande Source dans l'opérande Destination
MOV R1, R2 copier un registre dans un autre
MOV R, M copier le contenu d’une case mémoire dans un registre
MOV M, R copier un registre dans une case mémoire
MOV R, im copier une constante dans un registre
MOV taille M, im copier une constante dans une case mémoire (taille = BYTE ou WORD)
PUSH Op : Empiler l’opérande Op (Op doit être un opérande 16 bits), elle Décrémente dans un premier
temps SP de 2 avant de Copier Op dans la mémoire pontée par SP.
Exp: PUSH R16; PUSH word [adr].
POP Op : Dépiler l’opérande Op (Op doit être un opérande 16 bits), elle Copie les deux cases mémoire
pointée par SP dans l'opérande Op et ensuite incrémente SP de 2.
Exp: POP R16 ; POP word M.
XCHG Cette instruction permet d’échanger le contenu de deux registres ou un registre et une case
mémoire.
Exemple : XCHG AX, CX ; pas pour les registres segments
XCHG BX, CASE_MEM
3.6.2 Instructions de transfert d’adresse
LEA : Cette instruction charge l’adresse d’un opérande (offset) dans un registre.
Syntaxe : LEA Reg16, Mem16
LEA BX, Table ; charge dans BX l’offset de Table
LEA BX, [Table + SI] ; charge dans BX L’adresse effective Table + SI
LDS : chargement simultané d’un registre et du segment DS
LDS BX, Table ; Charge dans BX offset Table et dans DS le segment
3.6.3 Instructions d’Entrées/Sorties
IN & OUT : Transfert des données pour les périphériques,
IN Accumulateur, Port ; port compris entre 0 et 255 OUT Port, Accumulateur Il est plus commode
de charger l’adresse du port dans DX.
IN AL, DX ; charger un octet dans le registre AL ; OUT DX, AX ; le contenu de AX est sorti par le
port d’adresse DX
3.6.4 Les instructions Arithmétiques
Instructions d’addition
ADD destination, Source : Addition sans retenu de destination+source
ADC destination, source : Addition avec retenu de destination+source
Exp: ADD AX, BX ; AX AX+BX
AAA Ajustement ASCII pour Addition en ASCII
DAA Ajustement Décimal pour Addition en BCD
Exp: ADD AL, 37H
AAA
Instructions de soustraction
SBB Soustraction avec retenue
SUB destination, source : destination destination - source
Exp : SBB AX, BX ; AXAX-BX –CF
SUB AX, BX; AXAX-BX
AAS Ajustement ASCII pour division
Instructions de multiplication
MUL : multiplication non signe du contenu de l’accumulateur par le continu d’un registre ou
d’une case mémoire.
Exp : MUL BX ; DX&AX AX * BX
IMUL : multiplication signée
AAM : correction ASCII de multiplication
Instructions de division
DIV : Réalise la division non signée d’un nombre de 16 bits, contenu dans AX (ou 32bits
contenu dans DX et AX) par le nombre de 8 ou 16 bits. Le quotient est stocké dans AL (ou AX)
et le reste dans AH (ou DX).
DIV BX ; AL (AX/BX) et AH reste (AX/BX)
IDIV : division signe
AAD : Ajustement ASCII pour division
NEG Destination Cette instruction va tout simplement inverser le contenu d'un registre ou
d'une adresse mémoire. Pour cela, elle inverse d'abord tous les bits, et ajoute 1.INC
Destination : Cette instruction incrémente de 1 un registre ou un emplacement mémoire.
Exemple : INC AX I
INC TAB[DI]
DEC Destination Décrémente d’une unité un registre ou une case mémoire.
Exemple : DEC AL
DEC TABLE
CMP Opérande1, Opérande2 Soustrait les deux opérandes. Le résultat de la soustraction
n'est pas sauvé, seuls les indicateurs sont modifiés.
Exemple : CMP AX, 7
Les instructions logiques
AND Opérande1, Opérande2 : Cette instruction est l'équivalant d'une porte ET logique, elle
réalise un ET entre 2 opérandes. Le résultat est placé dans le premier opérande.
Exemple : AND AH, BH
OR Opérande1, Opérande2 : cette porte effectue un OU entre deux opérandes.
Exemple : OR AH, BH
XOR Opérande1, Opérande2 : Cette instruction effectue un OU exclusif.
Exemple : XOR AH, BH
NOT Destination C'est l'équivalent de la porte logique NON, le principe est simple, inverser
tous les bits.
Exemple : NOT AX
TEST Opérande1, Opérande2 : Cette instruction va effectuer un ET logique, mais le résultat
ne sera pas gardé; seul les indicateurs seront modifiés
Exemple : TEST AL, 01010110 B
3.6.5. Les instructions de décalage et de rotation En mode immédiat, seuls les décalages et
rotations de 1 bit peuvent se réaliser. Pour réaliser des décalages ou rotations de plusieurs bits, il
faut explicitement utiliser le registre CL.
SHR (Shift logical Right) Décale à droite de x positions, x contenu dans le deuxième
opérande, les bits entrant sont mis à 0, les bits sortant sont placés successivement dans CF,
sans conservation, celui- ci prend donc la valeur du dernier bit sorti.
Exemple: SHR AH, CL
SHL / SAL (Shift logical Left / Shift Arithmetic Left) Effectue un décalage des bits du
premier opérande, les bits sortant sont insérés dans CF, les bits entrant sont mis à 0.
Exemple : SHL AH, 1
SAR (Shift Arithmetic Right) Cette instruction effectue un décalage vers la droite, le
nombre de positions à décaler est inscrit dans le second opérande. Le bit sortant est mis dans
CF, et le bit rentrant varie en fonction du signe du nombre au départ; si au départ le nombre
était positif, tous les bits entrant seront de 0, sinon, l'inverse. Comme le carry (CF) prend
successivement les valeurs des bits sortant, après cette instruction CF est égal au dernier bit
sorti.
Exemple SAR AH, CL
ROR (ROtate Right) Prèsque le même style que les instructions précédentes, les bits sont
décalés vers la droite, mais, cette fois, le bit sortant est injecté à dans CF et dans le bit de
poids fort.
Exemple : ROR AH, 1
ROL ( ROtate Left) Identique à ROR, mais décale sur la gauche.
Exemple : ROL AL, CL
RCR (Rotate trought Cary Right) Cette instruction agit sur les bits de l'opérande, elle les
décale de x vers la droite. Le bit contenu dans CF prend la position du bit le plus fort, puis CF
prend la valeur du bit sortant. X est la valeur contenue dans le deuxième opérande.
Exemple : RCR AH, CL
RCL (Rotate trought Cary Left) Identique à RCR, mais déplace les bits vers la gauche.
Exemple : RCL AH, 1 4.5.
4.6.6 Instructions de branchement
Les branchements inconditionnels JMP : (Jump) Cette instruction effectue un saut sans
condition. Le saut peut être sur un label, une adresse mémoire, ou un registre.
Exemple : JMP AX ; IPAX
JMP Boucle
INT (Interrupt)
INT active la procédure d’interruption spécifiée par l’opérande de type de l’interruption.
L’adresse de pointeur d’interruption est calculée en multipliant le type d’interruption par 4.
Cette instruction sauvegarde dans la pile les contenus des registres (Flags, CS et IP) et remet
à zéro les flags TF et IF. La routine d’interruption se termine toujours par l’instruction IRET
(Interrupt Return)
CALL Cette instruction permet l’exécution d’une procédure (sous-programme) située en
dehors du programme principal.
- un CALL intra-segment sauvegarde dans la pile le contenu de IP.
- un CALL inter-segment sauvegarde dans la pile le contenu de CS et IP.
Une procédure se termine toujours par l’instruction RET (Return)
Les branchements conditionnels Ces instructions permettent de sauter "une partie d'un
programme" si une condition est vérifiée. Les tableaux suivants donnent la liste des
instructions de saut sur test des nombres signés et non signés
Tableau :8 Test des nombres non signés
Instruction Condition Indicateurs Définition
JA Jump if Above
A> B CF = 0 et ZF = 0 Jump if Not Below or
JNBE Equal
JAE Jump if Above or Equal
JNB A>= B CF = 0 Jump if Not Below
JNC Jump if Not Carry
JBE (CF =1 et ZF=1) Jump if Below or Equal
A < =B Ou
JNA Jump if Not Above
(CF<>ZF)
JB Jump if Below
JC Jump if Carry
A<B CF=1
Jump if Not Above or
JNAE Equal
JE Jump if Equal
A=B ZF=1
JZ Jump if Zero
JNE Jump if Not Equal
A<>B ZF=0
JNZ Jump if Not Zero
Tableau :9 Test des nombres signés
Instruction Condition Indicateurs Définition
JG Jump if
A> B ZF=0 et OF=SF
JNLE Jump if
JGE Jump if
A>= B SF=OF
JNL Jump if
JNG (ZF=1) Jump if
Ou
A < =B (SF<>OF) Jump if
ILE
JNGE Jump if
SF<>OF
JL A<B Jump if
JE Jump if
ZF=1
JZ Jump if
JNE Jump if
A=B ZF=0
JNZ Jump if
4.6.7 les instructions de boucle
LOOP : Cette instruction effectue une répétition tant que CX n'est pas égal à zéro;
celle ci décrémente CX de 1 à chaque saut.
LOOPE / LOOPZ : Cette instruction décrémente le contenu de CX, et provoque un
saut si le flag ZF vaut 1 ET le contenu de CX n’est pas nul (on sort de la boucle si ZF = 0
ou CX =0).
LOOPNE / LOOPNZ : Cette instruction décrémente le contenu de CX, et provoque un
saut si le flag ZF est nul ET le contenu de CX n’est pas nul (on sort de la boucle si ZF = 1
ou CX =0).
Gestion de la mémoire
Le 8086 dispose d’un bus Adresses de 20 bits ce qui permet de gérer un espace mémoire de 2 20 =
1048576 octets = 1MO. Cet espace se présente sous forme de segments. Un segment est un ensemble
de 64KO adjacents, chaque octet est sectionné par le 8086 au moyen d’une Adresse logique définit
par le couple (SR : OR) de deux registres de 16 bits chacun ; un registre de Segment SR à valeur fixe
pour tous les octets du même segment et un autre registre qui contient le déplacement ou offset
(appelé aussi adresse effective) dans ce segment.
La quantité binaire sur 20 bits qui se présente sur le bus d’adresse appelée l’adresse physique de
l’octet sélectionné. Connaissant l’adresse logique (Segment : Offset) l’adresse physique est donnée
par :
Adresse physique = 16 × segment + offset ….(EQU 4.1)
16 bits 4 bits
Segment 0000
20 bits
16 bits
+ Ofsset
Adresse Physique
=
20 bits
L’injection de 4 zéros en poids faible du segment revient à effectuer un décalage de 4 pas vers la
gauche, c’est à dire une multiplication par 24 = 16.
L’espace mémoire total de 1MO est partagé en 4 segments, chaque segment est désigné par l’un parmi
les quatres registre segment : ES, DS, SS ou ES.
Le registre CS est associé par défaut au pointeur d’instruction IP, ainsi la prochaine instruction à
exécuter se trouve à l’adresse logique CS : IP. De même, les registres de segments DS et ES peuvent
être associés à un registre d’index.
Exemple : DS : SI, ES : DI. Le registre de segment de pile peut être associé aux registres de
pointeurs : SS : SP ou SS : BP.
Selon L’équation (EQU 4.1), une même adresse physique peut avoir plusieurs couple d’adresse logique
(Segment : Offset), donc les segments ne sont pas nécessairement distincts les uns des autres, ils
peuvent se chevaucher ou se recouvrir complètement.