Aller au contenu principal
Version: 2024

01 - Simulateur

Information

info

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:

  1. développement de base de Kotlin
  2. utilisation de structures de données dans Kotlin
  3. utilisation des paramètres de la ligne de commande
  4. lecture de données à partir de fichiers
  5. division et traitement de chaînes
  6. 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:

  1. No Action - ces instructions n'effectuent aucune action
  2. Memory - ces instructions permettent au CPU d'interagir avec la pile (la mémoire)
  3. Math - ces instructions permettent au CPU d'effectuer des opérations mathématiques
  4. Flow - ces instructions permettent au CPU d'effectuer des if et des boucles
  5. Pseudo Debug - ces instructions sont utilisées pour le débogage
info

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

InstructionParamètresDescriptionExemple
noppas de paramètresElle ne fait rien, étant utilisée seulement pour les commentairesnop

Memory

InstructionParamètresDescriptionExemple
pushnuméro entier Elle ajoute le paramètre sur la pile
   ; la pile est [ ]
push 1
; la pile est [ 1 ]
push 2
;la pile est [ 1 2 ]
pop - Elle extrait le premier nombre de la pile; en d'autres termes, elle supprime le premier nombre de la pile
   ;la pile est [ 1 2 ] 
pop
; la pile est [ 1 ]
load - Elle extrait le premier nombre de la pile et le met dans R (le registre du processeur)
   ;la pile est [ 1 2 ] 
load
; la pile est [ 1 ]
; R est 2
store - Elle ajoute le nombre de R (le registre du processeur) dans la pile
   ; la pile est [ 1 ]
; R est 2
store
; la pile est [ 1 2 ]
; R est 2

Math

InstructionParamètresDescriptionExemple
add- Elle extrait deux nombres de la pile, fait l'addition, et ajoute le résultat à la pile
    push 1 
push 2
; la pile est [ 1 2 ]
add
; la pile est [ 3 ]
sub - Elle extrait deux nombres de la pile, fait la soustraction, et ajoute le résultat à la pile
    push 1 
push 2
; la pile est [ 1 2 ]
sub
; la pile est [ -1 ]
mul - Elle extrait deux nombres de la pile, fait la multiplication, et ajoute le résultat à la pile
    push 1 
push 2
; la pile est [ 1 2 ]
mul
; la pile est [ 2 ]
div - Elle extrait deux nombres de la pile, fait la division en utilisant une division entière et ajoute le résultat à la pile
    push 1 
push 2
; la pile est [ 1 2 ]
div
; la pile est [ 0 ]
mod - Elle extrait deux nombres de la pile, calcule le reste de leur division et ajoute le résultat à la pile
    push 5 
push 3
; la pile est [ 5 3 ]
mod
; la pile est [ 2 ]

Flow

InstructionParamètresDescriptionExemple
jumpnumé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
    ; exemple avec la ligne 
push 5 ; line 1
jump 5 ; line 2
push 3 ; line 3 - ignoré
push 2 ; line 4 - ignoré
push 2 ; line 5 - jump ici
mul
; la pile est [ 10 ]
    ; exemple avec étiquette
push 5
jump two
push 3 ; ignoré
push 2 ; ignoré
two: push 2 ; label two
mul
; la pile est [ 10 ]
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
    ; example ignore
push 5
jumpz two ; ignoré, le sommet de la pile est 5
push 3
push 3
two: push 2
mul
; la pile est [ 5 3 6 ]
    ; example jump
push 0
jumpz two ; saute, le sommet de la pile est 0
push 3 ; ignoré
push 3 ; ignoré
two: push 2
mul
; la pile est [ 0 ]
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
    ; example jump
push 5
jumpnz two ; jumps, le sommet de la pile n'est pas 0
push 3 ; ignoré
push 3 ; ignoré
two: push 2
mul
; la pile est [ 10 ]
    ; example ignore
push 0
jumpnz two ; ignoré, le sommet de la pile est 0
push 3
push 3
two: push 2
mul
; la pile est [ 0 3 6 ]

Pseudo Debug

InstructionParamètresDescriptionExemple
print- Affiche le numéro du sommet de la pile
    ; la pile est [ 1 2 ]
print ; affiche 2
stack - Affiche la pile
    ; la pile est [ 1 2 ]
stack ; imprime [ 1 2 ]

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
remarque

Les erreurs doivent être affichés exactement comme dans l'exemple suivant:

ErreurSignificationExemple
unknown instructionle simulateur a trouvé une instruction qu'il ne connaît pas
    multi ; ERROR (multi): unknown instruction
stack underflowle simulateur essaie d'exécuter une instruction qui extrait certaines valeurs de la pile, mais la pile n'a pas assez de valeurs
    push 1
mul ; ERROR (mul): stack underflow
unable to open file filenamele simulateur tente d'ouvrir un fichier qu'il ne peut pas ouvrir
    ERROR unable to open file filename.asm(ENOENT: no such file or directory, open filename.asm)
undefined labelle simulateur essaie de faire un jump à une étiquette qui n'est pas définie
    jump jumper ; ERROR (jump): undefined label jumper
invalid jump address le simulateur essaie de faire un jump à une adresse (numéro de ligne) qui n'existe pas dans le fichier
    jump 2 ; ERROR (jump): invalid jump address 2

Conseils d'implantation

Le devoir comprend beaucoup de fonctionnalités à implémenter, donc on vous suggère de suivre les étapes suivantes:

  1. Lire le contenu du fichier dans le string s et implanter l'erreur no file
  2. 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 fonction split()
  3. Séparer chaque ligne par (espace) et extraire l'instruction et ses parametres
  4. Implanter l'erreur unknown instruction
  5. Implanter les instructions push et pop en utilisant un array de numéros pour la pile
  6. Implanter les fonctions mathématiques
  7. 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:

InstructionParamètresDé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
remarque

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

  1. 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).
  2. Le code source doit être indenté (-0.1p).
  3. Vous devez expliquer en détail dans le Readme.md comment vous avez rédigé les devoirs (-1p)
Tricher

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.

Attention

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.