Ich weiß also, wie die folgenden Register und ihre Verwendung aussehen sollen:
CS = Codesegment (für IP verwendet)
DS = Datensegment (für MOV verwendet)
ES = Zielsegment (wird für MOVS usw. verwendet)
SS = Stapelsegment (für SP verwendet)
Aber wofür sollen die folgenden Register verwendet werden?
FS = "Dateisegment"?
GS = ???
Hinweis: Ich frage nicht nach einem bestimmten Betriebssystem - ich frage nach dem, wofür sie von der CPU verwendet werden sollen, wenn überhaupt.
Antworten:
Es gibt das, wofür sie gedacht waren und wofür sie von Windows und Linux verwendet werden.
Die ursprüngliche Absicht hinter den Segmentregistern war es, einem Programm den Zugriff auf viele verschiedene (große) Speichersegmente zu ermöglichen, die unabhängig und Teil eines dauerhaften virtuellen Speichers sein sollten. Die Idee stammt aus dem Multics-Betriebssystem von 1966 , das Dateien als einfach adressierbare Speichersegmente behandelte. Keine BS "Datei öffnen, Datensatz schreiben, Datei schließen", nur "Diesen Wert in diesem virtuellen Datensegment speichern" mit fehlerhafter Seitenbereinigung.
Unsere aktuellen 2010-Betriebssysteme sind ein großer Rückschritt, weshalb sie "Eunuchen" genannt werden. Sie können nur das einzelne Segment Ihres Prozessraums adressieren , wodurch ein sogenannter "flacher (IMHO langweilig) Adressraum" entsteht. Die Segmentregister auf der x86-32-Maschine können weiterhin für echte Segmentregister verwendet werden, aber niemand hat sich darum gekümmert (Andy Grove, ehemaliger Intel-Präsident, hatte im letzten Jahrhundert eine ziemlich berühmte öffentliche Passform, als er herausfand, dass all diese Intel-Ingenieure Energie und Energie aufgewendet hatten sein Geld, um diese Funktion zu implementieren, dass niemand sie nutzen würde. Los, Andy!)
AMD entschied, dass es ihnen egal war, ob sie Multics als Wahl eliminierten (das ist die gemeinnützige Interpretation; die gemeinnützige ist, dass sie keine Ahnung von Multics hatten), und deaktivierte daher die allgemeine Fähigkeit von Segmentregistern im 64-Bit-Modus. Es bestand immer noch ein Bedarf an Threads, um auf den lokalen Thread-Speicher zuzugreifen, und jeder Thread benötigte einen Zeiger ... irgendwo im sofort zugänglichen Thread-Status (z. B. in den Registern) ..., um den lokalen Speicher zu fädeln. Da Windows und Linux in der 32-Bit-Version FSand GS (danke Nick für die Klarstellung) für diesen Zweck verwendeten, entschied sich AMD, die 64-Bit-Segmentregister (GS und FS) im Wesentlichen nur für diesen Zweck zu verwenden (ich denke, Sie können Stellen Sie sicher, dass sie auf eine beliebige Stelle in Ihrem Prozessbereich verweisen (keine Ahnung, ob der Anwendungscode sie laden kann oder nicht).
Es wäre meiner Meinung nach architektonisch schöner gewesen, die Speicherzuordnung jedes Threads mit einer absoluten virtuellen Adresse (z. B. 0-FFF) zu versehen, die sein lokaler Thread-Speicher war (kein [Segment] -Registerzeiger erforderlich!). Ich habe dies in den 1970er Jahren in einem 8-Bit-Betriebssystem gemacht und es war äußerst praktisch, als hätte man einen weiteren großen Stapel von Registern zum Arbeiten.
Die Segmentregister ähneln nun Ihrem Anhang. Sie dienen einem Überbleibsel. Zu unserem kollektiven Verlust.
Diejenigen, die die Geschichte nicht kennen, sind nicht dazu verdammt, sie zu wiederholen. Sie sind dazu verdammt, etwas Dümmeres zu tun.
quelle
Die Register
FS
undGS
sind Segmentregister. Sie haben keinen prozessordefinierten Zweck, sondern werden von den Betriebssystemen, auf denen sie ausgeführt werden, zweckgebunden. In Windows 64-Bit wird dasGS
Register verwendet, um auf vom Betriebssystem definierte Strukturen zu verweisen.FS
undGS
werden häufig von Betriebssystemkernen verwendet, um auf threadspezifischen Speicher zuzugreifen. In Windows wird dasGS
Register zum Verwalten des threadspezifischen Speichers verwendet. Der Linux-Kernel verwendetGS
den Zugriff auf den CPU-spezifischen Speicher.quelle
*dest++ = lookup[*src++];
es sonst ziemlich umständlich wäre, wenn sich dest, lookup und src an drei nicht miteinander verbundenen Orten befinden würden.FS wird verwendet, um auf den Thread Information Block (TIB) in Windows-Prozessen zu verweisen.
Ein typisches Beispiel ist ( SEH ), in dem ein Zeiger auf eine Rückruffunktion gespeichert ist
FS:[0x00]
.GS wird üblicherweise als Zeiger auf einen Thread Local Storage (TLS) verwendet. und ein Beispiel, das Sie vielleicht schon einmal gesehen haben, ist der Stack Canary Protection (Stackguard). In gcc sehen Sie möglicherweise Folgendes:
quelle
Laut Intel-Handbuch sollen diese Register im 64-Bit-Modus als zusätzliche Basisregister in einigen linearen Adressberechnungen verwendet werden. Ich habe dies aus Abschnitt 3.7.4.1 (S. 86 im 4-Band-Set) gezogen. Wenn sich die CPU in diesem Modus befindet, entspricht die lineare Adresse normalerweise der effektiven Adresse, da in diesem Modus häufig keine Segmentierung verwendet wird.
In diesem flachen Adressraum spielen FS & GS also eine Rolle bei der Adressierung nicht nur lokaler Daten, sondern bestimmter Betriebssystemdatenstrukturen (S. 2793, Abschnitt 3.2.4). Daher sollten diese Register vom Betriebssystem verwendet werden, jedoch von diesen speziellen Designern bestimmen.
Bei der Verwendung von Überschreibungen im 32- und 64-Bit-Modus gibt es einige interessante Tricks, bei denen es sich jedoch um privilegierte Software handelt.
Aus der Perspektive der "ursprünglichen Absichten" ist das schwer zu sagen, außer dass es sich nur um zusätzliche Register handelt. Wenn die CPU in ist Realadreßmodus , das ist wie der Prozessor wird als High - Speed - 8086 laufen und diese Register müssen explizit durch ein Programm zugegriffen werden. Für eine echte 8086-Emulation würden Sie die CPU im virtuellen 8086-Modus ausführen und diese Register würden nicht verwendet.
quelle
TL; DR;
Einfach, um auf Daten außerhalb des Standarddatensegments (DS) zuzugreifen. Genau wie ES.
Die lange Lektüre:
Nun, fast aber DS ist nicht 'irgendein' Datensegment, sondern das Standard. Wurden alle Operationen standardmäßig durchgeführt (* 1)? Hier befinden sich alle Standardvariablen - im Wesentlichen
data
undbss
. Dies ist in gewisser Weise ein Grund dafür, dass x86-Code ziemlich kompakt ist. Alle wesentlichen Daten, auf die am häufigsten zugegriffen wird (plus Code und Stapel), befinden sich innerhalb einer 16-Bit-Kurzschriftentfernung.ES wird verwendet, um auf alles andere (* 2) zuzugreifen, alles über die 64 KiB von DS hinaus. Wie der Text eines Textverarbeitungsprogramms, die Zellen einer Tabelle oder die Bilddaten eines Grafikprogramms und so weiter. Anders als oft angenommen, wird auf diese Daten nicht so oft zugegriffen, sodass die Notwendigkeit eines Präfixes weniger schmerzt als die Verwendung längerer Adressfelder.
Ähnlich ist es nur ein kleiner Ärger, dass DS und ES möglicherweise geladen (und neu geladen) werden müssen, wenn Zeichenfolgenoperationen ausgeführt werden - dies wird zumindest durch einen der besten Zeichensatz-Befehlssätze seiner Zeit ausgeglichen.
Was wirklich weh tut, ist, wenn Benutzerdaten 64 KB überschreiten und der Betrieb aufgenommen werden muss. Während einige Vorgänge jeweils nur für ein einzelnes Datenelement ausgeführt werden (think
A=A*2
), erfordern die meisten zwei (A=A*B
) oder drei Datenelemente (A=B*C
). Wenn sich diese Elemente in verschiedenen Segmenten befinden, wird ES mehrmals pro Vorgang neu geladen, was einen erheblichen Overhead verursacht.Am Anfang war es mit kleinen Programmen aus der 8-Bit-Welt (* 3) und ebenso kleinen Datenmengen keine große Sache, aber es wurde bald zu einem großen Flaschenhals - und vor allem zu einem echten Ärgernis für Programmierer (und Compiler). Mit dem 386 sorgte Intel schließlich für Erleichterung, indem zwei weitere Segmente hinzugefügt wurden, sodass jede unäre , binäre oder ternäre Serienoperation mit im Speicher verteilten Elementen stattfinden konnte, ohne ES ständig neu zu laden.
Für die Programmierung (zumindest in der Assembly) und das Compiler-Design war dies ein ziemlicher Gewinn. Natürlich hätte es noch mehr geben können, aber bei drei war der Flaschenhals im Grunde genommen weg, so dass es nicht nötig war, es zu übertreiben.
In Bezug auf die Benennung sind die Buchstaben F / G einfach alphabetische Fortsetzungen nach E. Zumindest vom Standpunkt des CPU-Designs ist nichts zugeordnet.
* 1 - Die Verwendung von ES als Zeichenfolgenziel ist eine Ausnahme, da lediglich zwei Segmentregister benötigt werden. Ohne wären sie nicht sehr nützlich - oder benötigen immer ein Segmentpräfix. Was eines der überraschenden Merkmale zunichte machen könnte, ist die Verwendung von (nicht sich wiederholenden) Zeichenfolgenbefehlen, die aufgrund ihrer Einzelbyte-Codierung zu einer extremen Leistung führen.
* 2 - Im Nachhinein wäre "Alles andere Segment" eine viel bessere Benennung gewesen als "Zusätzliches Segment".
* 3 - Es ist immer wichtig zu bedenken, dass die 8086 nur als Stop-Gap-Maßnahme bis zur Fertigstellung der 8800 gedacht war und hauptsächlich für die Embedded-Welt gedacht war, um 8080/85-Kunden an Bord zu halten.
quelle