Une rapide présentation de l'assembleur MIPS.
Écrire un programme qui prend en argument (sur la ligne
de commande) une suite de valeurs entières ou réelles, avec au plus 5
valeurs de chaque type, et qui produit en sortie un programme en
assembleur MIPS qui affiche tous les entiers sur une première ligne et
tous les réels sur une deuxième ligne. Par exemple, pour la suite 5 4.56
8.6 12 0.25 8 8, le programme produira en sortie le programme assembleur
ci-dessous dont l'exécution affichera :
5 12 8 8
4.56 8.6 0.25
Programme assembleur :
.text
main:
li $v0,1 # appel système pour afficher un entier
li $a0,5 # chargement de l'entier à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,1 # appel système pour afficher un entier
li $a0,12 # chargement de l'entier à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,1 # appel système pour afficher un entier
li $a0,8 # chargement de l'entier à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,1 # appel système pour afficher un entier
li $a0,8 # chargement de l'entier à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,4 # appel système pour afficher un retour à la ligne
la $a0,str1 # chargement de l'adresse de la chaîne
syscall # affichage
li $v0,2 # appel système pour afficher un réel
l.s $f12,temp0 # chargement du réel à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,2 # appel système pour afficher un réel
l.s $f12,temp1 # chargement du réel à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,2 # appel système pour afficher un réel
l.s $f12,temp2 # chargement du réel à afficher
syscall # affichage
li $v0,4 # appel système pour afficher un blanc
la $a0,str2
syscall # affichage
li $v0,4 # appel système pour afficher un retour à la ligne
la $a0,str1 # chargement de l'adresse de la chaîne
syscall # affichage
# exit
li $v0,10 # on sort du programme proprement
syscall
.data
temp0: .float 4.560000
temp1: .float 8.600000
temp2: .float 0.250000
str1: .asciiz "\n"
str2: .asciiz " "
L'objectif de cet exercice est d'écrire un petit compilateur pour le langage EXPR des expressions arithmétiques avec variables dont vous trouverez la grammaire ci-dessous. Ce petit compilateur doit produire du code MIPS. Pour simplifier le problème et se concentrer davantage sur le génération de code MIPS, le code pour les phases d'analyse lexicale, d'analyse syntaxique et de génération de code intermédiaire (code à 3 adresses), est donné. Il s'agira donc de compléter ce code et en particulier d'ajouter la partie correspondante à la phase de génération de code MIPS.
Grammaire du langage EXPR :
L -> I ; L | I
I -> id = E | print id
E -> E + E | E - E | E * E | - E | ( E ) | id | num
Le code du compilateur à compléter.
NB : Dans ce code, la structure de données utilisée pour représenter la table des symboles est peu efficace, mais ceci n'a pas d'importance dans le contexte de cet exercice.
2*(3+2)+1
: .text
main:
# calcul de 3+2
lw $t0,temp2 # chargement de 3 dans le registre t0
lw $t1,temp3 # chargement de 2 dans le registre t1
add $t0,$t0,$t1 # t0 = t0 + t1
sw $t0,temp5 # écriture du résultat en mémoire à l'adresse dont le
label est temp5
# transfert du résultat de temp5 à temp6 ( E -> ( E ) )
lw $t0,temp5
sw $t0,temp6
# calcul de 2*(3+2)
lw $t0,temp1
lw $t1,temp6
mul $t0,$t0,$t1
sw $t0,temp7
# calcul de 2*(3+2)+1
lw $t0,temp7
lw $t1,temp4
add $t0,$t0,$t1
sw $t0,temp8
# affichage du résultat
li $v0,4 # appel système pour afficher une chaine
la $a0,str # chargement de l'adresse de la chaine
syscall # affichage de la chaine
li $v0,1 # appel système pour afficher un entier
lw $a0, temp8 # chargement de l'entier à afficher
syscall # affichage
# exit
li $v0,10 # on sort proprement du programme
syscall
.data
temp1: .word 2 # 2 est stocké en mémoire à l'adresse dont le label est
temp2
temp2: .word 3
temp3: .word 2
temp4: .word 1
temp5: .word 0
temp6: .word 0
temp7: .word 0
temp8: .word 0
str: .asciiz "le résultat est "
.text
main:
la $t0, temp # chargement de l'adresse du premier temporaire dans t0
# calcul de 3+2
lw $t1,4($t0) # 3 se trouve à l'adresse du premier temporaire + 4
octets
lw $t2,8($t0) # 2 se trouve à l'adresse du premier temporaire + 8
octets
add $t1,$t1,$t2 # t1 = t1 + t2
sw $t1,16($t0) # écriture du résultat en mémoire à l'adresse de départ
+ 16 octets
# transfert du résultat ( E -> ( E ) )
lw $t1,16($t0)
sw $t1,20($t0)
# calcul de 2*(3+2)
lw $t1,($t0)
lw $t2,20($t0)
mul $t1,$t1,$t2
sw $t1,24($t0)
# calcul de 2*(3+2)+1
lw $t1,24($t0)
lw $t2,12($t0)
add $t1,$t1,$t2
sw $t1,28($t0)
# affichage du résultat
li $v0,4 # appel système pour afficher une chaine
la $a0,str # chargement de l'adresse de la chaine
syscall # affichage de la chaine
li $v0,1 # appel système pour afficher un entier
lw $a0,28($t0) # chargement de l'entier à afficher
syscall # affichage
# exit
li $v0,10 # on sort proprement du programme
syscall
.data
temp: .word 2, 3, 2, 1, 0, 0, 0, 0
str: .asciiz "le résultat est "