A quoi sert le registre «FS» / «GS»?


102

Je sais donc ce que sont censés être les registres suivants et leurs utilisations:

  • CS = segment de code (utilisé pour IP)

  • DS = segment de données (utilisé pour MOV)

  • ES = segment de destination (utilisé pour MOVS, etc.)

  • SS = segment de pile (utilisé pour SP)

Mais à quoi servent les registres suivants?

  • FS = "segment de fichier"?

  • GS = ???

Remarque: je ne pose pas de questions sur un système d'exploitation en particulier - je demande à quoi ils étaient destinés à être utilisés par le processeur, le cas échéant.


24
Autant que je sache, le F et le G de ces deux éléments ne représentent rien. C'est juste qu'il y avait de la place sur le CPU (et dans le jeu d'instructions) pour six registres de segments spécifiables par l'utilisateur, et quelqu'un a remarqué qu'en plus du segment de virement "S", les lettres "C" et "D" (code et données) étaient en séquence, donc "E" était le segment "extra", puis "F" et "G" juste suivi.
torek

3
Cela aurait pu être, il est toujours difficile de savoir ce qui se passait dans la tête de quelqu'un d'autre à moins que vous n'étiez là à ce moment-là (et j'étais de l'autre côté, loin de l'équipe de conception d'Intel).
torek

20
Pensez simplement à tout le plaisir que nous aurions pu avoir avec le registre BS: -}
Ira Baxter

5
J'ai toujours utilisé GS comme "segment graphique". :-)
Brian Knoblauch

2
Que diriez-vous de l’élément «G» énéral «S»?
SS Anne

Réponses:


109

Il y a à quoi ils étaient destinés et à quoi ils servent sous Windows et Linux.

L'intention initiale derrière les registres de segments était de permettre à un programme d'accéder à de nombreux (grands) segments de mémoire différents qui étaient censés être indépendants et faire partie d'un magasin virtuel persistant. L'idée est tirée du système d'exploitation Multics de 1966 , qui traitait les fichiers comme de simples segments de mémoire adressables. Pas de BS "Ouvrir un fichier, écrire un enregistrement, fermer un fichier", juste "Stocker cette valeur dans ce segment de données virtuel" avec un vidage de page sale.

Nos systèmes d'exploitation actuels de 2010 sont un pas de géant en arrière, c'est pourquoi ils sont appelés «eunuques». Vous ne pouvez traiter que le segment unique de votre espace de processus, en donnant un «espace d'adressage plat (IMHO terne)». Les registres de segment sur la machine x86-32 peuvent toujours être utilisés pour de vrais registres de segment, mais personne ne s'est dérangé (Andy Grove, ancien président d'Intel, a eu une crise publique plutôt célèbre au siècle dernier quand il a découvert après que tous ces ingénieurs Intel aient dépensé de l'énergie et son argent pour implémenter cette fonctionnalité, que personne n'allait l'utiliser. Allez, Andy!)

