Accueil
Démo
Exercices formatifs
Travaux pratiques
Simulation libre
Sessions sauvegardées

TP5: Gestion d'une mémoire paginée

Ce travail pratique vaut 5% de la note totale du cours. Comme le stipule le plan de cours, le travail doit être fait individuellement.

Objectifs

Ce travail pratique vise les objectifs suivants:

  1. Distinguer les adresses virtuelles et physiques;
  2. Maîtriser le concept de la mémoire paginée;
  3. Implémenter diverses fonctions nécessaires à l'utilisation de la mémoire paginée;
  4. Comprendre pourquoi surviennent les fautes de pages et ce qu'il faut faire pour les traiter;
  5. Utiliser une table des pages et une table des pages inversée dans un système réel.

Préparation

Important: lisez attentivement tout l'énoncé avant de commencer à travailler! Il contient plusieurs informations qui vous seront très utiles.

Ce TP ne contient pas de questions à répondre sur le portail des cours. Le fichier source.txt que vous remettrez compte donc pour 100% de la note de ce TP.

Survol

Dans ce TP, vous devrez mettre en place un système d'allocation pour une mémoire paginée. Ce système est très similaire à celui utilisé dans les ordinateurs modernes. Toutefois, dans le contexte de ce TP, nous utiliserons un système contenant beaucoup moins de mémoire que ce que doit gérer votre ordinateur ou votre téléphone intelligent. Ce système possède les caractéristiques suivantes:

  • Taille des pages (et des trames) mémoire : 32 octets;
  • Taille totale de la mémoire virtuelle : 640 octets, soit 20 pages distinctes;
  • Taille de la mémoire vive (RAM) dans laquelle les trames (frames) sont stockées : 96 octets, soit 3 trames.

Afin de faciliter votre tâche, nous avons déjà découpé le code à produire en plusieurs fonctions, que vous pourrez programmer et tester indépendamment. Vous trouverez plus d'informations sur chacune de ces fonctions dans la section détails ci-bas.

Lorsque vous aurez terminé, téléchargez tout d'abord votre fichier source.txt sur votre ordinateur grâce au bouton « sauvegarder » dans le simulateur, puis téléversez ce même fichier dans la boîte de dépôt qui est disponible sur le portail des cours.

Pour toutes questions concernant la procédure de remise ou le travail lui-même, posez vos questions sur Piazza!

Détails

1. Présentation générale

Le simulateur ne pouvant directement émuler un disque dur, nous utiliserons plusieurs zones dans sa mémoire de données pour simuler un système tel que décrit à la section précédente. Trois zones sont ainsi déclarées dans la mémoire de données:

  • MaRAM : espace de 96 octets commençant à l'adresse 0x1000;
  • MonDisqueDur : espace de 640 octets commençant à l'adresse 0x10E0;
  • MaPile : espace de 200 octets commençant à l'adresse 0x1364.

Afin de faciliter leur visualisation dans l'afficheur mémoire du simulateur, toutes ces sections sont séparées par des espaces vides. MaRAM est l'espace que nous utiliserons pour simuler la RAM de votre système à mémoire paginé. Ainsi, lorsque l'on parlera d'aller lire une donnée à l'adresse 0x04 de la RAM, cela équivaut, dans le contexte du simulateur, à aller lire à l'adresse 0x1000 + 0x04 = 0x1004. De la même manière, MonDisqueDur est l'espace que nous utiliserons pour simuler une mémoire de stockage telle qu'un disque dur, sur laquelle le système peut décharger les pages de la RAM au besoin. Finalement, MaPile est un espace mémoire indépendant que vous pourrez utiliser pour sauvegarder les registres lors de l'exécution des fonctions que vous devez coder.

2. Accès à la mémoire paginée

Dans un "vrai" système à mémoire paginée, la pagination devrait être transparente aux programmes, c'est-à-dire que toutes les instructions LDR et STR devraient référer directement à des adresses virtuelles. Dans notre cas, afin de simplifier la mise en place du système, cette pagination ne sera pas transparente pour les programmes. Ainsi, un accès mémoire tel que LDR Rx, [Ry] devra être effectué par les étapes suivantes:

  • Mettre dans R8 la valeur de l'adresse que l'on souhaite lire (Ry);
  • Appeler la fonction LoadVirtuel, qui mettra dans R9 la valeur lue (Rx).
; Equivalent de LDR Rx, [Ry]
MOV R8, Ry
BL LoadVirtuel ; Effectue le "LDR". Après, R9 contient la valeur de Rx

