Intel-Speichermodell - Intel Memory Model

In Computing , Intel Speichermodell bezieht sich auf einen Satz von sechs verschiedenen Speichermodelle des x86 CPU - Betriebs in Real - Mode , die steuern , wie die Segmentregistern verwendet werden , und die Standardgröße von Zeigern.

Speichersegmentierung

Vier Register werden verwendet, um auf vier Segmente in der segmentierten 16-Bit-x86-Speicherarchitektur zu verweisen. DS ( Datensegment), CS ( Code - Segment), SS ( Stack - Segment), und ES (extra - Segment). Ein anderes 16-Bit-Register kann als Versatz in ein bestimmtes Segment fungieren, und daher wird eine logische Adresse auf dieser Plattform als Segment geschrieben : Versatz , typischerweise in hexadezimaler Notation. Um die physikalische Adresse eines Speicherbytes zu berechnen, verschiebt die Hardware im Realmodus den Inhalt des entsprechenden Segmentregisters um 4 Bit nach links (effektiv mit 16 multiplizieren) und addiert dann den Offset.

Beispielsweise liefert die logische Adresse 7522: F139 die physikalische 20-Bit-Adresse:

  75220
+ F139
  84359

Beachten Sie, dass dieser Prozess zu einem Aliasing des Speichers führt, sodass jede gegebene physikalische Adresse bis zu 4096 entsprechende logische Adressen hat. Dies erschwert den Vergleich von Zeigern auf verschiedene Segmente.

Zeigergrößen

Zeigerformate werden als nah , fern oder riesig bezeichnet .

  • Nahe Zeiger sind 16-Bit-Offsets innerhalb des Referenzsegments, dh DS für Daten und CS für Code. Sie sind die schnellsten Zeiger, können jedoch auf 64 KB Speicher (auf das zugehörige Segment des Datentyps) verweisen. Nahe Zeiger können in Registern gehalten werden (typischerweise SI und DI).
    mov bx, word [reg]
    mov ax, word [bx]
    mov dx, word [bx+2]
  • Far - Pointer sind 32-Bit Zeiger enthalten ein Segment und ein Offset. Um sie zu verwenden, wird das Segmentregister ES unter Verwendung der Anweisung verwendet les [reg]|[mem],dword [mem]|[reg] . Sie können bis zu 1024 KiB Speicher referenzieren  . Beachten Sie, dass die Zeigerarithmetik (Addition und Subtraktion) nicht den Segmentteil des Zeigers ändert, sondern nur dessen Versatz. Operationen, die die Grenzen von Null oder 65535 (0xFFFF) überschreiten, werden wie jede normale 16-Bit-Operation einer Modulo-64K-Operation unterzogen. Wenn beispielsweise das Segmentregister auf 0x5000 festgelegt und die Offset wird inkrementiert wird, das der Moment Zähler Offset wird (0x10000), die ergebende absolute Adresse 0x5000 überschlagen wird: 0000.
    les bx,dword [reg]
    mov ax,word [es:bx]
    mov dx,word [es:bx+2]
  • Riesige Zeiger sind im Wesentlichen Fernzeiger, werden jedoch (meistens) jedes Mal normalisiert, wenn sie so geändert werden, dass sie das höchstmögliche Segment für diese Adresse haben. Dies ist sehr langsam, ermöglicht es dem Zeiger jedoch, auf mehrere Segmente zu zeigen, und ermöglicht genaue Zeigervergleiche, als wäre die Plattform ein flaches Speichermodell : Es verbietet das Aliasing des Speichers wie oben beschrieben, sodass zwei große Zeiger auf denselben Speicher verweisen Standort sind immer gleich.
    les bx,dword [reg]
    mov ax,word [es:bx]
    add bx,2
    test bx,0xfff0
    jz lbl
    sub bx,0x10
    mov dx,es
    inc dx
    mov es,dx
 lbl:
    mov dx,word [es:bx]

Speichermodelle

Die Speichermodelle sind:

Modell Daten Code Definition
Winzig* in der Nähe von CS = DS = SS
Klein in der Nähe von** in der Nähe von DS = SS
Mittel in der Nähe von** weit DS = SS, mehrere Codesegmente
Kompakt weit in der Nähe von einzelnes Codesegment, mehrere Datensegmente
Groß weit weit mehrere Code- und Datensegmente
Enorm enorm weit mehrere Code- und Datensegmente; Ein einzelnes Array kann> 64 KB groß sein

Andere Plattformen

Im geschützten Modus kann ein Segment nicht sowohl beschreibbar als auch ausführbar sein. Daher muss bei der Implementierung des Tiny-Speichermodells das Codesegmentregister auf dieselbe physikalische Adresse zeigen und dieselbe Grenze wie das Datensegmentregister haben. Dies hat eine der Funktionen des 80286 zunichte gemacht , die sicherstellt, dass Datensegmente niemals ausführbar und Codesegmente niemals beschreibbar sind (was bedeutet, dass selbstmodifizierender Code niemals zulässig ist). Beim 80386 ist es jedoch mit seiner ausgelagerten Speicherverwaltungseinheit möglich, einzelne Speicherseiten vor dem Schreiben zu schützen.

Speichermodelle sind nicht auf 16-Bit-Programme beschränkt. Es ist möglich, die Segmentierung auch im 32-Bit-geschützten Modus zu verwenden (was zu 48-Bit-Zeigern führt), und es gibt C-Sprach-Compiler, die dies unterstützen. Die Segmentierung im 32-Bit-Modus ermöglicht jedoch keinen Zugriff auf einen größeren Adressraum als das, was ein einzelnes Segment abdecken würde, es sei denn, einige Segmente sind nicht immer im Speicher vorhanden und der lineare Adressraum wird nur als Cache über einen größeren segmentierten virtuellen Raum verwendet . Es ermöglicht einen besseren Schutz für den Zugriff auf verschiedene Objekte (Bereiche mit einer Länge von bis zu 1 MB können von einer Ein-Byte-Zugriffsschutzgranularität im Vergleich zu der groben 4-KiB-Granularität profitieren, die durch alleiniges Paging geboten wird) und wird daher nur in speziellen Anwendungen wie der Telekommunikation verwendet Software. Technisch gesehen ist der "flache" 32-Bit-Adressraum ein "winziges" Speichermodell für den segmentierten Adressraum. Unter beiden Regentschaften enthalten alle vier Segmentregister ein und denselben Wert.

x86-64

Auf der x86-64- Plattform existieren insgesamt sieben Speichermodelle, da die meisten Symbolreferenzen nur 32 Bit breit sind und die Adressen zur Verbindungszeit bekannt sind (im Gegensatz zu positionsunabhängigem Code ). Dies wirkt sich nicht auf die verwendeten Zeiger aus, bei denen es sich immer um flache 64-Bit-Zeiger handelt, sondern nur darauf, wie Werte platziert werden können, auf die über Symbole zugegriffen werden muss.

Siehe auch

Literaturverzeichnis

  • Turbo C ++ Version 3.0 Benutzerhandbuch . Borland International, Copyright 1992.

Verweise