Types d'adresses
Cet article résume les différents types d'adresses dans l'architecture IA-32. Cette architecture utilise principalement 3 types d'adresses:
- Adresses logiques, utilisée par la plupart des instructions, elle est composée d'un selecteur de segment ainsi que d'un offset dans ce segment, le processeur utilise la segmentation pour traduire une adresse logique en adresse linéaire;
- Adresses linéaires, composée uniquement d'un offset dans l'espace de mémoire linéaire, il existe deux cas de figure pour traduire une adresse linéaire en adresse physique:
- La pagination est activée, l'adresse linéaire est traduite via la table des pages en adresse physique;
- La pagination est désactivée, l'adresse linéaire est directement interprétée comme une adresse physique.
- Adresses physique, ce type d'adresse est utilisé par le processeur pour adresser la mémoire physique (RAM).
On peut résumer le processus de traduction comme sur le schéma suivante.
Segmentation
Le processeur défini des registres de segment:
- CS, Code Segment
- DS, Data Segment
- SS, Stack Segment
- ES, FS, GS, Extra Segments
Ces registres de segment font tous 16 bits de long, ces 16 bits sont appelés Selecteur de Segment, qui, comme on peut le voir sur le schéma suivant, consiste en un index, un bit IT
ainsi qu'un champ RPL
. Le bit IT
est dans notre cas toujours à 0 pour pointer vers la GDT, s'il était à 1 il pointerait sur la LDT que l'on ne va pas aborder en détails ici. Le champ RPL
Requested Privilege Level, permet de spécifier le privilège attendu de notre segment, on ne rentrera pas dans le détail ici.
Comme expliqué dans l'introduction, les instructions utilisent des adresse logiques et donc utilise un segment implicitement, dépendamment du type d'instruction:
1 2 3 4 5 6 7 8 |
|
On voit dans l'exemple ci-dessus que les segments se cachent dans les instructions les plus communes. Et qu'il est possible de les expliciter. Dans l'exemple, en plus du sélecteur, vous aurez deviné que l'offset de l'adresse logique est défini à la valeur du registre EAX.
Parlons maintenant de la GDT. La Global Descriptor Table est une table en mémoire constituée jusqu'à 8192 descripteurs de 8 octets chacun (max 65 Kio). Pour connaître l'adresse de cette structure, le processeur utilise un registre interne appelé GDTR
qui contient à la fois l'adresse de base mais également le nombre de descripteur maximum. Ce registre est typiquement défini au chargement du kernel par l'instruction lgdt
.
Comme on peut le voir sur le schéma suivant, le descripteur 0 est invalide, et les descripteur suivant sont constitués d'une multitude de champs permettant déclarer l'address de base, la limite, le type et des flags pour chaque segment.
Un sélecteur de segment référence ainsi un descripteur dans la GDT, qui permet ainsi de connaître l'adresse linéaire de base du segment. Le processus de traduction complet est décrit sur le schéma ci-dessous.
Un exemple de code peut permettre de mieux comprendre le fonctionnement. On suppose ici que notre GDT contient 2 entrées, le descripteur zero étant invalide et le descripteur 1 définissant comme base 0x0004000 et limite 0x40.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Pagination
TODO !
<