AMD en passant à 64 bits a décidé qu'il ne se souciait pas de savoir s'il éliminait Multics comme choix (c'est l'interprétation caritative; ce qui est peu charitable, c'est qu'ils n'avaient aucune idée de Multics) et ont donc désactivé la capacité générale des registres de segment en mode 64 bits. Il y avait toujours un besoin pour les threads d'accéder au magasin local de thread, et chaque thread avait besoin d'un pointeur ... quelque part dans l'état de thread immédiatement accessible (par exemple, dans les registres) ... pour threader le magasin local. Étant donné que Windows et Linux utilisaient tous deux FS et GS (merci Nick pour la clarification) à cette fin dans la version 32 bits, AMD a décidé de laisser les registres de segment 64 bits (GS et FS) être utilisés essentiellement uniquement à cette fin (je pense que vous pouvez faites-les pointer n'importe où dans votre espace de processus; je ne sais pas si le code de l'application peut les charger ou non).

Il aurait été plus joli sur le plan architectural à mon humble avis de faire en sorte que la carte mémoire de chaque thread ait une adresse virtuelle absolue (par exemple, 0-FFF disons) qui était son stockage local de thread (aucun pointeur de registre [segment] nécessaire!); Je l'ai fait dans un système d'exploitation 8 bits dans les années 1970 et c'était extrêmement pratique, comme avoir une autre grande pile de registres pour travailler.

Ainsi, les registres de segments sont maintenant un peu comme votre annexe. Ils servent un objectif résiduel. À notre perte collective.

Ceux qui ne connaissent pas l'histoire ne sont pas condamnés à la répéter; ils sont condamnés à faire quelque chose de plus stupide.


10
@supercat: Un schéma plus simple et plus brillant qui leur aurait permis d'adresser 65536 fois plus de stockage, aurait été de traiter les registres de segment comme une extension complète de 16 bits supérieurs des 16 bits inférieurs, ce qui est essentiellement ce que les 286, 386 et Multics l'a fait.
Ira Baxter

3
@IraBaxter: Le problème avec cette approche est que les segments de style 80286 ont une surcharge suffisamment élevée pour qu'on finisse par devoir stocker de nombreux objets dans chaque segment, et donc stocker à la fois le segment et le décalage sur chaque pointeur. En revanche, si l'on est prêt à arrondir les allocations de mémoire jusqu'à des multiples de 16 octets, la segmentation de style 8086 permet d'utiliser le segment seul comme moyen d'identifier un objet. Arrondir les allocations jusqu'à 16 octets aurait pu être un peu ennuyeux en 1980, mais représenterait une victoire aujourd'hui si cela réduisait la taille de chaque référence d'objet de 8 octets à quatre.
supercat du

3
Ces registres sont utilisés dans les systèmes d'exploitation modernes. Ils sont principalement dédiés à pointer vers des informations sur les blocs de contrôle des tâches, au moins dans les deux principaux systèmes d'exploitation désormais disponibles pour les puces x86. Et, comme ils ne sont plus «à usage général», même pour leur intention initiale, vous ne pouvez pas les utiliser pour beaucoup. Mieux vaut prétendre sur les systèmes x86-64 qu'ils n'existent tout simplement pas tant que vous n'avez pas besoin des informations auxquelles ils vous permettent d'accéder dans les blocs de contrôle de thread.
Ira Baxter le

5
L'analogie de l'appendice est vraiment mauvaise basée sur une science dépassée; c'est lié au système immunitaire, donc certainement pas "vestigial". Cela nuit à la publication réelle. A part ça, c'est une bonne réponse.
code_dredd

5
Merci pour le traitement amusant et illimité de la mémoire segmentée ou plate :) Ayant également écrit du code sur 6809 (avec et sans mémoire paginée), 6502, z80, 68k et 80 [123]? 86, mon point de vue est segmenté la mémoire est un spectacle d'horreur et je suis heureux qu'il ait été jeté à la poubelle de l'histoire. L'utilisation de FS et GS pour un accès efficace aux données thread_local est une heureuse conséquence involontaire d'une erreur historique.
Richard Hodges

44

Les registres FSet GSsont des registres de segment. Ils n'ont pas de fonction définie par le processeur, mais sont plutôt déterminés par le système d'exploitation qui les exécute. Sous Windows 64 bits, le GSregistre est utilisé pour pointer vers les structures définies par le système d'exploitation. FSet GSsont couramment utilisés par les noyaux OS pour accéder à la mémoire spécifique aux threads. Dans Windows, le GSregistre est utilisé pour gérer la mémoire spécifique au thread. Le noyau Linux utilise GSpour accéder à la mémoire spécifique au processeur.


1
Étaient-ils destinés à être utilisés à des fins définies par le système d'exploitation, ou pour faciliter le code qui doit faire quelque chose comme *dest++ = lookup[*src++];ce qui serait autrement plutôt gênant si dest, lookup et src étaient à trois emplacements non liés.
supercat du

8
Sur Windows FS est en effet pour le stockage spécifique aux threads. Voir la carte documentée du bloc pointé par FS ici en.wikipedia.org/wiki/Win32_Thread_Information_Block
Nedko

2
Ce n'est pas seulement sous Windows. GS est également utilisé pour le TLS sur OS X. GS est également utilisé par les noyaux 64 bits pour garder une trace des structures du système lors des changements de contexte. Le système d'exploitation utilisera SWAPGS à cet effet.
ET

12

FS est utilisé pour pointer vers le bloc d'informations de thread (TIB) sur les processus Windows.

un exemple typique est ( SEH ) qui stocke un pointeur vers une fonction de rappel dans FS:[0x00].

GS est couramment utilisé comme pointeur vers un stockage local de thread (TLS). et un exemple que vous avez peut-être déjà vu est la protection canary de pile (stackguard), dans gcc vous pourriez voir quelque chose comme ceci:

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax

2
Cela ne répond pas vraiment à la question. La question déclare Remarque: je ne pose pas de question sur un système d'exploitation en particulier - je demande à quoi ils étaient destinés à être utilisés par le processeur, le cas échéant.
Michael Petch

9
@MichaelPetch ya je sais que je veux juste ajouter ceci comme une bonne information pour ceux qui liront ce q / s dans SO
zerocool

2

