II. Rappels sur le microprocesseur Intel 8086 - Département ...
Emulation graphique du fonctionnement d'un microprocesseur 8086 ...
Développé en 1978 par Intel, le microprocesseur 8086 est un processeur CISC
16 bits.
Part of the document
I. Présentation du sujet
L'apprentissage de la programmation passe par la connaissance de
l'architecture des ordinateurs, et en particulier par la compréhension de
son élément central, à savoir le microprocesseur. Celle-ci peut être
réalisée de deux manières complémentaires : soit d'un point de vue purement
électronique, c'est-à-dire axée sur ses composants, soit d'un point de vue
fonctionnel, plutôt axée sur son mode de fonctionnement.
Cette deuxième approche induit la découverte, pour chaque
microprocesseur, de langages de bas niveau tels que le langage machine ou
le langage d'assemblage. Cette étape peut présenter quelques difficultés,
car les langages impératifs sont généralement les seuls langages que
connaissent les étudiants. Or, ces langages, étant de haut niveau,
n'imposent pas un découpage aussi strict des opérations effectuées. Entres
autres, l'absence de structures de contrôle telles que les « if » ou les
« while », ainsi que de tableaux ou d'enregistrements désarçonne les
néophytes.
L'objectif de ce projet est de créer une application permettant de
simuler l'exécution d'un programme écrit dans un langage d'assemblage
ressemblant à celui du microprocesseur 8086. Cette simulation ayant pour
but de faciliter la compréhension d'un langage d'assemblage, elle se doit
de présenter clairement l'ordre d'exécution des instructions, leur impact
sur les données, ainsi que sur les différents éléments manipulés par ce
microprocesseur, que sont la pile, les registres et les flags.
Il existe déjà de tels débogueurs dans le commerce, mais
l'apprentissage de leur syntaxe et de leur mode de fonctionnement nécessite
de passer de nombreuses heures à compulser la documentation. Notre but est
de créer un interpréteur minimaliste, d'un sous-ensemble du langage
d'assemblage du 8086, très rapidement compréhensible, même pour un
utilisateur n'ayant que peu de connaissances sur ce microprocesseur.
Le langage retenu pour effectuer le développement de cette application
est Java. L'intérêt d'utiliser ce langage est que Java est un langage
objets, ce qui a permis d'effectuer une modélisation du problème sous forme
de classes. A cela s'ajoutent les fonctionnalités offertes par ce langage
en terme d'Interfaces Homme-Machine.
Dans un premier temps, nous allons présenter succinctement les
principales caractéristiques du microprocesseur Intel 8086. Ensuite nous
aborderons nos choix d'implémentation, la modélisation effectuée et le
fonctionnement de la partie émulant le 8086. Enfin, nous nous intéresserons
plus particulièrement à l'utilisation de l'interface graphique de
l'application.
II. Rappels sur le microprocesseur Intel 8086
Développé en 1978 par Intel, le microprocesseur 8086 est un processeur
CISC 16 bits. Il s'agit du premier microprocesseur de la famille des
« x86 » comprenant les célèbres 80386 et 80486.
Ses caractéristiques principales sont les suivantes :
V Bus de données d'une largeur de 16 bits.
V Bus d'adresses de 20 bits, ce qui permet d'adresser un total de 1
mégaoctet de mémoire.
V 14 registres de 16 bits dont un registre d'état contenant des
indicateurs binaires.
La mémoire est segmentée en 16 blocs de 64 Ko et une adresse sur 20
bits est obtenue en combinant deux parties :
. Le registre CS permet de stocker les 4 bits de poids fort
donnant le numéro de segment de mémoire ;
. Le registre IP fournit les 16 bits de poids faible donnant
l'adresse à l'intérieur du segment de mémoire spécifié par CS.
L'adresse mémoire est retrouvée selon la formule :
adresse = (16 x CS) + IP.
Le 8086 autorise un mode de fonctionnement en pas à pas, ainsi que
l'utilisation d'opérations spécifiques appelées interruptions permettant au
8086 de « dialoguer » avec les autres périphériques de l'ordinateur.
Les registres du 8086 se décomposent en 4 grandes familles :
V 4 registres de données, se décomposant chacun en deux parties :
une partie « haute » et une partie « basse » de 8 bits chacune,
ce qui permet au microprocesseur de manipuler des données sur 8
ou 16 bits :
- AX (décomposable en AH et AL) sert d'accumulateur et est
principalement utilisé lors d'opérations arithmétiques et
logiques ;
- BX est la plupart du temps utilisé comme opérande dans les
calculs ;
- CX est utilisé comme compteur dans les structures
itératives ;
- DX, tout comme AX, est utilisé pour les calculs
arithmétiques et notamment dans la division et la
multiplication. Il intervient également dans les opérations
d'entrées/sorties.
V registres de segmentation :
- CS (segment de code) permet de déterminer les adresses sur
20 bits ;
- DS (segment de données) ;
- SS (segment de pile) ;
- ES (segment supplémentaire).
V registres pointeurs ou d'index :
- SP (pointeur de pile) pointe sur le sommet de la pile de
données ;
- BP (pointeur de base) pointe sur la base de la pile de
données ;
- SI (index de source) ;
- DI (index de destination).
V pointeur d'instruction : IP stocke l'adresse de la prochaine
instruction à exécuter par le microprocesseur.
V registre spécial contenant 9 indicateurs binaires nommés
« flags » :
- AF (indicateur de retenue auxiliaire) ;
- CF (indicateur de retenue) est mis à 1 lorsqu'il y a eu une
retenue lors d'un calcul ;
- OF (indicateur de débordement) est mis à 1 lorsqu'un
débordement arithmétique a eu lieu (lorsque le résultat
d'une opération ne peut tenir sur 16 bits) ;
- SF (indicateur de signe) représente le signe du résultat
d'une opération (0 = positif, 1 = négatif) ;
- PF (indicateur de parité) est mis à 1 lorsque le résultat
d'une opération contient un nombre pair de 1 ;
- ZF (indicateur de zéro) est mis à 1 lorsque le résultat
d'une opération vaut 0 ;
- DF (indicateur de direction) ;
- IF (indicateur d'autorisation d'interruption) ;
- TF (indicateur d'interruption pas à pas).
Le 8086 est programmable dans un langage d'assemblage comportant des
instructions utilisant les registres, les flags, la mémoire et, en ce qui
concerne les interruptions, d'autres éléments de l'ordinateur. Voici un
aperçu des instructions les plus couramment utilisées (dans la liste qui
suit, les mots entre parenthèses indiquent le nom de l'instruction). Ces
instructions seront étudiées plus en détail dans la section consacrée à la
partie « CPU » de notre émulateur.
V Instructions arithmétiques : addition (ADD), soustraction (SUB),
multiplication (MUL), division (DIV), incrémentation (INC),
décrémentation (DEC) et échange (XCHG) ;
V Instructions logiques : et (AND), ou (OR) et non (NOT) ;
V Instruction de comparaison (CMP) : met à jour les flags pour
permettre l'utilisation des instructions de saut ;
V Instructions de saut : saut si égal (JE), saut si différent (JNE),
saut si inférieur (JL), ...
V Instructions de gestion de la pile : empilement (PUSH) et
dépilement (POP)
V Instruction d'appel (CALL) et de retour (RET) ;
V De nombreuses autres instructions que nous ne détaillerons pas ici.
III. Modélisation de l'émulateur
1. Caractéristiques générales
Simuler complètement le fonctionnement d'un 8086 aurait demandé un
travail considérable car ses propriétés sont nombreuses. La durée imposée
pour le stage nous a conduit à sélectionner celles qui nous ont paru
essentielles.
La gestion de la mémoire à la manière du 8086 n'étant pas non plus
l'objectif principal de l'émulateur, nous avons opté pour un système à mi-
chemin entre celle-ci et celle proposée dans un langage impératif comme le
Pascal. Cette gestion passe donc par l'utilisation de variables et de
tableaux, au lieu de segments. Le type d'une variable ou d'un élément d'un
tableau est systématiquement un entier non signé sur 16 bits, ce qui
autorise les valeurs de 0 à 65535.
Au niveau du processeur, les registres supportés sont au nombre de 7 :
les registres de données (AX, BX, CX, DX), les deux registres pointeurs de
pile (BP et SP) et le pointeur d'instruction IP. Les autres registres ont
été laissés de coté en raison de leur utilisation dans les interruptions
(abandonnées du fait d'une trop grande complexité) et la gestion de la
mémoire par segments. Les flags conservés sont ZF, CF, OF et SF, les autres
ayant été rejetés car n'intervenant pas dans les instructions que nous
avons choisi de supporter.
La pile, quand à elle, est gérée non pas comme une partie de la
mémoire centrale mais comme une pile de données pouvant contenir des
adresses et des valeurs.
Le langage d'assemblage supporté par notre émulateur a été déterminé
en réalisant un compromis entre le langage d'assemblage réel du 8086 et
notre besoin de supporter les variables et les tableaux. Le besoin