De la même manière, une écriture en mémoire comme STR Rx, [Ry] sera simulée par les étapes suivantes:

  • Mettre dans R8 la valeur de l'adresse à laquelle on souhaite écrire (Ry);
  • Mettre dans R9 la valeur que l'on veut écrire (Rx);
  • Appeler la fonction StoreVirtuel, qui effectuera cette écriture
; Equivalent de STR Rx, [Ry]
MOV R8, Ry
MOV R9, Rx
BL StoreVirtuel ; Effectue le "STR"

Les fonctions LoadVirtuel et StoreVirtuel sont déjà écrites pour vous, mais elles nécessitent l'implémentation des autres fonctions pour fonctionner!

3. Les structures de données

Afin de remplir la tâche demandée, vous aurez besoin de trois structures de données : la table de pages, la table de pages inverse et les compteurs d'accès. Ces structures correspondent à ce qui a été vu dans le cours sur la gestion de la mémoire.

3.1 La table de pages

La table de pages est la structure qui fait le lien entre les pages et les trames présentes en RAM. Dans ce TP, vous utilisez une mémoire virtuelle de 20 pages, il y a donc 20 entrées dans cette table. Elle est située à l'adresse 0x04. Lors de l'exécution de votre programme, cette table pourrait par exemple ressembler à ceci :

Dans ce cas-ci, la table de page indique que la page 0 est présente en RAM dans la trame 0, que la page 8 est dans la trame 1 et que le contenu de la page 16 est située dans la trame 2. Toutes les autres pages ont -1 (0xFFFFFFFF) comme valeur de trame pour indiquer qu'elles ne sont pas en mémoire.

Notez que chaque entrée de la table de pages fait 4 octets (32 bits).

3.2 La table de pages inverse

La table de pages inverse met en relation les trames et les pages qu'elles contiennent. Elle peut donc être vue comme l'inverse de la table de pages : au lieu de chercher quelle trame correspond à une page donnée, on cherche quelle page correspond à une trame donnée. Puisque nous utilisons 3 trames en RAM, cette table possède donc 3 entrées. Par exemple, son état pourrait être le suivant :

Dans ce cas-ci, la table indique que la trame 0 contient la page 0, que la trame 1 contient la page 8 et que la trame 2 contient la page 0x10=16. Cette représentation est exactement l'opposé de la table de page présentée plus haut. Cette table inverse vous sera utile lorsque vous voudrez évincer une page de la RAM, puisqu'il faut alors connaître le numéro de cette page pour pouvoir la copier sur le disque dur.

3.3 Les compteurs d'accès

La dernière structure est un tableau de compteurs d'accès. Chaque trame mémoire possède son propre compteur, si bien que cette table a donc 3 entrées. Chaque entrée indique combien de cycles d'accès mémoire se sont écoulés depuis que cette trame a été accédée. Par exemple, une trame qui vient d'être accédée verra son compteur remis à 0; toutes les autres verront leur compteur incrémenté. Un exemple type de l'état des compteurs est donnée à la figure suivante :

La mise à jour de ces compteurs est faite par la fonction AjusteCompteurAcces, qui est déjà codée pour vous. Vous devrez cependant déterminer la page à retirer de la RAM, sachant que l'on souhaite toujours retirer la page la moins récemment utilisée (algorithme LRU, pour « Least Recently Used »).

4. Détail des fonctions à écrire

La mise en place d'un système à mémoire paginée n'est pas simple, aussi la structure du code à écrire a déjà été établie pour vous. Cette structure est présentée à la figure suivante :

Dans ce diagramme, chaque boîte correspond à une fonction. Chaque ligne allant vers la droite correspond à un appel de fonction (BL nomdelafonction), et chaque ligne allant vers la gauche à un retour de fonction (BX LR). Les fonctions dont le nom est en blanc sont déjà écrites pour vous. Vous n'avez donc rien à faire pour ces dernières, si ce n'est les utiliser. Par contre, vous devez implémenter les fonctions dont le nom est de couleur orange sur ce diagramme. Ces fonctions sont décrites en détail dans le code fourni dans l'onglet simulation, avec des informations concernant:

  1. Les paramètres d'entrée : quels registres contiendront les entrées requises pour l'exécution de la fonction;
  2. Les valeurs de retour (sortie) : quels registres doivent être modifiés par la fonction. Tous les autres registres utilisés par la fonction doivent être préalablement sauvegardés puis restaurés avant la fin de la fonction;
  3. Une description du comportement attendu de la part de la fonction;
  4. Les suppositions que vous pouvez faire dans le cadre de cette fonction. Un exemple d'une telle supposition pourrait être la taille des pages mémoire;

