La machine virtuelle MaP

publicité
La machine virtuelle
MaP
Le but de ce document est de fournir au lecteur une vue très simple du
fonctionnement d’un ordinateur au niveau de sa programmation en
langage machine.
Il s’agit d’un outil pédagogique n’ayant aucunément l’ambition de se
substituer à un produit professionnel du marché. L’avantage du
produit décrit dans ce document est:
d’être gratuit ;
• de pouvoir être utilisé sur tout PC équipé d’un 80386 au moins;
• d’être limité dans sa complexité afin justement de pouvoir être
utilisé dans un contexte d’enseignement.
•
© Nino Silverio (octobre 1999)
1
La machine virtuelle MaP
1 L’architecture de la machine MaP
Le cœur de la machine virtuelle MaP est un processeur orienté pile
(stack machine). Outre le processeur proprement dit, la machine
contient de la mémoire centrale subdivisée en un segment de code et
un segment de données. Le processeur est doté de trois registres
spéciaux:
un compteur ordinal PC (program counter) pointant sur
l’instruction à exécuter ;
• un pointeur de pile SP (stack pointer) contenant l’adresse du
sommet de la pile, c’est-à-dire l’adresse du dernier mot mémoire
occupé dans le segment de données ;
• le registre de base BP (base pointer) permettant d’accéder à des
mots mémoire du segment de données via un déplacement relatif
au contenu de ce registre.
•
processeur MaP
PC
segment de code
BP
SP
segment de données
Le segment de code et le segment de données sont physiquement
séparés. L’adresse de base de chacun des segments est 0. La fonction
du segment de code est de contenir le code machine que le processeur
doit exécuter.
Le segment de données sert à contenir les données que le programme
contenu dans le segment de code doit traiter ainsi que les résultats
que ce programme produit. Il est aussi l’endroit utilisé par le
processeur pour stocker des données temporaires. Le programmeur
peut utiliser le segment de données comme il l’entend, mais
généralement, il a intérêt, afin d’éviter tout conflit, de réserver
l’espace nécessaire au stockage des données et des résultats fixes
(alloués pour toute la durée de l’exécution du programme) en un bloc
2
© Nino Silverio
Le jeu d’instructions de la machine MaP
contigu à partir de l’adresse 0. Le segment de données aura ainsi la
structure usuelle suivante :
valeurs temporaires
données et résultats
fixes du programme
Structure du segment de données
Ainsi, immédiatement après le dernier mot occupé par les données et
résultats débute ce que l’on appelle la pile d’exécution qui peut
s’étendre jusqu’à la fin du segment de données. Elle contiendra
toutes les données temporaires nécessaires à la bonne exécution du
programme. Cet espace mémoire croîtra et décroîtra au fur et à
mesure de l’exécution du programme.
2 Le jeu d’instructions de la machine MaP
Le processeur MaP est capable de traiter trois types différents de
données :
les nombres entiers (int) ;
• les nombres décimaux (numeric) ;
• les caractères (char).
•
La taille d’un mot mémoire du segment de données est tel qu’il peut
contenir un nombre entier ou un caractère. Un nombre décimal
nécessite deux mots mémoire du segment de données.
La taille d’un mot mémoire du segment de code est la moitié de celle
d’un mot mémoire du segment de données.
Dans l’implémentation proposée, un entier (int) peut prendre une
valeur allant de –2147483648 à +2147 483 647.
© Nino Silverio
3
La machine virtuelle MaP
Les caractères (char) sont représentés de manière interne en se basant
sur la codification ASCII.
Un numérique (numeric) peut prendre une valeur comprise entre
2.2 ⋅ 10 – 308 et 1.8 ⋅ 10 308 .
Le processeur reconnaît 30 instructions de base parmi 58 instructions
possibles. En effet, la plupart des instructions existent en deux ou
trois versions suivant le type des données manipulées (int, numeric,
char).
Les instructions peuvent être classées de la manière suivante :
•
•
•
•
•
•
opérations arithmétiques : ADD, SUB, MULT, DIV, NEG
opérations logiques : AND, OR, NOT, EQ, GT, LS
instructions de rupture de séquence : CALL, RET, JF, JP
instructions de manipulation de la pile : DECR, INCR, DUPL,
ASSGN, LOAD, PAIBP, PUSH, STORE
instructions d’entrée-sortie : IN, OUT, OUTSTR
instructions spéciales : CALLS, HALT, NEWBP, RSTRBP.
Le code machine (exprimé en décimal) associé à chacune des
instructions est le suivant :
4
addi
0
addn
1
and
2
assgnc
3
assgni
4
assgnn
5
call
6
calls
7
contc
8
conti
9
contn
10
decr
11
divi
12
divn
13
duplc
14
dupli
15
dupln
16
eqc
17
eqi
18
eqn
19
gtc
20
gti
21
gtn
22
halt
23
inc
24
ini
25
inn
26
incr
27
jf
28
jp
29
loadc
30
loadi
31
loadn
32
lsc
33
lsi
34
lsn
35
multi
36
multn
37
negi
38
negn
39
newbp
40
not
41
or
42
outc
43
outi
44
© Nino Silverio
Le jeu d’instructions de la machine MaP
outn
45
outstr
46
paibp
47
pushc
48
pushi
49
pushn
50
ret
51
rstrbp
52
storec
53
storei
54
storen
55
subi
56
subn
57
2.1 Les opérations arithmétiques
Ces instructions existent pour le type entier ainsi que pour le type
numérique. Ainsi, par exemple, une opération d’addition de deux
entiers se fait à l’aide de l’instruction ADDI, alors qu’une instruction
d’addition de deux numériques se fait avec l’instruction ADDN.
L’ensemble des instructions arithmétiques s’écrit : ADDI, SUBI,
MULTI, DIVI, NEGI, ADDN, SUBN, MULTN, DIVN, NEGN.
Les instructions arithmétiques effectuent des opérations de calcul sur
les mots mémoire situés au sommet de la pile d’exécution. Elles ne
nécessitent pas d’opérandes car ceux-ci doivent se trouver sur le
sommet de la pile. Le compteur ordinal est incrémenté d’une unité à
la fin de chacune de ces instructions.
Voici la signification de ces instructions :
ADDI les deux opérandes entiers au sommet de la pile sont
additionnés et remplacés par le résultat entier de l’addition. Le
pointeur de pile décroît d’une unité.
SUBI l’opérande entier au sommet de la pile est soustrait de
l’opérande juste en dessous du sommet. Ces deux opérandes sont
remplacés par le résultat entier de la soustraction. Le pointeur de pile
décroît d’une unité.
MULTI les deux opérandes entiers du sommet de la pile sont
multipliés et remplacés par le résultat entier de la multiplication. Le
pointeur de pile décroît d’une unité.
DIVI l’opérande entier juste en dessous du sommet de la pile est
divisé par l’opérande entier du sommet de la pile. Ces deux
opérandes sont remplacés par le résultat entier de la division. Le
pointeur de pile décroît d’une unité. Dans le cas où le diviseur vaut 0,
une erreur est détectée et l’exécution est arrêtée.
© Nino Silverio
5
La machine virtuelle MaP
NEGI (NEGate) le signe de l’opérande entier au sommet de la pile
est inversé. Le pointeur de pile reste inchangé.
ADDN les deux opérandes numériques au sommet de la pile sont
additionnés et remplacés par le résultat numérique de l’addition. Le
pointeur de pile décroît de deux.
SUBN l’opérande numérique au sommet de la pile est soustrait de
l’opérande juste en dessous du sommet. Ces deux opérandes sont
remplacés par le résultat numérique de la soustraction. Le pointeur de
pile décroît de deux.
MULTNles deux opérandes numériques du sommet de la pile sont
multipliés et remplacés par le résultat numérique de la multiplication.
Le pointeur de pile décroît de deux.
DIVN l’opérande numérique juste en dessous du sommet de la pile
est divisé par l’opérande numérique du sommet de la pile. Ces deux
opérandes sont remplacés par le résultat numérique de la division. Le
pointeur de pile décroît de deux. Dans le cas où le diviseur vaut 0,
une erreur est détectée et l’exécution est arrêtée.
NEGN (NEGate) le signe de l’opérande numérique au sommet de la
pile est inversé. Le pointeur de pile reste inchangé.
2.2 Les opérations logiques
Les instructions AND, OR et NOT ne sont pas typées. AND et OR
fonctionnent avec deux opérandes qui sont les deux mots mémoire du
sommet de la pile, NOT ne prend en compte que le mot mémoire du
sommet de la pile (un seul opérande). Pour toutes ces opérations
logiques, le compteur ordinal PC est avancé d’une unité.
AND une opération logique et est effectuée avec les deux
opérandes du sommet de la pile. Le résultat de cette opération
remplace les deux opérandes au sommet de la pile. Le pointeur de
pile décroît d’une unité.
opérande 1
0
0
x
x
opérande 2
0
x
0
x
résultat
0
0
0
1
Dans ce tableau, x représente une valeur quelconque différente de 0.
6
© Nino Silverio
Le jeu d’instructions de la machine MaP
OR
une opération logique ou est effectuée avec les deux
opérandes du sommet de la pile. Le résultat de cette opération
remplace les deux opérandes au sommet de la pile. Le pointeur de
pile décroît d’une unité.
opérande 1
0
0
x
x
opérande 2
0
x
0
x
résultat
0
1
1
1
Dans ce tableau, x représente une valeur quelconque différente de 0.
NOT
une opération logique non est effectuée sur l’opérande au
sommet de la pile. Ceci signifie que si le sommet de la pile a comme
valeur faux, celle-ci devient vrai et inversement. La valeur 0 est
interprétée comme faux, toutes les autres valeurs comme vrai. Le
pointeur de pile reste inchangé.
Les autres instructions logiques EQ, GT et LS par contre existent
pour chacun des trois types reconnus par la machine. Voici leurs
significations respectives :
EQC
(EQual) les deux caractères au sommet de la pile sont
dépilés et s’ils sont égaux, la valeur logique vrai 1 est placée sur le
sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît d’une unité.
LSC
(LesS) les deux caractères au sommet de la pile sont dépilés
et si l’opérande juste en dessous du sommet est strictement inférieur
à l’opérande du sommet, la valeur logique vrai 1 est placée sur le
sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît d’une unité.
GTC
(Greater Than) les deux caractères au sommet de la pile sont
dépilés et si l’opérande juste en dessous du sommet est strictement
supérieur à l’opérande du sommet, la valeur logique vrai 1 est placée
sur le sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît d’une unité.
EQI
(EQual) les deux opérandes entiers au sommet de la pile
sont dépilés et s’ils sont égaux, la valeur logique vrai 1 est placée sur
le sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît d’une unité.
© Nino Silverio
7
La machine virtuelle MaP
LSI
(LesS) les deux opérandes entiers au sommet de la pile sont
dépilés et si l’opérande juste en dessous du sommet est strictement
inférieur à l’opérande du sommet, la valeur logique vrai 1 est placée
sur le sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît d’une unité.
GTI
(Greater Than) les deux opérandes entiers au sommet de la
pile sont dépilés et si l’opérande juste en dessous du sommet est
strictement supérieur à l’opérande du sommet, la valeur logique vrai
1 est placée sur le sommet de la pile, autrement c’est la valeur
logique faux 0. Le pointeur de pile décroît d’une unité.
EQN (EQual) les deux opérandes numériques au sommet de la
pile sont dépilés et s’ils sont égaux, la valeur logique vrai 1 est placée
sur le sommet de la pile, autrement c’est la valeur logique faux 0. Le
pointeur de pile décroît de trois unités.
LSN
(LesS) les deux opérandes numériques au sommet de la pile
sont dépilés et si l’opérande juste en dessous du sommet est
strictement inférieur à l’opérande du sommet, la valeur logique vrai 1
est placée sur le sommet de la pile, autrement c’est la valeur logique
faux 0. Le pointeur de pile décroît de trois unités.
GTN (Greater Than) les deux opérandes numériques au sommet
de la pile sont dépilés et si l’opérande juste en dessous du sommet est
strictement supérieur à l’opérande du sommet, la valeur logique vrai
1 est placée sur le sommet de la pile, autrement c’est la valeur
logique faux 0. Le pointeur de pile décroît de trois unités.
2.3 Les instructions de rupture de séquence
Les instructions de la machine MaP sont exécutées par défaut en
séquence, dans leur ordre d’apparition. A l’aide des instructions
CALL, RET, JF et JP, le programmeur peut changer cet ordre afin de
refléter la logique de traitement. Les instructions CALL et RET
permettent de mettre en œuvre le concept de sous-programme. JP
provoque un branchement inconditionnel alors que JF effectue un
branchement en fonction de la valeur présente sur le sommet de la
pile.
JP op (JumP) effectue un branchement inconditionnel à l’adresse
indiquée par l’opérande. Le compteur ordinal aura comme nouvelle
valeur la valeur de l’opérande. Le pointeur de pile n’est pas affecté.
8
© Nino Silverio
Le jeu d’instructions de la machine MaP
JF op (Jump if False) effectue un branchement à l’adresse
indiquée par l’opérande entier sous condition que la valeur logique
faux (0) se trouve sur le sommet de la pile. Dans ce cas, le compteur
ordinal aura comme nouvelle valeur la valeur de l’opérande,
autrement, si cette condition n’est pas vérifiée, le compteur ordinal
est simplement incrémenté de 3 (on passe à l’instruction suivante).
Dans tous les cas, la valeur logique (le sommet de la pile) est dépilée
et, par conséquent, le pointeur de pile est décrémenté d’une unité.
CALL op
l’adresse de retour (PC+3) est placée sur le sommet de
la pile d’exécution, puis il y a un branchement inconditionnel dans le
segment de code à l’adresse indiquée par l’opérande entier. Le
pointeur de pile est incrémenté de 1 et le compteur ordinal a comme
nouvelle valeur la valeur de l’opérande.
RET
le sommet de la pile est dépilé et cette valeur est affectée au
compteur ordinal. Le pointeur de pile est décrémenté de 1 et le
compteur ordinal a comme nouvelle valeur la valeur qui se trouvait
sur le sommet de la pile.
2.4 Les instructions de manipulation de la pile
Ces instructions peuvent être classées en deux catégories :
les instructions de manipulation du pointeur de pile ;
• les instructions modifiant le contenu de la pile et par extension le
contenu du segment de données.
•
Les instructions DECR et INCR permettent au programmeur de
changer la valeur du registre SP. DUPL, CONT, LOAD, PAIBP,
PUSH sont des instructions modifiant le sommet de la pile tandis que
ASSGN et STORE permettent de modifier n’importe quel mot
mémoire du segment de données.
DECR op le pointeur de pile SP est décrémenté de la valeur de
l’opérande entier. Le compteur ordinal est incrémenté de 3.
INCR op le pointeur de pile SP est incrémenté de la valeur de
l’opérande entier. Le compteur ordinal est incrémenté de 3. Avant
l’exécution de la première instruction d’un programme, SP vaut -1.
DUPLC le caractère au sommet de la pile est dupliqué et est placé sur
le sommet de la pile. Le pointeur de pile et le compteur ordinal sont
incrémentés de 1.
© Nino Silverio
9
La machine virtuelle MaP
DUPLI l’entier au sommet de la pile est dupliqué et est placé sur le
sommet de la pile. Le pointeur de pile et le compteur ordinal sont
incrémentés de 1.
DUPLN la valeur numérique au sommet de la pile est dupliquée et
est placé sur le sommet de la pile. Le pointeur de pile est incrémenté
de 2 et le compteur ordinal est incrémenté de 1.
CONTC le sommet de la pile est remplacé par un caractère conservé
à l’adresse indiquée par l’entier situé sur le sommet de la pile. Avant
d’exécuter cette instruction, le sommet de la pile doit donc contenir
l’adresse d’un mot mémoire contenant un caractère. Le compteur
ordinal est incrémenté de 1, le pointeur de pile reste inchangé.
CONTI le sommet de la pile est remplacé par un entier conservé à
l’adresse indiquée par l’entier situé sur le sommet de la pile. Avant
d’exécuter cette instruction, le sommet de la pile doit donc contenir
l’adresse d’un mot mémoire contenant un entier. Le compteur ordinal
est incrémenté de 1, le pointeur de pile reste inchangé.
CONTNle sommet de la pile est remplacé par un numérique
conservé à l’adresse indiquée par l’entier situé sur le sommet de la
pile. Avant d’exécuter cette instruction, le sommet de la pile doit
donc contenir l’adresse d’un mot mémoire contenant un numérique.
Le compteur ordinal et le pointeur de pile sont incrémentés de 1.
LOADC op le sommet de la pile est remplacé par op caractères
contigus conservés dans le segment de données et dont l’adresse de
départ est indiquée par le sommet de la pile. C’est l’opérande op qui
fixe le nombre de caractères à copier et le sommet de la pile doit
contenir l’adresse du premier caractère. C’est en fait une instruction
CONTC généralisée. Le pointeur de pile est incrémenté de op–1
unités. Le compteur ordinal est incrémenté de 3.
LOADI op
le sommet de la pile est remplacé par op entiers
contigus conservés dans le segment de données et dont l’adresse de
départ est indiquée par le sommet de la pile. C’est l’opérande op qui
fixe le nombre d’entiers à copier et le sommet de la pile doit contenir
l’adresse du premier entier. C’est en fait une instruction CONTI
généralisée. Le pointeur de pile est incrémenté de op–1 unités. Le
compteur ordinal est incrémenté de 3.
LOADN op le sommet de la pile est remplacé par op numériques
contigus conservés dans le segment de données et dont l’adresse de
départ est indiquée par le sommet de la pile. C’est l’opérande op qui
10
© Nino Silverio
Le jeu d’instructions de la machine MaP
fixe le nombre de numériques à copier et le sommet de la pile doit
contenir l’adresse du premier numérique. C’est en fait une instruction
CONTN généralisée. Le pointeur de pile est incrémenté de 2op – 1
unités. Le compteur ordinal est incrémenté de 3.
PUSHC op l’opérande op de type caractère est placé sur le
sommet de la pile. Le pointeur de pile croît d’une unité. Le compteur
ordinal est incrémenté de 2.
PUSHI op
l’opérande op de type entier est placé sur le sommet
de la pile. Le pointeur de pile croît d’une unité. Le compteur ordinal
est incrémenté de 3.
PUSHN op l’opérande op de type numérique est placé sur le
sommet de la pile. Le pointeur de pile croît de 2. Le compteur ordinal
est incrémenté de 5.
PAIBP op1 op2
(Push Address Indexed by BP) op1 de type
entier désigne le niveau d’imbrication de la variable référencée par
op2. L’opérande op2 indique un déplacement entier qui est ajouté à la
valeur du registre de base BP du niveau d’imbrication op1. Cette
adresse est chargée sur le sommet de la pile. Le pointeur de pile croît
d’une unité. Le compteur ordinal est incrémenté de 5. Ceci est une
instruction spécialisée servant à implémenter l’accès aux
identificateurs dans les langages de haut niveau supportant les
structures de blocs.
ASSGNC
le sommet de la pile contient une valeur de type
caractère elle-même empilée sur une adresse d’un mot-mémoire du
segment de données. L’effet de cette instruction est d’affecter la
valeur située sur le sommet à l’adresse placée juste en-dessous de
cette valeur. Par après, cette valeur et cette adresse sont dépilées (SP
diminue de 2) et le compteur ordinal est incrémenté de 1.
ASSGNI
le sommet de la pile contient une valeur de type entier
elle-même empilée sur une adresse d’un mot-mémoire du segment de
données. L’effet de cette instruction est d’affecter la valeur située sur
le sommet à l’adresse placée juste en-dessous de cette valeur. Par
après, cette valeur et cette adresse sont dépilées (SP diminue de 2) et
le compteur ordinal est incrémenté de 1.
ASSGNN
le sommet de la pile contient une valeur de type
numérique elle-même empilée sur une adresse d’un mot-mémoire du
segment de données. L’effet de cette instruction est d’affecter la
valeur située sur le sommet à l’adresse placée juste en-dessous de
© Nino Silverio
11
La machine virtuelle MaP
cette valeur. Par après, cette valeur et cette adresse sont dépilées (SP
diminue de 3) et le compteur ordinal est incrémenté de 1.
STOREC op est une instruction ASSGNC généralisée. L’opérande
op indique le nombre de caractères qui doivent être enlevés du
sommet de la pile et affectés dans une zone mémoire dont l’adresse
de début est le mot mémoire immédiatement en dessous des
caractères à transférer. Cette adresse ainsi que les valeurs à transférer
sont dépilées. Le pointeur de pile est décrémenté de op+1 unités. Le
compteur ordinal est incrémenté de 3.
STOREI op est une instruction ASSGNI généralisée. L’opérande
op indique le nombre d’entiers qui doivent être enlevés du sommet de
la pile et affectés dans une zone mémoire dont l’adresse de début est
le mot mémoire immédiatement en dessous des entiers à transférer.
Cette adresse ainsi que les valeurs à transférer sont dépilées. Le
pointeur de pile est décrémenté de op+1 unités. Le compteur ordinal
est incrémenté de 3.
STOREN op est une instruction ASSGNN généralisée. L’opérande
op indique le nombre de numériques qui doivent être enlevés du
sommet de la pile et affectés dans une zone mémoire dont l’adresse
de début est le mot mémoire immédiatement en dessous des
numériques à transférer. Cette adresse ainsi que les valeurs à
transférer sont dépilées. Le pointeur de pile est décrémenté de
2op + 1 unités. Le compteur ordinal est incrémenté de 3.
2.5 Les instructions d’entrée-sortie
Les instructions d’entrée-sortie permettent à la machine virtuelle de
communiquer avec le monde extérieur. Trois instructions de base,
déclinées selon le type des données (IN, OUT) sont prévues à cet
effet :
INC
le processeur attend que l’utilisateur ait entré un caractère au
clavier de l’ordinateur. Celui-ci est affecté à l’adresse indiquée par
l’entier se trouvant sur le sommet de la pile. Ensuite cette adresse est
dépilée. Le pointeur de pile est décrémenté de 1 tandis que le
compteur ordinal est incrémenté de 1.
INI
le processeur attend que l’utilisateur ait entré un entier au
clavier de l’ordinateur. Celui-ci est affecté à l’adresse indiquée par
l’entier se trouvant sur le sommet de la pile. Ensuite cette adresse est
dépilée. Le pointeur de pile est décrémenté de 1 tandis que le
compteur ordinal est incrémenté de 1.
12
© Nino Silverio
Le jeu d’instructions de la machine MaP
INN
le processeur attend que l’utilisateur ait entré un nombre
décimal (numérique) au clavier de l’ordinateur. Celui-ci est affecté à
l’adresse indiquée par l’entier se trouvant sur le sommet de la pile.
Ensuite cette adresse est dépilée. Le pointeur de pile est décrémenté
de 1 tandis que le compteur ordinal est incrémenté de 1.
OUTC le sommet de la pile est interprété comme un caractère et il
est affiché à l’écran à l’endroit du curseur. Ensuite cette valeur est
dépilée. Le pointeur de pile est décrémenté de 1 tandis que le
compteur ordinal est incrémenté de 1.
OUTI le sommet de la pile est interprété comme un entier et il est
affiché à l’écran à l’endroit du curseur. Ensuite cette valeur est
dépilée. Le pointeur de pile est décrémenté de 1 tandis que le
compteur ordinal est incrémenté de 1.
OUTN le sommet de la pile est interprété comme un numérique et il
est affiché à l’écran à l’endroit du curseur. Ensuite cette valeur est
dépilée. Le pointeur de pile est décrémenté de 2 tandis que le
compteur ordinal est incrémenté de 1. Par défaut, un tel nombre est
affiché sur 8 positions, dont 2 derrière le point décimal.
OUTSTR chaîne
tous les mots mémoire qui suivent cette
instruction dans le segment de code jusqu’au caractère ASCII 0
forment une chaîne de caractères qui est affichée à l’écran à l’endroit
du curseur. Le pointeur de pile n’est pas affecté. Le compteur ordinal
est incrémenté de 1 en plus du nombre de mots mémoire contenant
les caractères formant la chaîne, le caractère ASCII 0 compris.
2.6 Les instructions spéciales
CALLS op cette instruction permet d’effectuer un « appel
système». L’opérande entier indique l’appel système qui doit être
effectué. Les appels système possibles sont :
1
fixe le nombre de positions pour afficher un nombre (<I>,)
2
fixe le nombre de chiffres décimaux pour afficher un
nombre (<I>,)
3
fonction carré (<N>,<N>)
4
fonction racine carrée (<N>,<N>)
5
fonction sinus (<N>,<N>)
© Nino Silverio
13
La machine virtuelle MaP
6
fonction cosinus (<N>,<N>)
7
fonction tangente (<N>,<N>)
8
fonction arc sinus (<N>,<N>)
9
fonction arc cosinus (<N>,<N>)
10
fonction arc tangente (<N>,<N>)
11
renvoie un entier aléatoire compris entre 0 et 32767 inclus
(,<I>)
12
calcule la puissance N3 = N1 N2 (<N1><N2>,<N3>)
13
initialise le générateur de nombres aléatoires (<I>,)
14
(,<I>)
renvoie le nombre de secondes écoulées depuis le 1.1.1970
15
fonction valeur absolue (<N>,<N>)
16
fonction exponentielle (<N>,<N>)
17
fonction logarithme naturel (<N>,<N>)
18
indique si un nombre est impair ou non (<N>,<I>)
19
renvoie le nombre tronqué (sans partie fractionnaire)
(<N>,<N>)
20
renvoie le nombre arrondi (<N>,<N>)
21
renvoie un caractère correspondant au code ASCII donné
comme argument (<I>,<C>)
22
retourne le code ASCII correspondant à l’argument fourni
(<C>,<I>)
23
renvoie l’argument entier transformé en numérique
(<I>,<N>)
24
renvoie l’argument numérique transformé en entier
(<N>,<I>)
14
© Nino Silverio
L’assembleur MaP
25
renvoie le modulo (<I><I>,<I>)
26
renvoie le modulo (<N><N>,<N>)
27
renvoie la puissance I3 = I1I2 (<I1><I2>,<I3>)
Dans cette description, l’expression entre parenthèses formalise le
nombre et le type des arguments en entrée et en sortie. Le type d’un
argument est placé entre «<>». I désigne un entier, N un numérique
et C un caractère. Les arguments éventuels en entrée (avant la
virgule) précédent le résultat de la fonction (après la virgule).
Excepté pour les fonctions 11 et 14, au moment de l’appel, le sommet
de la pile d’exécution doit contenir les paramètres utiles qui sont
détruits à la fin de l’appel. Dans tous les cas, le compteur ordinal est
incrémenté de 3. A la fin de l’exécution de la fonction de l’appel
système, la valeur renvoyée éventuellement se trouve sur le sommet
de la pile.
RSTRBP
(ReSToReBP) le sommet de la pile est dépilé et cette
valeur est affectée au registre de base BP. Le pointeur de pile est
décrémenté de deux tandis que le compteur ordinal est incrémenté
d’une unité.
NEWBP op l’opérande entier désigne le niveau d’imbrication
permettant d’atteindre un BP préalablement sauvé. Le lien
dynamique est empilé avant le lien statique. Le pointeur de pile est
incrémenté de 1, le compteur ordinal est augmenté de 2.
HALT provoque l’arrêt de la machine virtuelle et redonne le
contrôle au système d’exploitation hôte.
3 L’assembleur MaP
3.1 Fonctionnement du système MaP
Le lecteur pourra réaliser des programmes écrits en langage MaP et
les exécuter sur son ordinateur personnel. Pour cela, il a à sa
disposition un programme capable d’exécuter les instructions MaP.
Ce programme s’appelle RUN. Lorsque ce dernier est exécuté sans
argument, il produit l’affichage suivant 1 :
Runtime MaP v3.0 Copyright N. Silverio CU/CRP-CU (7/10/99)
Format : run nom_de_fichier[.int] [-i]
© Nino Silverio
15
La machine virtuelle MaP
Ceci signifie que RUN s’attend à exécuter un programme exécutable
MaP. Le lecteur peut réaliser un tel programme exécutable de deux
manières différentes :
il crée manuellement un fichier exécutable ;
• il utilise pour ce faire le programme ASSEMBLE qui génère
directement le fichier exécutable.
•
La création manuelle d’un fichier exécutable, quoique réalisable, est
néanmoins déconseillée car elle est très délicate et recèle plein de
pièges. Elle ne sera pas décrite dans ce document.
ASSEMBLE est un programme capable de traduire un fichier
contenant des instructions MaP telles qu’elles ont été décrites dans la
section précédente en un code exécutable par RUN.
Le fichier contenant les instructions MaP écrites en clair, à l’aide
d’un éditeur de textes, s’appelle le fichier source. Le contenu de ce
fichier est encore appelé le programme source.
Le programme ASSEMBLE prend en entrée un tel fichier et produit
trois fichiers résultats : un fichier liste, un fichier exécutable par le
programme RUN et un fichier nécessaire au déboguage du
programme par un utilitaire adéquat.
Le fichier liste comprend les lignes du fichier source, mais
numérotées avec éventuellement un message d’erreur et, si le
programmeur le souhaite, une trace du contenu du segment de code.
Schématiquement, la situation est la suivante :
fichier source
.asm
ASSEMBLE
fichier liste
.lis
fichier exécutable
.int
fichier de déboguage
.dbg
1. La date indiquée entre parenthèses peut être plus récente que celle indiquée dans cette
trace d’exécution.
16
© Nino Silverio
L’assembleur MaP
Le programme ASSEMBLE, lorsqu’on l’exécute sans argument,
affiche le message suivant 1 :
Assembleur MaP v3.0 Copyright N. Silverio CU/CRP-CU (7/10/99)
Format : assemble nom_de_fichier[.asm]
Pour illustrer ce qui vient d’être dit, nous examinons un exemple de
manière plus détaillée. Il s’agit en fait d’un programme calculant la
somme de deux nombres entiers entrés au clavier de l’ordinateur. Ce
résultat est affiché à l’écran. Voici ce programme source :
{$d Ce programme calcule et affiche la somme de deux nombres entrés au
clavier }
n1
n2
somme
equ
equ
equ
0
1
2
; adresse de n1
; adresse de n2
; adresse de somme
debut_
incr
3
; réserver 3 mots mémoire pour n1, n2 et somme
outstr "Entrez le 1er nombre "
pushi n1
; placer l'adresse de n1 sur le sommet de la pile
ini
; la valeur lue au clavier est placée dans n1
outstr "Entrez le 2eme nombre "
pushi n2
; placer l'adresse de n2 sur le sommet de la pile
ini
; la valeur lue au clavier est placée dans n2
; la pile est vide
pushi somme ; placer l'adresse de la variable somme sur la pile
pushi n1
conti
; la valeur de la variable n1 se trouve sur la pile
pushi n2
conti
; la valeur de la variable n2 se trouve sur la pile
addi
; ces deux valeurs sont additionnées
assgni
outstr "La somme vaut : "
pushi somme
conti
outi
; le contenu de la variable somme est affiché
outstr "\n" ; passons à la ligne
halt
; facultatif
end debut_
Supposons que ce programme soit contenu dans le fichier
somme.asm. Si on le soumet à ASSEMBLE, celui-ci produira trois
fichiers, à savoir somme.lis, somme.exe et somme.dbg. Voici le
contenu du fichier somme.lis :
1 {$d Ce programme calcule et affiche la somme de deux nombres
entrés au clavier }
2
3 n1
equ
0
; adresse de n1
1. La date indiquée entre parenthèses peut être plus récente que celle indiquée dans cette
trace d’exécution.
© Nino Silverio
17
La machine virtuelle MaP
4 n2
equ
1
; adresse de n2
5 somme equ
2
; adresse de somme
6
7 debut_ incr 3
; réserver 3 mots mémoire pour n1, n2 et somme
8
9
outstr "Entrez le 1er nombre "
10
pushi n1 ; placer l'adresse de n1 sur le sommet de la pile
11
ini
; la valeur lue au clavier est placée dans n1
12
13
outstr "Entrez le 2eme nombre "
14
pushi n2 ; placer l'adresse de n2 sur le sommet de la pile
15
ini
; la valeur lue au clavier est placée dans n2
16
17
; la pile est vide
18
19
pushi somme ; placer l'adresse de la variable somme sur la
pile
20
pushi n1
21
conti
; la valeur de la variable n1 se trouve sur la pile
22
pushi n2
23
conti
; la valeur de la variable n2 se trouve sur la pile
24
addi
; ces deux valeurs sont additionnées
25
assgni
26
27
outstr "La somme vaut : "
28
pushi somme
29
conti
30
outi
; le contenu de la variable somme est affiché
31
outstr "\n" ; passons à la ligne
32
halt
; facultatif
33
end debut_
34
Assemblage sans erreurs
Code généré :
0
INCR3
3
OUTSTR"Entrez le 1er nombre "
16
PUSHI0
19
INI
20
OUTSTR"Entrez le 2eme nombre "
33
PUSHI1
36
INI
37
PUSHI2
40
PUSHI0
43
CONTI
44
PUSHI1
47
CONTI
48
ADDI
49
ASSGNI
50
OUTSTR"La somme vaut : "
60
PUSHI2
63
CONTI
64
OUTI
65
OUTSTR"
68
HALT
69
HALT
L'exécution débute à l'adresse 0
18
© Nino Silverio
L’assembleur MaP
Pour exécuter le programme assemblé, il suffit de taper la commande
:
RUN somme
On obtient, par exemple :
Runtime MaP v3.0 Copyright N. Silverio CU/CRP-CU (7/10/99)
Exécution en cours...
Entrez le 1er nombre 6
Entrez le 2eme nombre -3
La somme vaut : 3
Exécution terminée
Le fichier exécutable se présente ainsi :
0 27 0 0 0 3 0 46 0 69 110 116 114 101 122 32 108 101 32 49 101 114 32
110 111 109 98 114 101 32 0 0 0 49 0 0 0 0 0 25 0 46 0 69 110 116 114
101 122 32 108 101 32 50 101 109 101 32 110 111 109 98 114 101 32 0 0
49 0 0 0 1 0 25 0 49 0 0 0 2 0 49 0 0 0 0 0 9 0 49 0 0 0 1 0 9 0 0 0 4
0 46 0 76 97 32 115 111 109 109 101 32 118 97 117 116 32 58 32 0 0 49
0 0 0 2 0 9 0 44 0 46 0 10 13 0 0 23 0 23 0
Pour des raisons pédagogiques, ASSEMBLE génère un fichier
exécutable qui est en fait un fichier texte contenant uniquement des
nombres exprimés en décimal et séparés par des espaces. Le premier
nombre décimal représente l’adresse de la première instruction à
exécuter lorsque le programme en question est chargé dans le
segment de code. Tous les autres nombres représentent un octet. Un
mot mémoire du segment de code ou de données se compose de
plusieurs octets. C’est ainsi que la taille d’un mot mémoire du
segment de code est de deux octets alors qu’un mot mémoire du
segment de données est composé de quatre octets.
Dans l’exemple proposé ci-dessus, les six octets des trois premiers
mots mémoire du segment de code ont les valeurs respectives : 27 0 0
0 3 0. Le premier mot mémoire logé à l’adresse 0 se compose donc
des deux octets 27 et 0. Au début du chapitre 3, nous avons vu les
codes attribués à chacune des instructions. Dans ce tableau, nous
pouvons lire que le code 27 correspond à l’instruction INCR.
Comment faut-il alors lire les deux octets ? Le premier est l’octet de
poids faible, alors que le second est l’octet de poids fort. La valeur
résultante est donc: 27 + 0 ⋅ 256 = 27 . Dans notre cas, le deuxième
octet d’un mot mémoire contenant une instruction aura toujours
comme valeur 0 car le nombre d’instructions est inférieur à 256 ! Si
un octet a une valeur supérieure à 127, il est représenté par son
complément à 256. Si par exemple, dans le code généré, nous voyons
un octet de valeur -5, cela signifie qu’il représente le nombre 251 !
© Nino Silverio
19
La machine virtuelle MaP
Un entier est codé sur deux mots mémoire du segment de code et un
numérique sur quatre. Comme le processeur MaP a reconnu
l’instruction INCR, il sait qu’elle admet un argument entier et par
conséquent va lire les quatre octets suivants 0 0 3 0. Les deux
premiers octets sont le mot mémoire de poids fort (valeur 65536) et
les deux suivants le mot mémoire de poids faible. Chaque mot
mémoire est à son tour une paire (octet poids faible, octet poids fort).
Le tableau qui suit contient quelques exemples illustrant comment
des nombres entiers sont codés :
octets
mots mémoire
entier
0 et 3
3
0 0 96 –22
0 et 96 + 234 ⋅ 256 = 60000
60000
9 0 –64 39
9 et 10176
9 ⋅ 65536 + 10176 = 600000
0030
Les caractères sont représentés sous formes de nombres entiers en
utilisant la codification ASCII. Chaque mot mémoire pouvant
contenir deux octets, il suffit d’interpréter chacun des octets comme
un caractère. Voici la signification des 11 mots mémoire suivants:
69 110 116 114 101 122 32 108 101 32 49 101 114 32 110 111 109 98 114
101 32 0 0 0
E
n
t
r
e
z
l
e
1
e
r
n
o
m
b
r
e
Un mot mémoire incomplétement utilisé est rempli par un 0 et une
chaîne de caractères doit se terminer par un mot mémoire de valeur 0.
Les nombres décimaux (numériques) sont codés sur huit octets. Nous
ne détaillerons pas davantage le fonctionnement de cette
codification.
Le programme RUN peut être exécuté avec l’option «-i» qui a pour
effet d’indiquer à la fin de l’exécution l’état des trois registres PC, BP
et SP, l’espace mémoire occupé par le programme dans le segment de
code ainsi que l’espace mémoire maximal utilisé dans le segment de
données.
run test -i
Runtime MaP v3.0 Copyright N. Silverio CU/CRP-CU (7/10/99)
Exécution en cours...
Entrez le 1er nombre 5
Entrez le 2eme nombre 8
La somme vaut : 13
Exécution terminée sp(2) pc(68) bp(0)
code (70/20000) données (5/14000)
20
© Nino Silverio
L’assembleur MaP
3.2 Syntaxe du programme ASSEMBLE
Le programme ASSEMBLE est ce que l’on appelle dans le jargon
informatique un assembleur. Il s’agit d’un programme dans lequel
chaque instruction représente effectivement une instruction machine.
Cette instruction est alors écrite par le programmeur à l’aide d’un
code mnémonique lui permettant de mieux lire son programme. Dans
un langage plus évolué (Pascal, C, etc.) chaque instruction est
traduite en un bloc d’instructions machine, de quelques unes à
plusieurs dizaines voire des centaines !
En utilisant un assembleur, le programmeur a généralement la facilité
de pouvoir travailler avec des adresses et noms symboliques et de
pouvoir utiliser des pseudo-instructions.
Une ligne d’un programme assembleur MaP débute par :
une étiquette facultative, suivie éventuellement du code
mnémonique d’une instruction ou de la pseudo-instruction END
avec leurs opérandes éventuels;
• un identificateur suivi de la pseudo-instruction EQU et de la
valeur associée;
• le code mnémonique d’une instruction ou de la pseudo-instruction
END avec leurs opérandes éventuels.
•
Une étiquette sert à désigner de manière symbolique une adresse
mémoire. Elle doit débuter par une lettre, suivie de caractères
alphanumériques ou du symbole «_». Une étiquette doit se terminer
par le symbole «_». Chaque étiquette référencée dans un
programme doit y être définie.
Un nom symbolique sert à désigner une valeur. Il doit débuter par
une lettre, suivie de caractères alphanumériques ou du symbole «_».
Un symbole ne doit pas se terminer par le symbole «_». La valeur
associée à un nom symbolique est définie à l’aide de la pseudoinstruction EQU. Cette valeur en question doit suivre la pseudoinstruction EQU. Exemples :
nombre_lignes
pi
lettre_a
autre_lettre_a
nom
EQU
EQU
EQU
EQU
EQU
25
3.1415
’A’
’\65’
"Nino Silverio"
La virgule décimale est représentée par le point. Une constante
numérique dans laquelle figure un point décimal est considérée
comme étant une donnée numérique.
© Nino Silverio
21
La machine virtuelle MaP
Une valeur de type caractère est placée entre « ’ ». Pour représenter
un caractère non représentable, il suffit de concaténer son code
ASCII derrière le symbole «\ ». Si la chaîne de caractères doit
contenir le caractère « ’ », celui-ci doit être doublé.
Une valeur de type chaîne de caractères est placée entre « " ». Tous
les caractères imprimables peuvent y être utilisés. Si la chaîne de
caractères doit contenir le caractère «" », celui-ci doit être doublé.
Exemple :
une_quote
EQU
""""
Une instruction assembleur peut référencer un symbole défini
ultérieurement dans le programme.
La pseudo-instruction END indique la fin logique du programme et
provoque la génération de l’instruction machine HALT. END doit
être suivi d’une adresse symbolique désignant la première instruction
logique du programme, c’est-à-dire l’adresse par laquelle l’exécution
doit débuter.
Pour augmenter la lisibilité de son programme, le programmeur doit
le compléter avec des commentaires. Un commentaire est un texte
que l’on place dans le fichier source pour faciliter sa compréhension.
L’assembleur les élimine et ils n’ont aucune influence sur la vitesse
d’exécution du programme. Avec l’assembleur MaP, les
commentaires peuvent être placés :
en fin de ligne précédés du symbole « ; » ;
• n’importe où en espace est permis et il peuvent s’étendre du
plusieurs lignes s’ils sont délimités par une paire de symboles
« { } ».
•
Il existe encore une directive d’assemblage {$d} ou {$D} qui
provoque, à la fin de l’assemblage, l’affichage du code machine
généré. Ce code figurera aussi dans le fichier .lis produit.
3.3 Liste des messages d’erreur de l’assembleur MaP
Voici la liste des messages d’erreur pouvant survenir en travaillant
avec l’assembleur MaP :
Commentaire incorrect
Chaîne > MAX_CHAINE caractères
Chaîne de caractères pas terminée
22
© Nino Silverio
L’assembleur MaP
Caractère inconnu dans la source
Etiquette ambigue
Etiquette(s) non définie(s)
EQU manque
EQU non défini
Valeur de la constante absente
Identificateur ambigu
Identificateur inconnu
Une étiquette manque
Erreur de syntaxe
END manque
END déjà défini !
Type incorrect
Code opératoire inconnu
...ne devrait pas arriver
3.4 Liste des messages d’erreur de l’interprète d’exécution Run
Code généré déborde du segment de code
La pile déborde du segment de données
Division par 0
Code opératoire non défini
3.5 Exercices
1) Réaliser un programme en assembleur MaP qui calcule le produit
de deux nombres entiers entrés au clavier.
2) Réaliser un programme en assembleur MaP qui calcule le produit
de deux numériques entrés au clavier.
3) Réaliser un programme en assembleur MaP qui calcule et affiche
la moyenne de trois nombres décimaux entrés au clavier de
l’ordinateur.
© Nino Silverio
23
La machine virtuelle MaP
4) Réaliser un programme en assembleur MaP qui affiche le prix
d’un article TTC après avoir entré le prix hors TVA et le taux de
TVA.
5) Expliquer en détail ce que fait le programme suivant :
a
EQU 0
a_la_ligne_ OUTSTR "\n"
RET
debut_
INCR 2 ; une variable numérique
PUSHI a
INN
PUSHI 3
CALLS 2
PUSHI a
CONTN
OUTN
CALL a_la_ligne_
PUSHI a
CONTN
PUSHN 0.
LSN
JF bizarre_
PUSHI a
CONTN
NEGN
OUTN
JP fin_
bizarre_
PUSHI a
CONTN
OUTN
fin_
END debut_
6) Expliquer en détail ce que fait le programme suivant :
a
EQU 0
b
EQU 2
a_la_ligne_ OUTSTR "\n"
RET
debut_
INCR 4 ; deux variables numériques
PUSHI a
INN
PUSHI b
INN
PUSHI 3
CALLS 2
PUSHI a
CONTN
OUTN
CALL a_la_ligne_
PUSHI b
CONTN
OUTN
CALL a_la_ligne_
PUSHI a
CONTN
PUSHI b
CONTN
LSN
JF bizarre_
PUSHI b
24
© Nino Silverio
L’assembleur MaP
bizarre_
fin_
CONTN
OUTN
JP fin_
PUSHI a
CONTN
OUTN
END debut_
© Nino Silverio
25
La machine virtuelle MaP
26
© Nino Silverio
Téléchargement