Circuits et architecture TD 7 : assembleur LC-3

publicité
Université Paris Diderot
Master 1
Circuits et architecture
TD 7 : assembleur LC-3
On va utiliser un sous-ensemble de l’assembleur LC-3 que vous avez vu
en cours. Il est composé des instructions ADD, AND, BR, JMP, LDR, NOT,
STR (voir document joint). Nous avons implanté ces instructions dans un
circuit tkgate disponible sur
http://www.liafa.jussieu.fr/~amicheli/Ens/Archi/
L’architecture LC-3 et ce circuit seront utilisés à l’occasion du projet que
vous aurez à rendre.
Exercice 1
Comment initialiser un registre à la valeur zéro ? Donner l’instruction
assembleur puis son codage hexadécimal.
Exercice 2
Comment mettre une constante, par exemple 2007, dans un registre ?
Donner l’instruction assembleur puis son codage hexadécimal.
Exercice 3
Avec la technique précédente, combien d’instructions sont nécessaires
pour une constante arbitraire sur 16 bits ? Quelle autre technique peut-on
utiliser ?
Exercice 4
Avec les instructions dont on dispose, donner toutes les façons de coder
l’instruction NOP.
Exercice 5
Programmer une séquence de boot qui remet à zéro les registres et (une
partie de) la mémoire.
Exercice 6
Programmer la soustraction, c’est-à-dire une séquence qui code R2 ← R0
− R1.
1
Exercice 7
Faites un programme qui calcule les 12 premiers termes de la suite de
Fibonacci grâce à une boucle.
Exercice 8
On souhaite programmer la somme d’un tableau. L’adresse du début du
tableau est stockée dans R0 et la somme doit être calculée dans R1. On
suppose qu’on peut modifier tous les registres. Programmer la somme d’un
tableau si :
1. on suppose que la fin du tableau est marquée par un octet nul,
2. on suppose que la taille du tableau est stockée dans R2.
On désire maintenant implémenter le changement de contexte, afin de
pouvoir faire des appels de fonctions et (en exagérant un peu...) du multitâches.
Dans ce but, nous allons implémenter une pile en mémoire. Par convention, (aujourd’hui) M em[0] est le sommet de pile (adresse de la première case
vide), la première case de la pile est M em[1], la seconde M em[2]... jusqu’à
M em[M em[0]]. La pile grandit donc vers le haut.
Exercice 9
Programmer la sauvegarde du contexte, c’est-à-dire le fait de placer sur
la pile les 7 registres R1, R2, . . . , R7.
Pourquoi ne peut-on pas sauvegarder les 8 registres dans la pile ?
Exercice 10
Programmer la restauration du contexte : les 7 registres R1, R2, . . . , R7
doivent reprendre leurs valeurs initiales.
2
Solutions
Solution 1 : Avec AND et la valeur immédiate zéro.
AND R0, R0, 0
Noté aussi AND R0, R0, #0
Pour R0 : 0101 000 000 1 00000
x5020
Pour R1 : 0101 001 001 1 00000
x5260
...
Pour R4 : 0101 100 100 1 00000
x5920
...
Pour R7 : 0101 111 111 1 00000
x5FE0
Solution 2 : Les seules valeurs immédiates dont on dispose sont sur 5
bits signées, donc dans l’intervalle [−16, 15]. Mais on peut aussi multiplier
un registre par deux avec ADD...
Noter que 2007 = 2048 − 32 − 8 − 1 = 111 1101 01112 On peut aussi faire
les divisions par 2 successives.
Assembleur
AND R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
ADD R0, R0,
0
7
R0
R0
R0
R0
13
R0
R0
R0
R0
5
binaire
0101 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
0001 000
000
000
000
000
000
000
000
000
000
000
000
000
1 00000
1 00111
000 000
000 000
000 000
000 000
1 01101
000 000
000 000
000 000
000 000
1 00110
hexa
x5020
x1027
x1000
x1000
x1000
x1000
x102D
x1000
x1000
x1000
x1000
x1026
Solution 3 : Si on le fait naïvement, comme plus haut, il faut 1+5∗3+1 =
17 lignes. On peut gagner une ligne si on utilise “l’extension signée” pour le
bit de poids fort.
L’autre technique, vue en cours, consiste à mettre les constantes dans
un segment de données, qui se trouve en mémoire à la suite du programme.
On peut ensuite utiliser l’instruction de chargement LD (load), dont le mode
d’adressage est relatif au PC (PCoffset9).
Solution 4 : BR *** 000000000
BR 000 ********* qui ne peut pas s’écrire en assembleur en fait, mais peut
s’écrire en binaire (parce que BR est interprété comme BRnzp ...)
3
Les solutions suivantes ne sont pas tout à fait correctes : elles modifient les
codes de conditions NZP
ADD Ri, Ri, 0 pour i = 0, . . . , 7
AND Ri, Ri, 11111 pour i = 0, . . . , 7
AND Ri, Ri, Ri pour i = 0, . . . , 7
Faire deux NOT successif sur le même registre est plus risqué, en cas d’interruption...
Solution 5 : Le début est comme l’exo 1. Pour la mémoire, on a besoin
de 2 registres : un pour l’adresse et un pour la valeur 0.
AND R0, R0, 0
AND R1, R1, 0
STR R0, R1, 0
ADD R1, R1, 1
BRnp -3
Mem[R1+0] ← R0
revient à STR si R1 n’est pas nul
Bien sûr, si l’on fait comme cela, le programme (et le système d’exploitation)
vont être écrasés... Mais on peut aussi commencer avec une autre valeur de
R1. Ou décrémenter R1 jusqu’à zéro. On peut aussi utiliser un autre registre
pour faire des soustractions et des comparaisons.
Noter que BRnp -3 se code
0000 101 111111101
revoir aussi la sémantique du saut : “incremented PC”
Solution 6 : vu en cours :
NOT R1,R1
ADD R1, R1, 1
ADD R2, R0, R1
Attention, si l’on veut retrouver R1 à la fin, il faut ensuite
NOT R1,R1
ADD R1, R1, 1
On pourrait aussi n’ajouter le 1 qu’à R2
Ou bien, sans modifier les registres sources :
AND R2 R2 0
ADD R2 R1 0
NOT R2 R2
ADD R2 R2 1
ADD R2 R2 R0
on peut gagner une instruction en faisant -1 avant le not, au lieu de +1
après :
4
AND
ADD
NOT
ADD
R2
R2
R2
R2
R2 0
R1 -1
R2
R2 R0
Ou encore (mieux) :
NOT R2,R1
ADD R2,R2,#1
ADD R2,R2,R0
Solution 7 :
AND R0,R0,0
AND R1,R1,0
AND R2,R2,0
ADD R2,R2,#1 ; premier élément non nul de la suite
ADD R0,R0,#12 ; compteur de boucle
boucle :
ADD R3,R1,R2 ; calcul du nouvel élément
ADD R1,R2,0
ADD R2,R3,0
ADD R0,R0,#-1 BRp boucle ; c’est-à-dire BRp -5
Solution 8 :
1. LDR R2 R0 0
ADD R0 R0 1
ADD R1 R2 R1
ADD R2 R2 0
BRnp -5
2. LDR R1 R0 0
ADD R1 R2 R1
ADD R0 R0 1
ADD R2 R2 -1
BRp -5
Solution 9 : Sauvegarde :
AND R0,R0,0
LDR R0,R0,0 ; adresse du sommet de pile
STR R1,R0,0
STR R2,R0,1 ; le décalage (offset) évite de modifier R0 à chaque fois...
STR R3,R0,2
STR R4,R0,3
STR R5,R0,4
STR R6,R0,5
5
STR R7,R0,6
ADD RO,RO,7
AND R1,R1,0
STR R0,R1,0 ; mem[0] <- nouveau sommet de pile
On a besoin de R0 pour aller chercher le sommet de pile.
Solution 10 : Restauration :
AND R1,R1,0
LDR R0,R1,0 ; adresse du sommet de pile
ADD R0,R0,#-7 ;
STR R0,R1,0 ; on modifie tout de suite le sommet de pile, pour libérer R1
LDR R1,R0,0
LDR R2,R0,1 ; le décalage (offset) évite de modifier R0 à chaque fois...
LDR R3,R0,2
LDR R4,R0,3
LDR R5,R0,4
LDR R6,R0,5
LDR R7,R0,6
6
Téléchargement