5. Test de votre programme

Tester et déboguer un programme assembleur complexe n'est pas simple. Afin de vous aider dans ce travail, nous vous fournissons des tests pré-implémentés. Ceux-ci se situent dans le bloc main. Les premiers tests visent une seule fonction à la fois, de manière à vous permettre de programmer chaque fonction indépendamment. Une fois tous les tests individuels réussis avec succès, vous pouvez passer aux tests globaux, qui vérifient le bon comportement de votre système en utilisation réelle. Il ne sert à rien de passer aux tests globaux si un des tests précédents a échoué, puisque toutes les fonctions doivent fonctionner correctement pour que les tests globaux produisent des résultats valides.

La vérification de la réussite des tests est faite avec les commandes ASSERT. Par exemple, la ligne ASSERT R2=2 indique qu'après l'exécution de l'instruction précédente, R2 devrait contenir la valeur 2. Un « X » s'affichera à la gauche de cette ligne si la condition n'est pas rencontrée.

Si vous rencontrez des erreurs dans les tests, affairez-vous à régler ces erreurs avant de passer aux tests suivants, car plusieurs tests assument que toutes les fonctions précédentes fonctionnent correctement.

Pondération

Tel que mentionné précédemment, le code compte pour 100% de la note de ce TP. Chacune de vos fonctions sera tout d'abord évaluée indépendamment des autres en employant la pondération suivante:

  • DecomposeAdresse: 10%
  • TrouverPage: 15%
  • TrouverValeurMaximum: 20%
  • CopieMemoire: 5% (cela ayant déjà été évalué dans le TP3)
  • ChargerPage: 20%
  • EvincerPage: 20%

La réussite des tests globaux compte pour 10% de la note totale.

Ressources

Remerciements

Merci à Marc-André Gardner pour la création de ce TP!

Registre Généraux (User)

Nom Valeur
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13 (sp)
R14 (lr)
R15 (pc)

Registre Généraux (FIQ)

Nom Valeur
R0
R1
R2
R3
R4
R5
R6
R7
R8 FIQ
R9 FIQ
R10 FIQ
R11 FIQ
R12 FIQ
R13 FIQ (sp)
R14 FIQ (lr)
R15 (pc)

Registre Généraux (IRQ)

Nom Valeur
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13 IRQ (sp)
R14 IRQ (lr)
R15 (pc)

Registre Généraux (SVC)

Nom Valeur
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13 SVC (sp)
R14 SVC (lr)
R15 (pc)

État courant

 CPSRSPSR
Negatif (N)
Zero (Z)
Retenue (C)
Dépassement (V)
Ignore IRQ
Ignore FIQ

Configurations

Interruptions

Activer
Type
 cycles
 cycles (premier)
Vitesse d'exécution :  ms

Français

