Page prec.
Transformation adresse virtuelle -> adresse physique |
Fin de page |
Page suiv.
Eléments des répertoires de tables de pages |
Lors du passage d'un processus à un autre (commutation de contexte), les informations propres à chacun d'eux doivent être stockées dans - ou restauré à partir de - la mémoire principale. Il existe quatre sortes de descripteurs dans les tables traduisant la variété des informations : les descripteurs de segments, qui se subdivisent en descripteurs de segments de données, descripteurs de segments de code exécutable et descripteurs de segments système, et les descripteurs guichets (gates) (un guichet est un objet - 2 mots doubles, soit 8 octets - permettant d'établir des sécurités lors du passage de l'exécution d'un segment de code à un segment plus privilégié : voir plus loin "protection et privilèges").
Tous ces descripteurs ont une partie de la structure commune (partie non grisée de la figure ci-dessous). Rappelons qu'ils sont formés de 8 octets, numérotés de 0 à 7. Ils ne diffèrent que par une partie des octets 5 et 6.
L'adresse de base, de 32 bits, est répartie sur les octets 2, 3, 4 et 7. Ses différentes parties sont automatiquement concaténées par le processeur (par l'unité de gestion de la mémoire) pour donner une adresse linéaire.
La limite, constituée de 20 bits, est répartie sur les octets 0, 1 et 6.Utilisée conjointement avec le bit G (voir ci-dessous), elle permet de calculer la taille du segment et de vérifier que l'adresse mémoire accédée fait bien partie de l'espace adressable du processus.
Le bit G, dit bit de granularité (Granulatity bit), permet de calculer la limite du segment. Si G = 0, la granularité est de 1 octet, la limite représente le nombre d'octets du segment, dont la taille maximale est alors de F FFFFh, ce qui représente 1 Mo (= 220 octets). Si G = 1, la granularité est alors de 4 Ko, ce qui signifie que la limite est exprimée en unités de 4 Ko. La limite réelle est donc obtenue en multipliant la limite contenue dans le descripteur par 4 Ko. La taille maximale du segment désigné par le descripteur est alors de FFFF FFFFh, soit 4 Go (= 232 octets).
Si le bit S (bit 12) de l'octet 5 est positionné à 1, il s'agit d'un descripteur de segment dit de type segment (de données ou de code). Si le bit S est à zéro, c'est un descripteur de segment système.
Les bits DPL (bits 13 et 14 de l'octet 5) sont les bits de droits d'accès au segment. Ils indiquent le niveau de privilège (Descriptor Privilege Level) du segment désigné par le descripteur (voir plus loin : "protection et privilèges").
Le bit P, dit bit de Présence, indique la présence du segment correspondant en mémoire physique. Une tentative d'accès à un segment absent (bit P = 0) déclenche une exception (analogue aux défauts de page).
La figure ci-dessous illustre la structure des octets 5 et 6 d'un descripteur de segment de données. Comme nous venons de le voir, un segment de type segment de données ou de code est caractérisé par le bit S = 1. Si le bit E (bit 11) de l'octet 5 est positionné à 0, c'est un descripteur de données. Sinon c'est un descripteur de code.
Le bit B contient des informations sur le registre pointeur de pile. Si la directive d'assemblage usel6 est utilisée, le bit B est positionné à 0. Le registre de pile utilisé est alors le registre SP, de l6 bits, ce qui limite la taille de la pile à FFFFH (= 1 Mo). Si la directive d'assemblage use32 est utilisée, le bit B est positionné à 1. Le registre de pile utilisé est alors le registre ESP, de 32 bits, ce qui limite la taille de la pile à FFFF FFFFH (= 4 Go).
Le bit ED (Expansion Direction) permet de savoir si la partie du segment utilisable est la partie au-dessous ou au-dessus de la limite. Considérons un segment dont le bit G = 0 (granularité = 1 octet, taille maximale = FFFFFH) et dont la limite est A0000h. La figure ci-dessous indique quelle est la partie du segment utilisable selon la valeur de ED.
Si ED = 0, il s'agit d'un segment de données "classique" qui se développe vers les adresses croissantes. Les déplacements seront valides s'ils sont <= A0000h. Ils provoqueront une erreur s'ils sont supérieurs. Si ED = 1, la partie utilisable du segment est située entre la taille maximale et la limite du segment. C'est la structure habituelle d'une pile, qui se développe vers les adresses basses. Un déplacement sera valide s'il est <= A0000h. L'augmentation de la taille d'une pile consiste à diminuer la limite du nombre d'octets que l'on veut ajouter à la pile.
Le bit W (Writable) permet de positionner une protection du segment en écriture. Si W = 1, toute donnée du segment est accessible en lecture et en écriture (RW). C'est le cas des variables et des segments de pile. Il faut noter que c'est la totalité du segment qui est affectée par cet attribut. Si W = 0, toute donnée du segment n'est accessible qu'en lecture (RO). C'est le cas des segments de constantes par exemple.
Le bit A (Accessed) est positionné à 1 chaque fois que le descripteur est utilisé par le processeur. Ce bit n'est jamais remis automatiquement à 0. Il peut être utilisé par le système d'exploitation dans l'algorithme d'allocation de la mémoire, pour déterminer les segments les plus anciennement utilisés (algorithme LRU : Least Recently Used).
Structure d'un descripteur de segment de code
Le bit D permet au processeur 80x86 d'interpréter le code qu'il exécute comme du code 16 bits ou 32 bits. Rappelons qu'à l'assemblage, les directives usel6 et use32 indiquent le type de segment. Si la directive usel6 est utilisée pour assembler un segment de code, le bit D du descripteur de ce segment est posé égal à 0. Si la directive use32 est utilisée, le bit D du descripteur est posé égal à 1. De plus le code peut être généré différemment à l'assemblage ou interprété différemment à l'exécution selon la directive utilisée. Par exemple, le code Ch est interprété par l'iAPX 386 comme l'instruction PUSH AX (empiler le registre AX de 16 bits) si le bit D du descripteur de segment de code correspondant est égal à 0, et comme l'instruction PUSH EAX (empiler le registre EAX de 32 bits) si le bit D est égal à 1.
Inversement, l'assemblage ajoute un préfixe (66h ou 67h) aux codes des instructions générés, si l'opérande (ou l'adresse effective) associé à l'instruction n'a pas la taille "par défaut". Par exemple, l'assembleur code par la même valeur 66Ch l'instruction PUSH EAX si la directive usel6 est utilisée et l'instruction PUSH AX si la directive use32 est utilisée.
Le bit C (Conforming) permet ou non une modification des droits d'exécution du code d'un segment. Si C = 0, le code contenu dans le segment est exécuté avec les privilèges indiqués dans le descripteur (bits DPL). Si C = 1, le code est exécuté avec les privilèges de la procédure appelante (voir plus loin : "protection et privilèges").
Le bit R joue un rôle analogue au bit W des segments de données. Si R = 0, le code du segment correspondant ne peut être qu'exécuté (EO : Execute Only). Si R = 1, le code peut être lu et exécuté (ER : Execute and Read). Cette possibilité est utilisée pour pouvoir analyser un programme en cours d'exécution.
Le bit A a la même signification que pour les segments de données.
Structure d'un descripteur de segment de code
Les bits TYPE de l'octet 5 déterminent la nature du descripteur : le bit 10 est toujours égal à 0 pour les descripteurs de segments "système" et à 1 pour les descripteurs "guichets". Rappelons que le système d'exploitation a en charge la gestion de la mémoire et des processus. Pour cela, il doit conserver en mémoire principale un certain nombre d'informations. Nous avons déjà vu que les informations décrivant l'espace mémoire occupé par les différents processus sont accessibles par l'intermédiaire d'une table générale de descripteurs, appelée GDT, qui est unique et accessible directement grâce au registre GDTR, et par différentes tables locales de descripteurs LDT. Chacune de ces tables locales est stockée dans un segment, dont le descripteur est dans la table GDT. D'autre part, l'état d'avancement de chaque tâche est caractérisé par l'ensemble des valeurs des registres du processeur lors de son exécution (le contexte de la tâche). Le contexte de chaque tâche est sauvegardé dans un segment de mémoire, alors que l'état de la tâche (active ou non active) est stocké dans le bit 9 de l'octet 5 du descripteur.
Pour résumer, les bits TYPE déterminent la nature du segment système selon le tableau suivant :
0010 | descripteur de LTD (table de descripteurs locale) |
0001 | TSS 286 non actif |
0011 | TSS 286 actif |
1001 | TSS 386 non actif |
1011 | TSS 386 actif |
0000 | type invalide |
1000 | " " |
1010 | réservé |
Remarques
Page prec.
Transformation adresse virtuelle -> adresse physique |
Début de page |
Page suiv.
Eléments des répertoires de tables de pages |