01 - Simulateur
Information
Deadline: le 17 mars
Points: 2 points de la note finale
Lien: https://classroom.github.com/a/s3tmWRAY
Téléchargement tardif: 1p/jour (maximum 2 jours)
Objectifs
Le but de ce travail est de vous familiariser avec les concepts suivants:
- développement de base de Kotlin
- utilisation de structures de données dans Kotlin
- utilisation des paramètres de la ligne de commande
- lecture de données à partir de fichiers
- division et traitement de chaînes
- le mode de fonctionnement d'un processeur simple
Description du devoir
Le but de ce devoir est de simuler un CPU. Il s'agit d'un processeur très simple, qui a un registre, appelé R, et un espace de pile infini, appelé STACK. Le CPU effectue tous les calculs en utilisant des nombres entiers signés. Il ne sait pas comment gérer les nombres à virgule flottante.
Ensemble d'instructions
L'ensemble d'instructions est divisé en cinq catégories d'instructions:
- No Action - ces instructions n'effectuent aucune action
- Memory - ces instructions permettent au CPU d'interagir avec la pile (la mémoire)
- Math - ces instructions permettent au CPU d'effectuer des opérations mathématiques
- Flow - ces instructions permettent au CPU d'effectuer des if et des boucles
- Pseudo Debug - ces instructions sont utilisées pour le débogage
Dans les exemples suivants, on utilisera le ;
pour marquer les commentaires dans les fichiers .asm
. Les fichiers du devoir ne contiendront pas de commentaires, on les utilise ici seulement pour vous donner plusieurs explications.
No Action
Instruction | Paramètres | Description | Exemple |
---|---|---|---|
nop | pas de paramètres | Elle ne fait rien, étant utilisée seulement pour les commentaires | nop |
Memory
Instruction | Paramètres | Description | Exemple |
push | numéro entier | Elle ajoute le paramètre sur la pile |
|
pop | - | Elle extrait le premier nombre de la pile; en d'autres termes, elle supprime le premier nombre de la pile |
|
load | - | Elle extrait le premier nombre de la pile et le met dans R (le registre du processeur) |
|
store | - | Elle ajoute le nombre de R (le registre du processeur) dans la pile |
|
Math
Instruction | Paramètres | Description | Exemple |
add | - | Elle extrait deux nombres de la pile, fait l'addition, et ajoute le résultat à la pile |
|
sub | - | Elle extrait deux nombres de la pile, fait la soustraction, et ajoute le résultat à la pile |
|
mul | - | Elle extrait deux nombres de la pile, fait la multiplication, et ajoute le résultat à la pile |
|
div | - | Elle extrait deux nombres de la pile, fait la division en utilisant une division entière et ajoute le résultat à la pile |
|
mod | - | Elle extrait deux nombres de la pile, calcule le reste de leur division et ajoute le résultat à la pile |
|
Flow
Instruction | Paramètres | Description | Exemple |
jump | numéro entier / étiquette | Au lieu d'exécuter l'instruction suivante, la CPU prendra l'instruction: a) au numéro de ligne spécifié comme paramètre ou b) de l'étiquette spécifiée par le paramètre |
|
jumpz | numéro entier / étiquette | Si la valeur supérieure de la pile est zéro, cela fonctionne de la même manière que jump, sinon cela ne fait rien |
|
jumpnz | numéro entier / étiquette | Si la valeur supérieure de la pile n'est pas zéro, cela fonctionne de la même manière que jump, sinon cela ne fait rien |
|
Pseudo Debug
Instruction | Paramètres | Description | Exemple |
print | - | Affiche le numéro du sommet de la pile |
|
stack | - | Affiche la pile |
|
Erreurs
Le fichier que le simulateur de processeur exécute peut contenir des erreurs. Lorsque le simulateur rencontre une erreur, il ignore cette instruction et continue l'exécution avec la ligne suivante.
Le format d'erreur général est:
ERROR (nom_instruction): texte d'erreur
Les erreurs doivent être affichés exactement comme dans l'exemple suivant:
Erreur | Signification | Exemple |
unknown instruction | le simulateur a trouvé une instruction qu'il ne connaît pas |
|
stack underflow | le simulateur essaie d'exécuter une instruction qui extrait certaines valeurs de la pile, mais la pile n'a pas assez de valeurs |
|
unable to open file filename | le simulateur tente d'ouvrir un fichier qu'il ne peut pas ouvrir |
|
undefined label | le simulateur essaie de faire un jump à une étiquette qui n'est pas définie |
|
invalid jump address | le simulateur essaie de faire un jump à une adresse (numéro de ligne) qui n'existe pas dans le fichier |
|
Conseils d'implantation
Le devoir comprend beaucoup de fonctionnalités à implémenter, donc on vous suggère de suivre les étapes suivantes:
- Lire le contenu du fichier dans le string
s
et implanter l'erreurno file
- Séparer l'entrée lue par
\n
(\r\n
pour Windows, assurez-vous de l'avoir changé avant de transférer sur git), en utilisant la fonctionsplit()
- Séparer chaque ligne par
- Implanter l'erreur
unknown instruction
- Implanter les instructions
push
etpop
en utilisant un array de numéros pour la pile - Implanter les fonctions mathématiques
- Implanter les autres instructions
Bonus
Pour 2p supplémentaires, implantez une mémoire pour le CPU. Le simulateur recevra un autre paramètre dans la ligne de commande qui représente le nombre d'emplacements de mémoire disponibles.
Implantez les instructions de mémoire suivantes:
Instruction | Paramètres | Détails |
write | - | Extrait 2 numéros de la pile et écrit le premier à l'emplacement de la mémoire défini par le deuxième |
read | - | Extrait un numéro de la pile et lit un numéro de l'emplacement de la mémoire défini par le premier numéro, en ajoutant le deuxieme a la pile |
Le bonus ne sera attribué que si tous les autres tests réussissent.
Exécution du programme
Pour compiler et exécuter le programme, on va utiliser gradle.
Pour compiler le programme:
$./gradlew build
Pour exécuter le programme:
$./gradlew run --args="<nom_du_fichier_d'entrée>"
Exemple
Pour le fichier .asm
suivant (les fichiers du devoir ne contiendront pas de commentaires, on les a mis ici seulement pour expliquer ce que les instructions font):
push 20 ;ajoute 20 à la pile, la pile est [ 20 ]
push 35 ;ajoute 35 à la pile, la pile est [ 20 35 ]
push 9 ;ajoute 9 à la pile, la pile est [ 20 35 9 ]
stack ;affiche les contenus de la pile
load ;extrait le sommet de la pile (9 dans notre cas) et le met dans R, la pile est [ 20 35 ] et R est [9]
add ;ajoute les premiers deux numéros de la pile et met le résultat sur la pile, la pile est [ 55 ] et R est [9]
print ;affiche le premier numéro de la pile
store ;met la valeur de R sur la pile, la pile est [ 55 9 ] et R est [9]
stack ;affiche la pile
On aura la sortie suivante (sans les commentaires):
[ 20 35 9 ]
55
[ 55 9 ]
Règles
- Vous ne pouvez pas utiliser RegEx ou toute autre bibliothèque qui utilise des expressions régulières (sauf \n\r? pour séparer les lignes d'entrée de la source).
- Le code source doit être indenté (-0.1p).
- Vous devez expliquer en détail dans le Readme.md comment vous avez rédigé les devoirs (-1p)
Les devoirs sont individuels. Toute tentative de tricher entraînera 0p pour les devoirs. Un système anti-copie automatisé sera utilisé.
Questions
Si vous avez des questions concernant les devoirs, posez-les en publiant un problème sur le github repository pour les questions avec le format du titre [simulateur]<titre de votre question>
. Vous aurez besoin d'un compte github pour cela.
Ne postez pas de code. Cette action est considéré comme tentative de tricher et alors vous obtiendrez 0p pour le devoir.
Si vous souhaitez recevoir un e-mail lorsque des problèmes sont publiés ou lorsqu'il y a de nouveaux messages, accédez au repository pour les questions et cliquez sur Regarder.