Programmation en assembleur 8086

publicité
Microprocesseur 8086 - TD 4
TD 4 : Programmation en assembleur 8086
Exercice 1 :
Ecrire un programme, en langage assembleur 8086, qui permet de compter les nombres nuls
dans un tableau d’octets mémoire de longueur 100h et débutant à l’adresse [200h], le résultat
sera placé à l’adresse [400h].
Solution :
Début
NZ <-- 0
C <-- 1
NON
T(C) = 0 ?
OUI
NZ <-- NZ + 1
C <-- C + 1
NON
OUI
C < N ?
Fin
Exploitation des registres :
Le compteur C sera remplacé par le registre CX, et comme tout le tableau de N octets sera
examiné, donc CX va prendre N valeurs, la toute dernière est toujours égale à 1, donc la
valeur initiale sera N :
CX = N, N-1, N-2, ... 2, 1.
Lorsque CX est initialisé à N, La valeur actuelle du tableau mémoire, qui est définie par
DS:[SI], est initialisée par DS:[100h] ; à chaque décrémentation de CX correspond une
incrémentation de SI.
1
Début
BX <-- 0h
CX <-- 100h
SI <-- 200h
CMP DS:[SI],0
NON
Z = 1 ?
OUI
BX <-- BX + 1
SI <-- SI + 1
CX <-- CX - 1
OUI
NON
Z = 1 ?
DS:[400h] <-- BX
Fin
Après la décrémentation de CX, on n’a pas besoin d’effectuer une comparaison entre CX et 0,
parce que la décrémentation est suffisante pour affecter le flag Z dont on a besoin pour
effectuer l’instruction de saut qui vient juste après la décrémentation de CX.
Donc les instructions de saut sont généralement utilisées après une comparaison ou après une
décrémentation du compteur.
2
Le programme en langage assembleur 8086 : (partie la plus significative)
Etq2 :
Etq1 :
MOV
MOV
MOV
CMP
JNZ
INC
INC
DEC
JNZ
MOV
BRK
CX, 100h
BX, 0000h
SI, 200h
[SI], 0
Etq1
BX
SI
CX
Etq2
[400], BX
Contrairement à l’instruction HLT qui fait arrêter le 8086 de toute activité jusqu’à l’arrivée
d’une interruption matérielle, l’instruction BRK (break) fait arrêter le programme en cours
d’exécution et revenir à l’exécution du système d’exploitation.
3
Exercice 2 :
Ecrire un programme qui permet de déterminer le maximum dans un tableau d’octets
mémoire de longueur 100h et débutant à l’adresse [200h], le résultat sera placé à l’adresse
[400h].
Solution :
Début
CX <-- FFh
SI <-- 200h
AL <-- [SI]
SI <-- SI + 1
NON
OUI
AL > [SI] ?
AL <-- [SI]
CX <-- CX - 1
OUI
NON
Z = 1 ?
DS:[400h] <-- AL
Fin
4
Le compteur CX a été initialisé à : N-1 = 100h - 1 = FFh ; En fait le registre AL prend la
première valeur du tableau, c à d [200h] ; Puis il est comparé avec les N-1 valeurs suivantes.
Pour chaque comparaison, CX prend une valeur, pour la comparaison de la dernière valeur du
tableau, la valeur de CX et égale à 1, donc la valeur initiale de CX est N-1 :
CX = N-1, N-2, ... 2, 1.
Le programme en langage assembleur 8086 : (partie la plus significative)
Etq2 :
Etq1 :
MOV
MOV
MOV
INC
CMP
JLE
MOV
DEC
JNZ
MOV
BRK
CX, FFh
SI, 200h
AL, [SI]
SI
AL, [SI]
Etq1
AL, [SI]
CX
Etq2
[400], AL
5
Exercice 3 :
Ecrire un programme qui permet de trier par ordre croissant un tableau de longueur N = 100h
débutant à l’adresse [200h].
Solution :
Début
BX <-- 200h
CX <-- N-1
SI <-- BX + 1
DX <-- CX
AL <-- [BX]
OUI
NON
AL > [SI] ?
XCHG AL,[SI]
[BX] <-- AL
SI <-- SI + 1
DX <-- DX - 1
OUI
NON
Z = 1 ?
BX <-- BX + 1
CX <-- CX - 1
NON
Z = 1 ?
OUI
Fin
6
Dans cette solution on a eu besoin de deux compteurs CX et DX ; En fait, pour chaque valeur
du compteur CX on prend une des (N - 1) premières valeurs du tableau et on la compare avec
toutes les valeurs qui viennent après (avec une pour chaque valeur de DX). Le compteur CX
prend donc les valeurs suivantes :
CX = N-1, N-2, ... 2, 1.
Lorsque CX est fixé à une valeur (i), on est alors entrain de comparer la valeur (N - i) du
tableau avec les (i) valeurs qui viennent après ; Donc pour chaque valeur de CX, DX prendra
les valeurs suivantes :
DX = CX-1, CX-2, ... 2, 1.
7
Une deuxième solution :
Début
CX <-- N-1
SI <-- 200h
DX <-- CX
BL <-- 0
AL <-- [SI]
NON
OUI
AL ≤ [SI+1] ?
XCHG AL,[SI+1]
[SI] <-- AL
BL <-- BL+1
SI <-- SI + 1
DX <-- DX - 1
OUI
NON
Z = 1 ?
NON
BL = 0 ?
OUI
CX <-- CX - 1
Z = 1 ?
NON
OUI
Fin
8
Dans cette solution on fait le tri de chaque deux valeurs successives du tableau (si elles ne
sont pas triées entre elles dans l’ordre croissant, on fait une permutation entre elles) ;
Pour chaque valeur du compteur secondaire DX, les valeurs à trier sont pointées par [SI] et
[SI+1] ;
Le tableau ayant N valeurs, et le premier passage se faisant jusqu’à comparer entre l’avant
dernière et la dernière valeur, le compteur principal CX aura donc à parcourir (N - 1) valeurs,
càd:
CX = N-1, N-2, ... 2, 1
Cette solution permet d’arrêter le processus lorsqu’on constate que le tableau et déjà trié après
un passage du compteur secondaire DX par toutes ses valeurs concernées, même avant
d’atteindre la limite du compteur principal (CX = 1) ;
Pour chaque passage (i) (c à d pour chaque valeur du compteur principal CX = N - i), SI varie
de sa valeur initiale (200h) jusqu’à la valeur (200h + N - i -1), ce qui donne (N - i) valeurs,
donc le compteur DX va prendre les (N - i) valeurs suivantes :
DX = N-i, N-i-1, N-i-2, ... 2, 1
Ce qui donne :
DX = CX, CX-1, CX-2, ... 2, 1
Par exemple, pour un tableau de longueur N = 5, et pour le premier passage et le deuxième
passage (i = 1) on aura :
CX = 3
CX = 4
DX = 4
3
2
1
DX = 3
2
(SI+1) finale
1
(SI+1) finale
9
Le programme en langage assembleur 8086 :
;tri3
CODE
START :
SEGMENT
ASSUME
ORG
JMP
CS:CODE, DS:CODE ES:CODE
0100H
N EQU 100H
BEGIN
; la procédure sera placée ici
BEGIN :
MOV AX, CODE
MOV DS, AX
MOV ES, AX
MOV CX, N-1
Etq3 :
MOV SI, 200h
MOV DX, CX
MOV BL, 0
Etq2 :
MOV AL, [SI]
CMP AL, [SI+1]
JLE Etq1
XCHG AL, [SI+1]
MOV [SI], AL
INC BL
Etq1 :
INC SI
DEC DX
JNZ Etq2
CMP BL, 0
JZ Fin
DEC CX
JNZ Etq3
Fin :
BRK
CODE
ENDS
END START
10
Une troisième solution : (utilisation d’un sous-programme appelé ‘FINDMAX’)
Début
CX <-- N-1
FINDMAX
NON
OUI
BL = 0 ?
CX <-- CX - 1
NON
OUI
Z = 1 ?
Fin
11
Le sous-programme :
SI <-- 200h
DX <-- CX
BL <-- 0
AL <-- [SI]
NON
OUI
AL ≤ [SI+1] ?
XCHG AL,[SI+1]
[SI] <-- AL
BL <-- BL+1
SI <-- SI + 1
DX <-- DX - 1
OUI
NON
Z = 1 ?
RET
12
Le programme en langage assembleur 8086 :
programme
;tri3
CODE
START :
sous-programme
FINDMAX
SEGMENT
ASSUME
ORG
CS:CODE, DS:CODE ES:CODE
0100H
N EQU 100H
BEGIN
JMP
Etq2:
; la procédure sera placée ici
MOV AX, CODE
MOV DS, AX
MOV ES, AX
BEGIN :
Etq1 :
MOV CX, N-1
CALL FINDMAX
CMP BL, 0
JZ Fin
DEC CX
LOOP Etq3
Etq3 :
Fin :
CODE
FINDMAX
PROC
PUSH CX
MOV SI, 200h
MOV DX, CX
MOV BL, 0
MOV AL, [SI]
CMP AL, [SI+1]
JLE Etq1
XCHG AL, [SI+1]
MOV [SI], AL
INC BL
INC SI
DEC DX
JNZ Etq2
POP CX
RET
ENDP
BRK
ENDS
END START
Remarques :
Le compteur CX est utilisé par le programme principal, mais il n’est pas nécessaire de l’empiler avant
l’exécution de la procédure du sous-programme, car cette dernière ne modifie pas le contenu de CX.
Il est possible aussi de faire l’empilement de CX dans le programme principal juste avant le CALL et de faire
son désempilement dans le programme principal aussi juste après le CALL.
Le registre BL ne peut pas être empilé et désempilé par le programme principal, car la valeur retournée par le
sous-programme ne doit pas être perdue avant son utilisation dans l’instruction (CMP BL, 0) qui vient après le
sous programme.
On rappelle que pour un programme dont l’ensemble des segments ne dépasse pas les 64 Ko,
alors, le programme est organisé selon le canevas suivant :
; nom du programme
CODE
SEGMENT
ASSUME
CS:CODE, DS:CODE ES:CODE, SS:CODE
ORG
0100H
placer toutes les ‘EQU’ ici
START :
JMP
BEGIN
placer tous les ‘define’ ici
placer toutes les procédures ici
placer votre programme ici
BEGIN :
CODE
ENDS
END START
13
Exercice 4 :
Ecrire un programme qui puisse calculer le PGDC (plus grand diviseur commun) de deux
nombres se trouvant aux adresses [200h] et [201h] ; le résultat sera placé à l’adresse [202h].
On rappelle que :
* PGDC [n , m] = PGDC [m , reste(n/m)] , n > m
* PGDC [n , 0] = n , quelque soit n
Solution :
Cette solution utilise une procédure récursive (qui fait appel à elle-même) :
programme
;pgdcom
CODE
START :
sous-programme
PGDC
SEGMENT
ASSUME
ORG
JMP
CS:CODE, DS:CODE ES:CODE
0100H
BEGIN
PUSH AX
PUXH BX
DIV BL
CMP AH, 00H
JZ FIN
MOV AL, BL
MOV BL, AH
CBW
CALL PGDC
; la procédure sera placée ici
BEGIN :
CODE
PROC
MOV AL, [200]
MOV BL, [201]
CBW ; forcer AH = 0
CALL PGDC
MOV [202], AL
BRK
ENDS
END START
FIN :
POP BX
POP AX
RET
PGDC
ENDP
Remarque :
Les registres AH, AL, BH, BL sont employés par le programme principal et par la procédure, donc on doit les
empiler avant de les utiliser par la procédure, puis les désempiler après finir leur utilisation avec la procédure
(PUSH et POP ne fonctionnent que sur des registres 16 bits).
14
Exercice 5 :
Ecrire un programme qui puisse calculer à un dixième près la moyenne arithmétique de
N = 100 valeurs se trouvant dans un tableau.
Solution :
;moy
CODE
SEGMENT
ASSUME
ORG
CS:CODE, DS:CODE ES:CODE
0100H
N EQU 100D
BEGIN
START :
JMP
BEGIN :
MOV AX, CODE
MOV DS, AX
MOV ES, AX
Boucle :
MOV SI, 200
MOV CL, N
MOV BX, N
MOV AX, 0000H
ADD AX, [SI]
INC SI
LOOP Boucle
CWD ; Forcer DX = 0
DIV BX
XCHG AX, BX
MOV [0400H], 0AH ; 0A Hexa = 10 Déci
MUL [0100H]
DIV BL
Fin :
BRK
CODE
ENDS
END START
15
Exercice 6 :
Ecrire un programme qui indique la présence de la chaîne de caractères ‘TEC568’ qui débute
à l’adresse [300h], dans un tableau de N = 96 éléments qui débute à l’adresse [200h], (utiliser
deux procédures ‘AFICH_OK’ et ‘AFFICH_NK’ pour afficher le résultat).
Solution :
Début
SI <-- 200h
CX <-- N-5
DI <-- 300h
BL <-- 6
CLD
CMPSB
NON
OUI
Z = 1 ?
OUI
NON
DEC BL
BL = 5 ?
NON
OUI
Z = 1 ?
DEC SI
DEC CX
NON
Z = 1 ?
AFFICH_OK
OUI
AFFICH_NK
Fin
16
La longueur de la chaîne ‘TEC586’ est N’ = 6, la première lettre ‘T’ est donc cherchée parmi
les (N - N’ -1) premières valeurs ; et le compteur CX prend les valeurs suivantes (sa dernière
valeur est toujours égales à 1) :
CX = N - (N’ - 1), N - (N’ - 1) - 1, ... 2, 1
Par exemple, si N = 15, on aura :
1
CX = 10
2
3
9
4
8
7
5
6
6
5
7
4
8
3
9
2
10
11 12
T
E
C
13
14
5
8
15
6
1
Le programme :
;moy
CODE
SEGMENT
ASSUME
ORG
CS:CODE, DS:CODE ES:CODE
0100H
N EQU 96D
BEGIN
START :
JMP
BEGIN :
MOV AX, CODE
MOV DS, AX
MOV ES, AX
Etq1 :
Etq2 :
Etq3
Etq4
MOV SI, 0200H
MOV CX, N-5
MOV DI, 0300H
MOV BL, 6
CLD
CMPSB
JNZ Etq3
DEC BL
JNZ Etq2
CALL AFFICH_OK
JMP FIN
CMP BL, 5
JZ Etq4
DEC SI
LOOP Etq1
CALL AFFICH_NK
Fin :
INT 3
CODE
ENDS
END START
Rev 1.06 (25 - 01 - 2009) - http://www.electro.bbactif.com/ - Code is Poetry
17
Téléchargement