SECTION INTVEC B main ; Table de pages (correspondance page / trame) tableDePages ASSIGN32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ; Table de pages inverse (correspondance trame / page) tableDePagesInverse ASSIGN32 -1, -1, -1 ; Compteurs d'accès à chaque trame tableAcces ASSIGN32 0, 0, 0 SECTION CODE ;############################################################################ DecomposeAdresse ; Paramètres d'entrée : ; - R8 : Adresse virtuelle à décomposer ; ; Valeurs de sortie : ; - R0 : Index de la page correspondant à cette adresse, numéroté à partir de 0 ; - R1 : Décalage (offset) à l'intérieur de cette page ; ; Description : ; Cette fonction doit, à partir d'une adresse virtuelle, déterminer à quelle ; page cette adresse appartient. Elle doit également calculer le décalage ; requis à partir du début de la page pour atteindre l'adresse demandée. ; La fonction doit retourner dans R0 l'index de la page en question et dans ; R1 le décalage calculé. ; ; Notes: ; Dans l'énoncé de ce TP, on emploie les termes: ; - « index » pour dénoter le numéro de page ; - « décalage » pour dénoter la position dans la page. ; Cette spécification vous est donnée pour faire le parallèle avec ce qui est ; indiqué dans les notes de cours. ; ; Suppositions nécessaires : ; - Ce système utilise des pages de 32 octets. ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ TrouverPage ; Paramètres d'entrée : ; - R0 : Numéro de la page demandée ; ; Valeurs de sortie : ; - R2 : -1 si cette page n'est pas présente en RAM (défaut de page), sinon ; le numéro de la trame en RAM contenant cette page ; ; ; Description : ; ; Cette fonction doit déterminer la trame contenant une page en RAM. ; Pour ce faire, elle utilise le numéro de page i reçu en argument dans R0, et ; retourne la valeur contenu à la position i de la table de pages. Par exemple, ; si la table de pages contient les valeurs 1, -1, -1, 2, -1, 0, -1, ... et que ; l'on demande la page numéro 3, alors cette fonction doit retourner 2 ; (puisque la valeur du 4e élément de la table de page est 2, et qu'on commence ; à compter à partir de zéro). Si on avait plutôt demandé la page numéro 0, ; alors la fonction aurait dû retourner 1. Si on avait demandé la page numéro 5, ; alors le retour devrait être 0. Finalement, si on demande une page inexistante ; en RAM (qui n'est contenue dans aucune trame), alors il faut retourner -1. ; Par exemple, si on avait demandé la page numéro 2, ou la page numéro 4, ; il aurait fallu retourner -1, puisque c'est la valeur de la table de pages ; à ces positions. ; ; Suppositions nécessaires : ; - Chaque entrée de la table de pages fait 4 octets. ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ CopieMemoire ; Paramètre d'entrée : ; - R10 : Adresse source ; - R11 : Adresse destination ; - R12 : Nombre d'octets à copier ; ; Valeurs de sortie : ; - Aucune valeur de sortie requise ; - La copie doit cependant bien avoir été effectuée ; ; Description : ; Cette fonction doit copier les données d'un endroit à l'autre de la mémoire. ; Elle est analogue à celle du TP3, mais la formulation de ses arguments ; diffère légèrement, faites donc attention! ; ; Suppositions nécessaires : ; - Le nombre d'octets à copier sera toujours un multiple de 4. ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ TrouverValeurMaximum ; Paramètres d'entrée : ; - Aucun paramètre d'entrée ; ; Valeurs de sortie : ; - R2 : index de la trame possédant le compteur le plus élevé ; ; Description : ; Cette fonction doit retourner l'index de la trame qui a été le moins ; récemment utilisée. Pour ce faire, elle doit lire le contenu de tableAcces ; et déterminer l'index de la plus GRANDE valeur. Par exemple, si tableAcces ; contient 8, 3, 5, alors cette fonction doit retourner 0x00 dans R2. Si elle ; contient plutôt 2, 7, 1, alors c'est 0x01 qui doit être retourné (la position ; du 7 dans le tableau). ; ; Suppositions nécessaires : ; - La RAM contient 3 trames (donc il y a 3 compteurs). ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ ChargerPage ; Paramètres d'entrée : ; - R0 : index de la page à charger ; - R2 : index de la trame où la charger ; ; Valeurs de sortie : ; - Aucun registre modifié ; - Une copie doit être faite entre la page à charger sur le disque et la ; trame où la charger en RAM. ; - La table des pages et la table des pages inverse doivent être mises à ; jour pour refléter ce changement ; ; Description : ; Cette fonction doit copier une page à partir du disque dur dans une trame ; en mémoire vive. Elle doit également mettre à jour la table des pages et la ; table des pages inverse. ; Chaque page est stockée à l'endroit sur le disque dur correspondant à son ; numéro (index). Par exemple, la page 0 est stocké dans les premiers ; 32 octets du disque dur, la page 1 dans les 32 octets suivants, etc. ; CopieMemoire vous sera certainement utile dans cette fonction. ; ; Suppositions nécessaires : ; - Ce système utilise des pages de 32 octets. ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ EvincerPage ; Paramètres d'entrée : ; - Aucun paramètre d'entrée ; ; Valeurs de sortie : ; - R2 : index de la trame à utiliser, trame qui doit préalablement avoir été ; sauvegardée sur le disque dur ; - La table des pages doit être mise à jour pour indiquer que la page qui ; occupait précédemment cette trame n'est plus en mémoire ; ; Description : ; Cette fonction doit d'abord utiliser la fonction TrouverValeurMaximum pour ; déterminer la trame ayant été accédée le moins récemment. Par la suite, elle ; doit copier cette page de la RAM vers le disque, afin de permettre son ; remplacement. Chaque page doit être stockée à l'endroit sur le disque dur ; correspondant à son numéro. Par exemple, la page 0 est stocké dans les premiers ; 32 octets du disque dur, la page 1 dans les 32 octets suivants, etc. ; Finalement, la table des pages doit être mise à jour. ; Il existe une EXCEPTION à ce comportement : si la table de pages inverse ; indique que la trame mémoire visée n'a jamais contenu une page valide jusqu'à ; maintenant (la valeur de la table de pages inverse à cet endroit est -1), ; alors il ne faut PAS essayer de copier la trame, puisque copier une zone ; mémoire non initialisée générera une erreur. ; En résumé, la copie doit être effectuée SAUF SI la table de pages inverse ; contient -1 à l'index correspondant à la trame. ; CopieMemoire vous sera certainement utile dans cette fonction. ; ; Suppositions nécessaires : ; - Ce système utilise des pages de 32 octets. ; ; ÉCRIVEZ VOTRE CODE ICI BX LR ;############################################################################ ; NE RIEN MODIFIER À PARTIR D'ICI ; TOUTES LES FONCTIONS SUBSÉQUENTES SONT DÉJÀ CODÉES POUR VOUS AjusteCompteursAcces ; Paramètres d'entrée : ; - R2 : Numéro de la trame (frame) à laquelle on accède ; ; Valeurs de sortie : ; - Aucune valeur de sortie ; ; Description : ; Cette fonction met à jour les compteurs d'accès de chaque trame en mémoire. ; Une trame qui est accédée voit son compteur remis à 0, alors que toutes ; les autres ont leur compteur incrémenté. ; ; Suppositions nécessaires : ; Vous pouvez supposer que nous utilisons un système ne pouvant stocker que ; trois (3) pages dans sa RAM. ; ; CETTE FONCTION EST DÉJÀ CODÉE POUR VOUS! ; VOUS N'AVEZ PAS À LA MODIFIER! ; PUSH {R3, R4, R5} LDR R3, =tableAcces MOV R4, #2 ; Index de la page dont on ajuste le compteur. ; On commence à la fin pour simplifer la condition de sortie de la boucle boucleAjusteCompteursAcces CMP R4, R2 MOVEQ R5, #0 ; Trame à laquelle on accède : on remet son compteur à 0 LDRNE R5, [R3, R4, LSL #2] ; Page non-accédée, on ajoute 1 à son compteur ADDNE R5, R5, #1 STR R5, [R3, R4, LSL #2] ; On inscrit la nouvelle valeur en mémoire SUBS R4, R4, #1 ; On passe à la page précédente BPL boucleAjusteCompteursAcces ; Si on n'a pas traité toutes les pages, on continue! POP {R3, R4, R5} BX LR ;############################################################################ PrepareAccesMemoire ; Paramètres d'entrée : ; - R8 : Adresse VIRTUELLE à convertir vers une adresse PHYSIQUE ; ; Valeurs de sortie : ; - R3 : Adresse PHYSIQUE demandée. Cette adresse doit OBLIGATOIREMENT se situer ; à l'intérieur des limites de la variable MaRAM, soit entre ; 0x100000 et 0x10005F ; ; Description : ; Cette fonction doit retrouver l'adresse physique correspondant à une adresse ; virtuelle passée en paramètre. Cette adresse virtuelle peut correspondre à ; une page qui n'est PAS chargée en RAM, auquel cas il faut la charger! ; ; CETTE FONCTION EST DÉJÀ CODÉE POUR VOUS! ; VOUS N'AVEZ PAS À LA MODIFIER! ; PUSH {R0-R2,LR} ; Décomposition de l'adresse en # de page (dans R0) et offset en octets ; par rapport au début de cette page (dans R1) BL DecomposeAdresse ; Cette page est-elle présente en mémoire? ; Si oui R2 contiendra l'index en RAM de la page. ; Sinon, il contiendra -1, valeur spéciale indiquant un défaut de page BL TrouverPage CMP R2, #-1 BNE finPrepareAccesMemoire ; Pas de faute de page, donc on peut ; sauter directement à l'accès en RAM BL EvincerPage ; Évincer la page utilisée depuis le plus ; longtemps, et retourner dans R2 la position ; de cette trame BL ChargerPage ; Charger la page voulue à cet endroit finPrepareAccesMemoire ; À cet endroit on sait que la page est présente en RAM, dans la trame R2 ; et que l'offset par rapport au début de le page est R1 LDR R3, =MaRAM ; Debut de la RAM ADD R3, R3, R2, LSL #5 ; On additionne 32 * l'index de page ADD R3, R3, R1 BL AjusteCompteursAcces ; On met à jour les compteurs nous permettant ; de déterminer quelle page évincer POP {R0-R2,LR} BX LR ;############################################################################ LoadVirtuel ; Paramètres d'entrée : ; - R8 : Adresse VIRTUELLE à charger ; ; Valeurs de sortie : ; - R9 : Valeur (sur 4 octets) de la donnée à cette adresse virtuelle ; ; Description : ; Effectue l'équivalent de LDR R9, [R8], où R8 contient une adresse virtuelle ; ; Suppositions nécessaires : ; On charge toujours 4 octets ; PUSH {LR} BL PrepareAccesMemoire LDR R9, [R3] ; On va chercher la valeur POP {LR} BX LR ;############################################################################### StoreVirtuel ; Paramètres d'entrée : ; - R8 : Adresse VIRTUELLE à laquelle écrire ; - R9 : Valeur à y écrire ; ; Valeurs de sortie : ; - Aucune ; ; Description : ; Effectue l'équivalent de STR R9, [R8], où R8 est une adresse virtuelle ; ; Suppositions nécessaires : ; On écrit toujours sur 4 octets ; PUSH {LR} BL PrepareAccesMemoire STR R9, [R3] ; On stocke la valeur POP {LR} BX LR ;############################################################################### main ; Initialisation de la pile LDR SP, =MaPile ADD SP, SP, #200 ; Ne pas effacer cette ligne: ${TEST_CORRECTION} ; DÉBUT DES TESTS ; LES LIGNES SUIVANTES SONT DES PETITS PROGRAMMES QUI TESTENT CHAQUE FONCTION ; VOUS DEVEZ VOUS ASSURER VOUS-MÊMES DE LA RÉUSSITE DE CES TESTS ; CHAQUE TEST NECESSITE QUE LES TESTS PRÉCÉDENTS SOIENT FONCTIONNELS ; Test de DecomposeAdresse MOV R8, #196 BL DecomposeAdresse ASSERT R0=6,R1=4 MOV R8, #0 BL DecomposeAdresse ASSERT R0=0,R1=0 MOV R8, #88 BL DecomposeAdresse ASSERT R0=2,R1=24 ; Test de TrouverPage LDR R0, =tableDePages MOV R1, #1 MOV R2, #0 MOV R3, #-1 MOV R4, #-1 MOV R5, #-1 MOV R6, #2 STMIA R0, {R1-R6} MOV R0, #0 BL TrouverPage ASSERT R2=1 MOV R0, #1 BL TrouverPage ASSERT R2=0 MOV R0, #5 BL TrouverPage ASSERT R2=2 MOV R0, #4 BL TrouverPage ASSERT R2=-1 MOV R2, #5 MOV R0, #2 BL TrouverPage ASSERT R2=-1 MOV R1, #-1 MOV R2, #-1 MOV R3, #-1 MOV R4, #-1 MOV R5, #-1 MOV R6, #-1 LDR R0, =tableDePages STMIA R0, {R1-R6} ; Test de TrouverValeurMaximum LDR R0, =tableAcces MOV R1, #5 MOV R2, #0 MOV R3, #6 STMIA R0, {R1-R3} BL TrouverValeurMaximum ASSERT R2=2 MOV R3, #4 STMIA R0, {R1-R3} BL TrouverValeurMaximum ASSERT R2=0 ; Test 1 de CopieMemoire LDR R10, =AdresseSource1 LDR R11, =AdresseDest1 MOV R12, #12 BL CopieMemoire ; >>> Le contenu de AdresseDest1 devrait être égal à celui de AdresseSource1 ASSERT 0x143C=0x12, 0x143D=0, 0x143E=0, 0x143F=0 ASSERT 0x1440=0x34, 0x1441=0, 0x1442=0, 0x1443=0 ASSERT 0x1444=0x45, 0x1445=0, 0x1446=0, 0x1447=0 ASSERT 0x1448=0xFFFFFFFF ; Test 2 de CopieMemoire LDR R10, =AdresseSource2 LDR R11, =AdresseDest2 MOV R12, #8 BL CopieMemoire ; >>> Le contenu de AdresseDest2 devrait être égal à celui de AdresseSource2 ASSERT 0x1454=0x67, 0x1455=0, 0x1456=0, 0x1457=0 ASSERT 0x1458=0x89, 0x1459=0, 0x145A=0, 0x145B=0 ASSERT 0x145C=0xFFFFFFFF ; Test 3 de CopieMemoire LDR R10, =AdresseSource3 LDR R11, =AdresseDest3 MOV R12, #32 BL CopieMemoire ; >>> Le contenu de AdresseDest3 devrait être égal à celui de AdresseSource3 ASSERT 0x1480=0, 0x1481=0, 0x1482=0, 0x1483=0 ASSERT 0x1484=1, 0x1485=0, 0x1486=0, 0x1487=0 ASSERT 0x1488=2, 0x1489=0, 0x148A=0, 0x148B=0 ASSERT 0x148C=3, 0x148D=0, 0x148E=0, 0x148F=0 ASSERT 0x1490=4, 0x1491=0, 0x1492=0, 0x1493=0 ASSERT 0x1494=5, 0x1495=0, 0x1496=0, 0x1497=0 ASSERT 0x1498=6, 0x1499=0, 0x149A=0, 0x149B=0 ASSERT 0x149C=7, 0x149D=0, 0x149E=0, 0x149F=0 ASSERT 0x14A0=0xFFFFFFFF ; Test 4 de CopieMemoire LDR R10, =MonDisqueDur MOV R1, #0 MOV R2, #0 boucleTestCopieMemoire STR R1, [R10, R2] ADD R2, R2, #4 CMP R2, #32 BNE boucleTestCopieMemoire ADD R11, R10, #128 MOV R12, #32 BL CopieMemoire ; >>> Les adresses allant de 0x1160 à 0x117F devraient toutes valoir 0x00 ASSERT 0x1160=0,0x1161=0,0x1162=0,0x1163=0,0x1164=0,0x1165=0,0x1166=0,0x1167=0 ASSERT 0x1168=0,0x1169=0,0x116A=0,0x116B=0,0x116C=0,0x116D=0,0x116E=0,0x116F=0 ASSERT 0x1170=0,0x1171=0,0x1172=0,0x1173=0,0x1174=0,0x1175=0,0x1176=0,0x1177=0 ASSERT 0x1178=0,0x1179=0,0x117A=0,0x117B=0,0x117C=0,0x117D=0,0x117E=0,0x117F=0 ; Test de ChargerPage ; (CopieMemoire DOIT fonctionner correctement avant de faire ce test) MOV R0, #4 MOV R2, #2 BL ChargerPage ASSERT 0x14=2,0x5C=4 ; >>> Les adresses allant de 0x1040 à 0x105F devraient toutes valoir 0x00 ASSERT 0x1040=0,0x1041=0,0x1042=0,0x1043=0,0x1044=0,0x1045=0,0x1046=0,0x1047=0 ASSERT 0x1048=0,0x1049=0,0x104A=0,0x104B=0,0x104C=0,0x104D=0,0x104E=0,0x104F=0 ASSERT 0x1050=0,0x1051=0,0x1052=0,0x1053=0,0x1054=0,0x1055=0,0x1056=0,0x1057=0 ASSERT 0x1058=0,0x1059=0,0x105A=0,0x105B=0,0x105C=0,0x105D=0,0x105E=0,0x105F=0 MOV R0, #0 MOV R2, #0 BL ChargerPage ASSERT 0x04=0,0x54=0 ; >>> Les adresses allant de 0x1000 à 0x101F devraient toutes valoir 0x00 ASSERT 0x1000=0,0x1001=0,0x1002=0,0x1003=0,0x1004=0,0x1005=0,0x1006=0,0x1007=0 ASSERT 0x1008=0,0x1009=0,0x100A=0,0x100B=0,0x100C=0,0x100D=0,0x100E=0,0x100F=0 ASSERT 0x1010=0,0x1011=0,0x1012=0,0x1013=0,0x1014=0,0x1015=0,0x1016=0,0x1017=0 ASSERT 0x1018=0,0x1019=0,0x101A=0,0x101B=0,0x101C=0,0x101D=0,0x101E=0,0x101F=0 ; Test de EvincerPage ; (TrouverValeurMaximum, CopieMemoire et ChargerPage DOIVENT fonctionner ; correctement avant de faire ce test) ; Les deux appels précédents à ChargerPage doivent avoir été exécutés ; sans erreur! LDR R0, =MaRAM MOV R1, #0xAA STR R1, [R0] STR R1, [R0, #8] STR R1, [R0, #12] LDR R0, =tableAcces MOV R1, #5 MOV R2, #3 MOV R3, #4 STMIA R0, {R1-R3} BL EvincerPage ASSERT R2=0 ASSERT 0x10E0=0xAA,0x10E1=0x00,0x10E2=0x00,0x10E3=0x00 ASSERT 0x10E8=0xAA,0x10E9=0x00,0x10EA=0x00,0x10EB=0x00 ASSERT 0x10EC=0xAA,0x10ED=0x00,0x10EE=0x00,0x10EF=0x00 ASSERT 0x04=0xFFFFFFFF LDR R0, =MaRAM ADD R0, R0, #64 MOV R1, #0xBB STR R1, [R0] STR R1, [R0, #20] STR R1, [R0, #28] LDR R0, =tableAcces MOV R1, #0 MOV R2, #7 MOV R3, #9 STMIA R0, {R1-R3} BL EvincerPage ASSERT R2=2 ASSERT 0x1160=0xBB,0x1161=0x00,0x1162=0x00,0x1163=0x00 ASSERT 0x1174=0xBB,0x1175=0x00,0x1176=0x00,0x1177=0x00 ASSERT 0x117C=0xBB,0x117D=0x00,0x117E=0x00,0x117F=0x00 ASSERT 0x14=0xFFFFFFFF ; Tests globaux. Ces tests sont plus complets que les précédents, car ils ; utilisent TOUTES vos fonctions (directement ou indirectement). Il est donc ; important de vous assurez que vos fonctions soient correctes individuellement ; avant de procéder aux tests suivants. ; Initialisation de la table de pages LDR R0, =tableDePages MOV R1, #-1 MOV R2, #0 boucleInitTablePages STR R1, [R0, R2] ADD R2, R2, #4 CMP R2, #80 BNE boucleInitTablePages ; Initialisation de la table de pages inversée LDR R0, =tableDePagesInverse MOV R1, #-1 MOV R2, #-1 MOV R3, #-1 STMIA R0, {R1-R3} ; Initialisation des compteurs LDR R0, =tableAcces MOV R1, #0 MOV R2, #0 MOV R3, #0 STMIA R0, {R1-R3} ; Initialisation de la mémoire virtuelle ; Chaque page mémoire se voit assigner la valeur correspondant à son index + 1 ; Par exemple, la page 0 est remplie de 1, la page 1 est remplie de 2, et ; ainsi de suite MOV R0, #1 LDR R2, =MonDisqueDur b1 MOV R1, #32 b2 STR R0, [R2], #4 SUBS R1, R1, #4 BNE b2 ADD R0, R0, #1 CMP R0, #21 BNE b1 ; Tests MOV R8, #0x00 BL LoadVirtuel ASSERT R9=1 MOV R8, #0x20 BL LoadVirtuel ASSERT R9=2 MOV R8, #0x04 BL LoadVirtuel ASSERT R9=1 MOV R8, #0x3C BL LoadVirtuel ASSERT R9=2 MOV R8, #0x08 MOV R9, #0xAA BL StoreVirtuel MOV R9, #0xBB BL LoadVirtuel ASSERT R9=0xAA MOV R8, #0x40 BL LoadVirtuel ASSERT R9=0x03 MOV R8, #0x20C MOV R9, #0xCC BL StoreVirtuel MOV R8, #0xA8 BL LoadVirtuel ASSERT R9=0x06 ASSERT 0x10E8=0xAA MOV R8, #0x08 BL LoadVirtuel ASSERT R9=0xAA MOV R8, #0x110 BL LoadVirtuel ASSERT R9=9 ASSERT 0x12EC=0xCC MOV R8, #0x20C BL LoadVirtuel ASSERT R9=0xCC ; FIN DES TESTS B main SECTION DATA ; Espace simulant la RAM (96 octets) MaRAM ALLOC8 96 ; Espace vide (seulement utilisé pour faciliter la séparation visuelle ; entre la RAM et le disque) EspaceVide ALLOC32 32 ; Espace simulant le disque dur (640 octets) MonDisqueDur ALLOC8 640 ; Espace non initialisé (laissé volontairement vide) Canari ALLOC32 1 ; Utilisé pour sauvegarder les registres, à la discrétion du programmeur MaPile ALLOC32 51 ; Utilisé pour tester votre fonction CopieMemoire AdresseSource1 ASSIGN32 0x12, 0x34, 0x45 AdresseDest1 ALLOC32 4 AdresseSource2 ASSIGN32 0x67, 0x89 AdresseDest2 ALLOC32 3 AdresseSource3 ASSIGN32 0, 1, 2, 3, 4, 5, 6, 7 AdresseDest3 ALLOC32 9 ; Ne pas enlever cette ligne: ${TEST_DATA}

Instruction courante

Mémoire

Suivre PC
Cycle courant :