Menu principal:
Correction de l'examen du 09/12/2009 (Programmation système: Niveau Supérieur)
1. SIMULATION CPU-SYSTEME
La mémoire centrale de notre machine est composée de cellules. Une cellule peut contenir soit un entier de 32 bits (la taille des entiers sur une architecture PC) soit une instruction. La mémoire contient quelques dizaines de cellules simulées par un simple tableau. Les adresses physiques sont contiguës et varient de zéro à 127.
typedef union { /* une cellule memoire contient */
int value; /* soit un entier 32 bits signe */
INST inst; /* soit une instruction. */
} CELL;
CELL mem[128]; /* memoire
Instructions de la C.P.U.
Notre C.P.U. exécute des instructions à taille fixe (32 bits). Une instruction est composée d'un code opération, de deux numéros de registre et d'un argument.
typedef struct {
unsigned OP: 10; /* code operation (10 bits) */
unsigned i: 3; /* nu 1er registre (3 bits) */
unsigned j: 3; /* nu 2eme registre (3 bits) */
short ARG; /* argument (16 bits) */
} INST;
L'instruction va ressembler à ceci : « ADD R1, R2, 1000 ». Elle va effectuer l'affectation R1=R1+R2+1000. Afin de ne pas rendre la création d'un programme trop pénible une fonction est fournie pour implanter une instruction en mémoire.
void make_inst(int adr, unsigned code, unsigned i, unsigned j, short arg) {
INST inst;
inst.OP = code;
inst.i = i;
inst.j = j;
inst.ARG = arg;
mem[adr].inst = inst;
}
Structure de la C.P.U.
Le mot d'état du processeur est défini comme suit
typedef struct PSW { /* Processor Status Word */
int PC; /* Program Counter */
int SB; /* Segment Base */
int SS; /* Segment Size */
int IN; /* Interrupt number */
int DR[8]; /* Data Registers */
int AC; /* Accumulateur */
INST RI; /* Registre instruction */
} PSW;
PC : Le Program Counter (compteur ordinal) est un pointeur sur la prochaine instruction à exécuter.
SB et SS : voir section suivante.
IN : En cas d'interruption, la CPU range dans ce registre la cause de cette interruption. Cette information peut être exploitée par le système d'exploitation.
DR[i] : La C.P.U. dispose de huit registres généraux pouvant contenir chacun un entier signé de 32 bits.
AC : Le registre accumulateur est un relais entre d'une part les instructions de test et d'autre part les instructions de branchement conditionel. Le registre AC est également affecté par les instructions qui modifient le contenu d'un registre (chargement, calcul, incrémentation, ...).
Adressage logique et physique
Durant l'exécution, la CPU adresse la mémoire en utilisant des adresses logiques c'est à dire des entiers compris entre 0 et la taille de la zone mémoire allouée à ce processus (Segment). Le début de cette zone mémoire est pointé par le registre SB (Segment Base) tandis que le registre SS en donne la taille (Segment Size).
<-------------- SS -------------->
---+---+---+------------------+---+---+---
... | | | .... | | | ...
---+---+---+------------------+---+---+---
^
SB
pour chaque adresse logique « a » la CPU calcule l'adresse physique « p » en appliquant l'algorithme suivant :
lire(a) :
| si (a < 0) ou (a >= SS) <erreur adressage>
| p = (SB + a)
| renvoyer mem[p]
Simulation de la machine
Nous avons vu en cours que la CPU passe son temps à alterner des cycles ou elle exécute du code utilisateur et des cycles ou elle exécute du code système. Elle passe du code utilisateur au code système par une interruption et du code système au code utilisateur par un chargement du mot d'état processeur (ou processor Status Word). On peut donc simuler ce comportement par le code ci-dessous :
mep.IN = INT_INIT; /* interruption INIT */
while (1) {
mep = systeme(mep);
mep = cpu(mep);
}
La fonction cpu() simule l'exécution du code utilisateur jusqu'à l'apparition d'une interruption. La fonction systeme() reprends la main, traite l'interruption et redonne la main au code utilisateur.