Segmentierung (Speicherverwaltung)
Unter Segmentierung versteht man im Zusammenhang von Rechenmaschinen die kontextuelle (Adressregister) Verfügbarkeit von Speicherbereichen. Die Segmentierung war zu Zeiten der 8-Bit- und 16-Bit-Mikroprozessoren die einzige Möglichkeit, mehr als 64Ki Worte Speicher über einen Speicherkanal zu adressieren. Im Verlauf der Entwicklung der Betriebssysteme und Prozessoren wurde die Segmentierung zu einem Schutzmechanismus und dem Paging weiterentwickelt. Durch 32-Bit-Prozessoren und diese voll unterstützende 32-Bit-Betriebssysteme (wie Windows NT) sowie 32-Bit-Anwendersoftware wurde die Segmentierung in ihrer Ursprungsform abgeschafft.
Prozessoren mit Segmentierung enthalten meist mehrere Segmentierungsregister und Hardware, um 16-Bit-Adressen anhand der Segmentierungsregister auf die physisch vorhandenen Adressleitungen (oft 20 oder 24) zu erweitern. Die Implementation ohne interne Hardwareunterstützung erfolgte per Memory Management Unit als externer IC. Ein Beispiel für letzteres Vorgehen ist der in den 1990er Jahren von Nintendo verkaufte Game Boy, dessen Spiele oft eine MMU enthielten und so trotz des Z80 z. B. 1 MiB ROM verwendeten.
Ab Ende der 1990er Jahre verblieb nur noch der Zweck der Unterteilung zur Umsetzung von Schutzmechanismen oder virtueller Speicherverwaltung. Je nach Betriebssystem und zugrundeliegender Hardware können einem Segment verschiedene Attribute zugewiesen werden. So können beispielsweise Programm-, Daten- und Stack-Segmente festgelegt werden. Diese Attribute ergeben sich für die Intel x86 Architektur direkt aus den Segmentierungsregistern des Intel 8086, dem Prozessors des ersten IBM PCs. Die Speicherverwaltung sorgt dann unter anderem dafür, dass aus dem Programmsegment nur Befehle, aber keine Daten gelesen werden, oder dass umgekehrt Daten im Datensegment nicht als Befehle interpretiert werden. Oft ist es auch möglich, Segmenten Privilegierungsebenen zuzuweisen, sodass auf die entsprechenden Segmente nur von Programmen bestimmter Privilegierungsebenen zugegriffen werden kann. Man kann so zum Beispiel Betriebssystemdaten und -befehle vor Zugriff durch andere Programme schützen. Häufig kann auch die Zugriffsart (zum Beispiel nur lesen, nur schreiben, kein Zugriff) eingeschränkt werden. Manche Systeme erlauben auch Privilegierungsebenen-abhängige Zugriffsarteneinschränkung.
Speicheradressierung bei der Segmentierung
Ein Segment wird über zwei Werte definiert:
- Segmentanfangsadresse, Segmentbasis oder Basis: die erste im Segment enthaltene Speicheradresse
- Segmentlänge, Segmentlimit oder Limit: die Zahl der aufeinanderfolgenden Speicheradressen, die das Segment umfasst.
Segmentiert wird in der Regel der physische Adressraum direkt oder ein virtueller linearer Adressraum, der auf den physischen Adressraum abbildet. Durch die Segmentierung wird ein sogenannter logischer Adressraum gebildet. Logische Adressen sind unterteilt in einen Segmentselektor und einen Offset. Der Segmentselektor bestimmt direkt oder indirekt, über eine Segmentverwaltungstabelle, das adressierte Segment und somit die Segmentanfangsadresse und -länge. Der Offset gibt, relativ zum Segmentanfang, die Speicherstelle innerhalb dieses Segmentes an.
Soll aus einer logischen Adresse die lineare Adresse bestimmt werden, werden zunächst über den Segmentselektor die Segmenteigenschaften Basis, Länge, Typ, Lese-/Schreibrechte usw. ermittelt. Danach wird anhand der ermittelten Segmenteigenschaften geprüft, ob der Speicherzugriff zulässig ist. Weiterhin wird der Offset mit der Segmentlänge verglichen, um sicherzustellen, dass der Zugriff innerhalb der Segmentgrenzen liegt. Schlägt eine dieser Überprüfungen fehl, wird eine Fehlerbehandlung (Interrupt, Exception etc.) eingeleitet. Der Offset wird zur Segmentbasisadresse addiert und ergibt die lineare Adresse. Ist der lineare Adressraum nicht der physische, wird die lineare Adresse durch eine anschließende Seitenverwaltung (englisch paging unit) in eine physische Adresse umgewandelt.
Diese Adressumwandlungen werden in modernen Computern üblicherweise von Speicherverwaltungseinheiten übernommen, welche in vielen modernen Prozessoren integriert sind.
Beispiele
Intels x86-Prozessoren im Real-Mode
Beim 8086-Prozessor und neueren x86ern im Real Mode wird die Segmentanfangsadresse direkt aus dem Segmentselektor der logischen Adresse berechnet. Alle Segmente haben die feste Länge von 64 KiB. Eine logische Adresse wird in Real-Mode-Programmen meist so geschrieben: Segment:Offset, wobei Segment und Offset 16-Bit-Zahlen sind und in der Regel im Hexadezimalsystem angegeben werden, also zum Beispiel: 2F10:87A1
.
Diese logische Adresse wird folgendermaßen in eine physische umgerechnet:
Adresse physisch = Segmentselektor logisch · 16 + Offset logisch
Im Beispiel ergibt sich für die physische Adresse:
0x2F10 · 16 + 0x87A1 = 0x2F10 · 0x10 + 0x87A1 = 0x2F100 + 0x87A1 = 0x378A1
Mit dieser Adressierung kann man die physische Adressbreite auf 20 Bits ausweiten, da die 16-Bit-Segmentadresse durch die Multiplikation mit 16 zu einer 20-Bit-Zahl wird, zu der noch der Offset addiert wird. Mit diesen 20 Bits können immerhin bis zu 1 MiB RAM auf einem 16-Bit-Prozessor adressiert werden. Genau genommen können unter bestimmten Umständen durch den Übertrag bei der Addition sogar 21-Bit-Zahlen bei der Adressrechnung entstehen, es kann also etwas mehr als 1 MiB Speicher adressiert werden. Für genauere Informationen hierzu sei auf die Artikel High Memory Area und A20-Gate verwiesen.
Paragraph
Als Paragraph wird bei x86 Prozessoren im Real Mode der Speicherbereich zwischen zwei Adressen genannt, den man erhält, wenn man das Segmentregister um genau einen Wert erhöht oder erniedrigt.[1] Ein Paragraph ist 16 Byte groß. Die Paragraphennummer ist hierbei die Bezeichnung für die Basisadresse, an der dieser Speicherbereich beginnt.[2] Der Paragprah ist x86 und Real Mode spezifisch.
Beispiel:
Eine Adresse besteht im Real Mode aus der Schreibweise Segment:Offset. Die erste mögliche Segmentadresse eines Segments ist die Adresse 0000:0000, die zweite 0001:0000. Bei einer Linearen Adressierungsart würde das den Anfangsadressen 0x0 (Dezimal 0) und 0x10 (Dezimal 16) entsprechen. Der Speicherbereich dazwischen nennt man Paragraph und ist gegeben durch obige Berechnungsmethode genau 16 Byte groß. Da jedes Segment 64 KiB groß ist, überlappen sich somit die Segmente, die durch diese beiden Adressen definiert werden. Dies gilt aber nicht für den Bereich des Paragraphen des unteren Segments.
Speichermodell
Um die Kompatibilität zwischen Assembler und Compilern zu erhöhen, legte Microsoft die sogenannten Speichermodelle fest, die als Segment-Direkten dem MASM Assembler mitgeteilt werden konnten. Andere Compiler und Assemblerhersteller wie bspw. Borland übernahmen diese Speichermodelle, womit sie als Standard festgeschrieben wurden.[3][4]
Diese Modelle waren:
Speichermodellname | Anzahl Codesegmente | Anzahl Datensegmente | Bemerkung |
---|---|---|---|
Tiny | Das Code- und Datensegment sind identisch. Es existierte aus Abwärtskompatibilitätsgründen zu CP/M und war für COM-Dateien gedacht. | ||
Small | 1 | 1 | |
Medium | mehrere | 1 | |
Compact | 1 | mehrere | |
Huge/Large | mehrere | mehrere | |
Flat | - | - | Keine Segmente, sondern ein linearer Adressraum |
Die Speichermodelle hatten auch Auswirkung auf die verwendbaren Zeigerarten:
Zeigergröße für Daten | |||
---|---|---|---|
Near | Far | ||
Zeigergröße für Code | Near | Small | Compact |
Far | Medium | Large |
Intels x86-Prozessoren im Protected-Mode
Ab Intels 80286-Prozessor wurde der sogenannte Protected Mode eingeführt. Hier können Segmente zwischen einem Byte und 64 KiB (ab dem 80386er bis zu 4 GiB) lang sein und an beliebigen Byte-Positionen im linearen Adressraum beginnen. Jedes Segment wird durch eine spezielle Datenstruktur, Segmentdeskriptor genannt, beschrieben. Neben der Segmentbasisadresse und der Segmentlänge enthält ein Segmentdeskriptor auch Informationen über Segmentattribute wie Segmenttyp, Privilegierungsebene und Lese-/Schreibrechte.
Segmentdeskriptoren werden aus im Arbeitsspeicher liegenden Deskriptortabellen gelesen. Diese Tabellen werden vom Betriebssystem aufgebaut und verwaltet. Der Segmentselektor einer logischen Adresse gibt die Deskriptortabelle und den Index eines Segmentdeskriptors innerhalb der Tabelle an. Aus dem gewählten Segmentdeskriptor werden dann die zur Adressberechnung nötigen Daten ausgelesen.
Weblinks
Einzelnachweise
- ↑ Removing the Mystery from SEGMENT : OFFSET Addressing#Visualizing the Overlapping Segments. In: pcministry.com, 15. Oktober 2007.
- ↑ "Assembler Programmierung" von Wolfgang Link, Franzis Verlag, ISBN 3-7723-8839-6, Seite 23
- ↑ Raymond Chen: A look back at memory models in 16-bit MS-DOS. In: The Old New Thing. Microsoft, 28. Juli 2020, abgerufen am 26. März 2024 (englisch).
- ↑ Programmer's Guide Microsoft MASM 6.1. Microsoft Corporation, 1992.