TP TD Assembleur2 Id012
TP TD Assembleur2 Id012
TP TD Assembleur2 Id012
février 2001
MicroInformatique
Informatique Industrielle
Assembleur 8086/8088
TP n°2
I. BUT DU TP
Se familiariser avec assembleur freeware NASM associé à l'éditeur syntaxique NASMIDE.
- Vérifier que les options suivantes sont configurées dans le menu options|directories
- Editer le programme qui affiche un caractère A à l'écran (le même celui du TP 1).
(Attention, int 21 s'écrit maintenant int 0x21 ou int $21)
- Appuyer sur la touche F2 pour sauver le programme.
- Appuyer simultanément sur les touches alt + F9 pour assembler le programme.
- Une fenêtre d'erreur doit normalement indiquer qu'aucune erreur n'est survenue.
- Appuyer simultanément sur les touches Ctrl + F9 pour exécuter le programme.
100 décimal
100h hexadécimal
0x100 hexadécimal aussi
$100 hexadécimal également mais le premier caractère doit être un chiffre
10000100b binaire
nb db $10
tab db 1, 2 ,3 ,4 ,5 ,6 ,7 ,8 ,10
message db 'bonjour les IUP GSI TI',13,10,'$'
(13 retour chariot, 10 ligne suivante, $ fin de chaîne de caractères)
R dd 1024
A dd 1.2
B dd 1.e10
C dd 1.e+10
D dq 1.e-10
pi dt 3.141592353589793238462
f) Définition d'étiquettes
Contrairement à DEBUG, il est possible de définir des étiquettes vers lesquelles certaines
instructions pourraient se brancher. Ceci évite le comptage laborieux des octets lorsqu'il s'agit de
réaliser un saut dans le programme.
Une étiquette de déclare par un nom de taille inférieure à 8 caractères et se terminant par :
Exemple:
III. Exercices
Exercice 1:
2) Afficher ensuite le résultat à l'écran en utilisant l'interruption $21 puis déduire en fonction
du caractère affiché la valeur numérique du résultat.
Exercice 2:
L'interruption $21 avec ah à 9 permet d'afficher des chaînes de caractères qui se terminent par
le caractère 13, 10 ,'$'. (13 retour chariot, 10 ligne suivante, $ fin de chaîne de
caractères)
Pour cela, il faut définir un message avec la pseudo instruction db (voir explications de db) en
terminant ce message par 13, 10, '$'.
Il faut ensuite affecter au registre dx l'adresse de ce message (mov dx, mess où mess est le nom
donné au message).
Ecrire un programme qui affiche dix fois à l'écran le message suivant avec retour à la ligne et
saut de ligne:
Si je travaille bien en TP, je deviendrai un dieu de l'assembleur et le prof sera fier de moi
Exercice 3:
Concevoir une application qui réalise le produit de deux nombres A =
100 et B = 170. Les nombre A et B sont codés sur 8 bits chacun.
- Quelle instruction faut il utiliser ?
- Où se trouvent les opérandes ?
- Où se trouve le résultat de l'opération.
- Afficher les octets du registre contenant le résultat de
l'opération.
- Déduire le résultat numérique à partir des caractères
affichés.
MicroInformatique
Informatique Industrielle
Assembleur 8086/8088
TP n°3
I. BUT DU TP
Maîtriser les différents types d'adressage, notamment pour accéder aux éléments de tableaux.
IV. RAPPELS
Pour adresser les différents éléments d'un tableau, il faut utiliser l'adressage indexé basé en prenant le
registre BX comme base et le registre DI ou SI comme indexe. Pour mettre la base du tableau
(déplacement du tableau dans le segment de données) dans BX, il suffit d'écrire
MOV BX, nom du tableau.
V. EXERCICES
Exercice 1:
Soit le tableau suivant:
Faire le somme des 6 éléments de ce tableau et mettre le résultat dans une variable S. Afficher
le résultat à l'écran, en déduire la valeur numérique.
Exercice 2:
Ecrire une application qui compte le nombre de lettres 'e' dans une phrase quelconque (50
caractères minimum) se terminant par le caractère '$'.
- Représenter l'organigramme.
- Mettre le résultat dans le registre dl et ajouter 32.
- Imprimer le caractère à l'écran et vérifier si le caractère qui apparaît est cohérent.
Exercice 3:
Définir une chaîne de caractères de longueur au moins 50 caractères se terminant par '$'.
Réaliser une application (organigramme + programme) qui remplace toutes les lettres d'un
type donné par un autre type (par exemple tous les 'e' par des 'a').
On entrera les deux lettres au clavier en utilisant l'interruption 21,8.
Les saisies clavier seront précédées d'un message du type 'Remplacer:' et 'par:'
Exercice 4:
i0
j1
n5
tant que i < n-1
tant que j <n
Si tab[i]>tab[j] alors Permuter(tab,i,j)
j = j +1
fin tant que
i = i+1
j = i+1
fin tant que
message db "le but de ce probleme est de trier par ordre croissant de code ASCII cette chaîne de caractere"
- Ecrire le programme qui tri par ordre croissant de code ASCII la chaîne précédente.
- On prendra SI pour l'index i et DI pour l'index j.
- On affichera le résultat grâce à l'interruption $21, 9.
Olivier HABERT
février 2001
MicroInformatique
Informatique Industrielle
Assembleur 8086/8088
TP n°4
I. But du TP
Programmer l'affichage en mode Graphique MCGA.
Exemple:
mov ax,0xa000
mov es,ax
mov dl, 0xaa
mov bx, 160
mov [es:bx], dl ; on écrit à l'adresse 0xa000 + 160
ou
mov bx, 160
mov [es:bx + 320], dl ; on écrit à l'adresse 0xa000 + 160 +320
ou
ou
V. Exercices
Exercice 1:
- Allumer le pixel de coordonnées (200,100) avec la couleur de code 0x32.
- Allumer les 256 premiers pixels leur associant une couleur variant de 0 à 255.
- Même question mais en augmentant l'épaisseur du trait (5 lignes).
- Même question mais sur toute la hauteur de l'écran (cf figure suivante).
Exercice 2:
- Encadrer l'écran avec un cadre d'épaisseur 5 pixels de la couleur de votre choix
- Quadriller l'écran avec une ligne de 5 pixels d'épaisseur et un espacement de 10
pixels entre les lignes.
Exercice 3: (pour les meilleur(e)s)
- Ecrire un programme qui déplace un motif rectangulaire (8*6 pixels) en bas de la
fenêtre de gauche droite, de droite gauche, … tant qu'aucune touche n'est
appuyée.
- L'affichage et l'effacement devra se faire avec un ou exclusif pour ne pas effacer ce
qui se trouve éventuellement déjà sur l'écran.
- Le test de l'appui d'une touche se fera en utilisant l'interruption 0x16 (voir annexe)
- Les variables à utiliser seront les suivantes:
- entre chaque affichage, il est nécessaire (au moins sur les Pentiums) de générer une
temporisation. Pour cela on écrira un sous-programme de temporisation simple du
type:
- Pour déplacer le motif vers la gauche ou vers la droite, on utilisera une variable
delta qui prendra la valeur 1 ou –1 selon le sens du déplacement. Cette variable
servira d'incrément pour afficher la position suivante du motif.
- Il faudra tester si on arrive au niveau de la limite supérieure droite (320-L) pour
donner à delta la valeur –1 et tester la limite inférieure gauche (0) pour mettre delta
à +1.
MicroInformatique
Informatique Industrielle
Assembleur 8086/8088
TP n°5
I. But du TP
Se familiariser avec les instructions répétitives, les horloges temps réel, la génération de nombres
pseudo aléatoires, …
(Ce TP a été largement inspiré de ce que l'on trouve sur le site
http://www.multimania.com/abcp/ad/index.html#depart )
Quand les spots arrivent en bas de l'écran, ils reviennent en haut et la balayage recommence. Pendant
la remontée, les spots sont invisibles.
Nous allons dans cet exercice synchroniser l'affichage des points avec la remontée des spots. Pour
cela nous allons détecter grâce à la lecture d'un port d'entrée sortie le moment ou les spots commencent
leur remontée. Pendant cette remontée, nous allons effectuer l'affichage.
Cette information de trouve au niveaux du port E/S d'adresse 3DAh. Quand on lit ce port, le bit n°3
(quatrième bit) renseigne sur l'état des spots. Quand ce bit est à 0, on est entrain de dessiner (balayage
vers le bas des spots) et quand ce bit est à 1, les spots sont entrain de remonter.
Le principe est d'attendre tant que le bit n°3 est à 1 puis d'attendre tant qu'il est à 0. Ainsi on sera
certain que l'on va commencer l'affichage au début de la remontée des spots. Dans les animations
graphiques, cette méthode permet d'éviter les phénomène d'instabilité au niveau de l'affichage.
Ajouter dans le programme précédent le code qui synchronise le dessin sur le rafraîchissement de
l'écran.
Pour cela on suivra les étapes suivantes:
- Lire le port 3DAh avec l'instruction IN AL, DX (dx contient l'adresse du port).
- Faire un masque avec la valeur 08 (utiliser l'instruction AND AL,08).
- Faire le saut tant que le résultat n'est pas nul.
- Recommencer une seconde boucle qui dure maintenant tant que le résultat est nul.
V. Utilisation des instructions de chaînes pour translater
l'écran
Les instructions de chaînes:
MOVSB
MOVSW
MOVSD
REP MOVSB
REP MOVSW
REP MOVSD
Commentaires.
Ces instructions permettent de déplacer un octet (suffixe B comme Byte), un mot (suffixe W comme
Word) ou un double mot à partir du processeur 386 (suffixe D comme DWord).
En mode 16 bits, l'octet (mot ou double mot) d'origine est pris en [DS:SI], d'où le nom SI de Source
Index. Le segment DS est implicite et il est possible d'en choisir un autre avec un préfixe de segment.
La destination est [ES:DI], d'où le nom DI de destination index. Il n'est par contre pas possible de
changer le segment ES.
En mode 32 bits, les index ESI et EDI sont utilisés en place de SI et DI.
Ces instructions permettent de faire des transfert simples ou multiples. On parle alors de chaîne de
caractère, d'où le nom de l'instruction MOVE (déplacer) S (string=chaîne).
Pour être prêt à faire le transfert suivant, les index sont incrémentés si l'indicateur de direction est à 0,
et décrémentés si il est à 1. Pour mettre l'indicateur de direction à 0 on utilise l'instruction CLD (clear
direction, clear=effacer). Avec MOVSB, SI et DI seront incrémentés de 1. Avec MOVSW, on vient de
transférer deux octets, il faut donc pointer sur le word suivant qui est deux octets plus loin. SI et DI
seront donc incrémentés de 2. Avec MOVSD, les index sont incrémentés de 4. On peut aussi mettre
l'indicateur de direction à 1 par l'instruction STD (set D, set se traduit par mettre), ainsi les index seront
décrémentés de 1, 2 ou 4.
Si on utilise le préfixe REP devant, l'instruction est répétée CX fois en mode 16 bits (ECX fois en mode
32 bits). En fait REP va décrémenter CX et faire l'instruction tant que CX n'est pas nul. Si on met 10
dans CX avant l'instruction MOVSB, on copiera 10 octets. MOVSW copiera donc 20 octets (10 fois 2
octets) et MOVSD copiera 40 octets. Si CX est nul, la première décrémentation mettra
CX à 65535, et on fait donc 65536 copies.
Utilisation
On utilise rarement cette instruction en dehors d'une boucle. Elle est utilisée en principe pour copier
une zone de mémoire dans une autre. REP MOVSD est plus rapide pour copier un nombre d'octets
fixe, on la préférera si le nombre d'octet est connu ou est divisible par 4. On utilise MOVSW si le
processeur peut être un 8086 ou un 80286. MOVSB ne devrait que très peu être employée.
Ces instructions sont très utiles pour déplacer des tableaux, des chaînes de caractères, des buffers, des
zones d'écran...
Un exemple.
On vient de dessiner en mémoire une belle page que l'on veut afficher en mode 13h.
La page dessinée commence en DS:0000.
Dans l'étape précédente, nous avions un ciel noir dans lequel apparaissait progressivement des étoiles colorées.
Nous allons monter dans une fusée et nous allons voir les étoiles défiler. Cela va donner:
Pour faire ce programme, nous allons répéter quatre choses (une de plus que la dernière fois):
- Décaler l'écran graphique d'une ligne vers le bas (pour avoir l'impression de monter)
Décaler l'écran.
C'est la seule chose qui est nouvelle dans cette étape. Nous sommes en mode 13h et l'écran visible à 200 lignes.
Quand on écrit un point au hasard, on l'écrit dans le segment entier. L'écran dans lequel on dessine dépasse un
peu de quelques lignes. Nous allons utiliser la ligne 200, qui est invisible, car seules les lignes 0 à 199 sont
affichées. Nous allons dérouler l'écran comme du papier à musique: pour faire descendre l'écran, il suffit de
prendre toutes les lignes et de les redessiner une ligne plus bas. Pour avoir de plus en plus d'étoile comme dans
l'étape précédente, nous allons mettre la dernière ligne à la place de la première. Pour décaler nos 200 lignes
nous allons en utiliser 201 (une ligne sert de mémoire). Nous allons faire cette rotation en deux temps.
Premier temps: copiez les lignes 0 à 199 dans les lignes 1 à 200. En assembleur pour faire un tel travail, il n'y a
pas vraiment le choix, il faut utiliser l'instruction MOVSW (pour recopier les octets 2 par 2).
Les zones source et destination se recouvrent. Il va donc falloir réfléchir: si nous copions d'abord la ligne 0 dans
la ligne 1, nous ne pourrons plus copier le ligne 1 dans la ligne 2 car la ligne 1 aura été écrasée et contiendrait la
ligne 0. Il va donc falloir copier à l'envers. Mettons la ligne 199 dans la 200, la 198 dans la 199 et ainsi de suite.
Pour positionner les index, il faut mettre dans SI l'offset du dernier ensemble de 2 points de l'écran que l'on va
copier (vu que nous commençons par copier par la fin ). Chaque ligne contient 320 points, soit 320
octets. Après notre dernier ensemble de 2 points, nous allons trouver les points de la ligne
200, et donc d'offset 200*320. Le dernier couple copié est donc en 200*320-2. Nous écrirons
simplement:
mov si,200*320-2
Pour le calcul de di, c'est exactement une ligne au dessous soit 320 octets plus loin.
mov di,200*320-2+320
Ne faites pas le calcul pour le propgramme, on sait ainsi comment cette valeur est obtenue.
L'initialisation des segments peut se faire au début du programme une fois pour toutes.
Profitons de l'initialisation de l'un pour initialiser l'autre. Écrivons quelque chose du style:
mov ax,0A000h
mov ds,ax
mov es,ax
Pour déplacer 200 lignes, soit 200*320 octets, il faut initialiser CX à 200*320/2 vu que nous copions les
octets 2 par 2.
Ici les lignes ne se recouvrent pas, on peut donc les copier dans le sens que l'on veut. Comme
nous avons copié le reste en décrémentant les indices, il y a deux solutions: soit on met
l'indicateur à 1 une fois pour toutes dans les initialisations et on décrémente aussi pour cette
partie, soit on positionne l'indicateur à chaque fois pour chacune des deux parties et on peut
utiliser l'incrémentation. Pour une fois, c'est vous qui choisissez. On aura de toutes façon
l'occasion d'utiliser cette deuxième démarche dans une étape ultérieure.
Normalement si tout se passe bien, l'écran va se remplir progressivement de points tout en descendant. Tant que
les points sont peu nombreux, tout est sympathique, mais quand les points seront suffisamment denses, vous
apercevrez comme des barres horizontales au milieu de l'écran. Cela est dû en partie au fait que l'écran est
dessiné dans le mauvais sens (bas vers le haut, contraire au balayage). Il y a des moyens de faire mieux, mais ce
qui nous intéresse actuellement est la découverte des méthodes de programmation et les instructions, avec une
progression pas trop rapide.