Selon le manuel Intel, en mode 64 bits, ces registres sont destinés à être utilisés comme registres de base supplémentaires dans certains calculs d'adresses linéaires. J'ai tiré ceci de la section 3.7.4.1 (p. 86 dans l'ensemble de 4 volumes). Habituellement, lorsque la CPU est dans ce mode, l'adresse linéaire est la même que l'adresse effective, car la segmentation n'est souvent pas utilisée dans ce mode.

Ainsi, dans cet espace d'adressage plat, FS & GS jouent un rôle dans l'adressage non seulement des données locales mais de certaines structures de données du système d'exploitation (pg 2793, section 3.2.4), donc ces registres étaient destinés à être utilisés par le système d'exploitation, mais ces concepteurs particuliers déterminer.

Il y a une astuce intéressante lors de l'utilisation de remplacements dans les modes 32 et 64 bits, mais cela implique un logiciel privilégié.

Du point de vue des «intentions originales», c'est difficile à dire à part ce ne sont que des registres supplémentaires. Lorsque la CPU est en mode d'adresse réelle , c'est comme si le processeur fonctionne en tant que 8086 à grande vitesse et ces registres doivent être explicitement accédés par un programme. Pour une véritable émulation 8086, vous exécuteriez le processeur en mode virtual-8086 et ces registres ne seraient pas utilisés.


2

TL, DR;

A quoi sert le registre «FS» / «GS»?

Simplement pour accéder aux données au-delà du segment de données par défaut (DS). Exactement comme ES.


La longue lecture:

Je sais donc ce que sont censés être les registres suivants et leurs utilisations:

[...]

Eh bien, presque, mais DS n'est pas «un» segment de données, mais celui par défaut. Toutes les opérations ont-elles eu lieu par défaut (* 1). C'est là que se trouvent toutes les variables par défaut - essentiellement dataet bss. C'est en partie la raison pour laquelle le code x86 est plutôt compact. Toutes les données essentielles, qui sont ce qui est le plus souvent consulté, (plus le code et la pile) sont à une distance abrégée de 16 bits.

ES est utilisé pour accéder à tout le reste (* 2), tout au-delà des 64 Kio de DS. Comme le texte d'un traitement de texte, les cellules d'une feuille de calcul, ou les données d'image d'un programme graphique, etc. Contrairement à ce que l'on suppose souvent, ces données ne sont pas autant consultées, donc avoir besoin d'un préfixe fait moins mal que d'utiliser des champs d'adresse plus longs.

De même, ce n'est qu'un inconvénient mineur que DS et ES doivent être chargés (et rechargés) lors d'opérations sur des chaînes - au moins, cela est compensé par l'un des meilleurs jeux d'instructions de gestion de caractères de son époque.

Ce qui fait vraiment mal, c'est lorsque les données utilisateur dépassent 64 Ko et que les opérations doivent commencer. Alors que certaines opérations sont simplement effectuées sur un seul élément de données à la fois (pensez A=A*2), la plupart nécessitent deux ( A=A*B) ou trois éléments de données ( A=B*C). Si ces éléments résident dans différents segments, ES sera rechargé plusieurs fois par opération, ce qui ajoutera une certaine surcharge.

Au début, avec de petits programmes du monde 8 bits (* 3) et des ensembles de données tout aussi petits, ce n'était pas un gros problème, mais c'est rapidement devenu un goulot de performance majeur - et plus encore une vraie douleur dans le cul pour programmeurs (et compilateurs). Avec le 386, Intel a finalement apporté un soulagement en ajoutant deux segments supplémentaires, de sorte que toute opération unaire , binaire ou ternaire en série, avec des éléments étalés en mémoire, pouvait avoir lieu sans recharger ES tout le temps.

Pour la programmation (au moins dans l'assemblage) et la conception du compilateur, c'était tout un gain. Bien sûr, il aurait pu y en avoir encore plus, mais avec trois, le goulot de la bouteille avait pratiquement disparu, donc pas besoin d'en faire trop.

En ce qui concerne les noms, les lettres F / G sont simplement des suites alphabétiques après E. Au moins du point de vue de la conception du processeur, rien n'est associé.


* 1 - L'utilisation de ES pour la destination de la chaîne est une exception, car il suffit de deux registres de segment. Sans cela, ils ne seraient pas très utiles - ou auraient toujours besoin d'un préfixe de segment. Ce qui pourrait tuer l'une des fonctionnalités surprenantes, l'utilisation d'instructions de chaîne (non répétitives) entraînant des performances extrêmes en raison de leur codage à un octet.

* 2 - Donc, avec le recul, 'Everything Else Segment' aurait été une bien meilleure dénomination que 'Extra Segment'.

* 3 - Il est toujours important de garder à l'esprit que le 8086 était uniquement conçu comme une mesure provisoire jusqu'à ce que le 8800 soit terminé et qu'il était principalement destiné au monde embarqué pour garder 8080/85 clients à bord.


1
Wow, merci d'avoir expliqué tout ça! Cela explique beaucoup et a tellement de sens! +1
user541686
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.