2012-11-01 9 views
7

Ich versuche das Verhalten von GAS in .code16 zu verstehen. Aus dem Handbuch geht hervor, dass im 16-Bit-Abschnitt für 32-Bit-Operanden oder -Befehle ein 66H-Operanden-Override-Präfix für die Befehlskodierung erzeugt wird. Heißt dasOperandengrößenpräfix im 16-Bit-Modus

.code16 
movw %eax, %ebx 

ist in diesem Modus legal? Dann kann der Code nicht auf 16-Bit-Prozessor ausgeführt werden?

+0

Dies ist nicht zulässig, da das Suffix "w" eine 2-Byte-Verschiebung anzeigt. 'movl% eax,% eax' ist jedoch legal. – fuz

Antwort

10

Dies sind rechtliche Anweisungen für 80386+. Beginnend mit dem 80386 können wir operandsize- und addresssize-override Präfixe verwenden. Diese Präfixe können in Kombination mit dem 16-Bit-Adressmodus und dem 32-Bit-Adressmodus verwendet werden. Zusätzlich kann es mit dem realen Adressmodus und mit dem geschützten Modus und dem virtuellen 86 Modus verwendet werden. Diese Präfixe kehren die Standardoperandengröße und/oder die Adressgröße für eine Anweisung in dem Codesegment um. Die Standardoperandengröße und die Adressgröße werden durch das D-Flag im Codesegmentdeskriptor angegeben (oder wenn es keine GDT/LDT gibt, werden wir nach dem POST-Prozess des Bios zum 16-Bit-Adressmodus).

Bei dem 16 Bit Adressmodus müssen wir diese Präfixe hinzufügen, wenn wir 32 Bit Operanden und/oder 32 Bit Adressen verwenden wollen. Ohne diese Präfixe können wir nur 16-Bit-Adressen/Operanden im 16-Bit-Adressmodus verwenden.

Beim 32-Bit-Adressmodus müssen wir diese Präfixe aus unserem Code weglassen, wenn wir 32-Bit-Operanden und/oder 32-Bit-Adressen verwenden wollen. Und wenn wir diese Präfixe zu unserem Code hinzufügen, können wir 16-Bit-Adressen/Operanden im 32-Bit-Adressmodus verwenden.

Blockquote Intel:

Instruction Präfixe können die Standard-Operandengröße und die Adresse Größe eines Code-Segment zu überschreiben, verwendet werden. Diese Präfixe können sowohl im Real-Address-Modus als auch im Protected-Modus und Virtual-8086-Modus verwendet werden. Ein Präfix in Operandengröße oder Adressgröße ändert nur die Größe für die Dauer der Anweisung.

Die folgenden zwei Befehls Präfixe ermöglichen Mischen von 32-Bit- und 16-Bit-Operationen innerhalb eines Segments: • der Operand-size Präfix (66H) • Die Adressengröße Präfix (67H)

Diese Präfixe Umkehren Sie die Standardgröße, die durch das D-Flag im Codesegmentdeskriptor ausgewählt wurde. Der Prozessor kann beispielsweise den Befehl (MOV mem, reg) auf eine der folgenden vier Arten interpretieren: • In einem 32-Bit-Code-Segment: - Verschiebt 32 Bits von einem 32-Bit-Register in einen 32-Bit-Speicher Adresse. - Wenn ein Präfix mit Operandengröße vorangestellt wird, werden 16 Bits aus einem 16-Bit-Register unter Verwendung einer effektiven 32-Bit-Adresse in den Speicher verschoben. - Wenn ein Präfix für die Adressgröße vorangestellt wird, werden 32 Bits aus einem 32-Bit-Register unter Verwendung einer effektiven 16-Bit-Adresse in den Speicher verschoben. - Wenn sowohl ein Präfix für die Adressgröße als auch ein Präfix für die Operandengröße vorangestellt wird, werden 16 Bits von einem 16-Bit-Register unter Verwendung einer effektiven 16-Bit-Adresse in den Speicher verschoben.

• In einem 16-Bit-Code-Segment: - Verschiebt 16 Bits von einem 16-Bit-Register in den Speicher unter Verwendung einer 16-Bit-Adresse. - Wenn ein Präfix mit Operandengröße vorangestellt wird, werden 32 Bits aus einem 32-Bit-Register unter Verwendung einer effektiven 16-Bit-Adresse in den Speicher verschoben. - Wenn ein Präfix für die Adressgröße vorangestellt wird, werden 16 Bits aus einem 16-Bit-Register unter Verwendung einer 32-Bit-Adresse in den Speicher verschoben. - Wenn sowohl ein Präfix für die Adressgröße als auch ein Präfix für die Operandengröße vorangestellt wird, werden 32 Bits aus einem 32-Bit-Register unter Verwendung einer effektiven 32-Bit-Adresse in den Speicher verschoben.

Die vorherigen Beispiele zeigen, dass jeder Befehl eine beliebige Kombination aus Operandengröße und Adressgröße generieren kann, unabhängig davon, ob sich der Befehl in einem 16- oder 32-Bit-Segment befindet. Die Auswahl des 16- oder 32-Bit-Standards für ein Codesegment basiert normalerweise auf den folgenden Kriterien: • Leistung - Verwenden Sie nach Möglichkeit immer 32-Bit-Codesegmente. Sie laufen viel schneller als 16-Bit-Code-Segmente auf Prozessoren der P6-Familie und etwas schneller auf früheren IA-32-Prozessoren. • Das Betriebssystem, auf dem das Codesegment ausgeführt wird - Wenn das Betriebssystem ein 16-Bit-Betriebssystem ist, unterstützt es möglicherweise keine 32-Bit-Programmmodule. • Funktionsweise - Wenn das Codesegment für die Ausführung im Real-Adress-Modus, Virtual-8086-Modus oder SMM ausgelegt ist, muss es sich um ein 16-Bit-Codesegment handeln. • Abwärtskompatibilität zu früheren IA-32-Prozessoren - Wenn ein Codesegment auf einem Intel 8086- oder Intel 286-Prozessor ausgeführt werden kann, muss es sich um ein 16-Bit-Codesegment handeln.

Das D-Flag in einem Code-Segment-Deskriptor bestimmt die Standardoperandengröße und Adressgröße für die Anweisungen eines Codesegments. (Im Real-Adress-Modus und im Virtual-8086-Modus, die keine Segmentdeskriptoren verwenden, ist der Standardwert 16 Bit.) Ein Code-Segment mit gesetztem D-Flag ist ein 32-Bit-Segment; Ein Code-Segment, dessen D-Flag gelöscht ist, ist ein 16-Bit-Segment.

Ausführbares Codesegment. Das Flag wird als D-Flag bezeichnet und gibt die Standardlänge für effektive Adressen und Operanden an, auf die in den Anweisungen im Segment Bezug genommen wird. Wenn das Flag gesetzt ist, werden 32-Bit-Adressen und 32-Bit- oder 8-Bit-Operanden angenommen; Wenn dies klar ist, werden 16-Bit-Adressen und 16-Bit- oder 8-Bit-Operanden angenommen. Das Befehlspräfix 66H kann verwendet werden, um eine andere Operandengröße als die Standardgröße auszuwählen, und das Präfix 67H kann verwendet werden, um eine andere Adressgröße als die Standardadresse auszuwählen.

Das 32-Bit-Operandenpräfix kann in Real-Adress-Modus-Programmen verwendet werden, um die 32-Bit-Formen von Anweisungen auszuführen. Dieses Präfix ermöglicht auch Real-Address-Modus-Programmen, die 32-Bit-Allzweckregister des Prozessors zu verwenden. Das 32-Bit-Adresspräfix kann in Real-Modus-Programmen verwendet werden, wodurch 32-Bit-Offsets zulässig sind.

Die IA-32-Prozessoren, die mit dem Intel386-Prozessor beginnen, können 32-Bit-Offsets unter Verwendung eines Adressen-Override-Präfix erzeugen; Im Real-Adress-Modus darf der Wert eines 32-Bit-Offsets jedoch FFFFH nicht überschreiten, ohne eine Ausnahme zu verursachen.

Assembler Verwendung: Wenn ein Codesegment definiert wird, das im Real-Adress-Modus ausgeführt wird, muss es auf ein USE 16-Attribut festgelegt werden. Wenn ein 32-Bit-Operand in einem Befehl in diesem Codesegment verwendet wird (z. B. MOV EAX, EBX), generiert der Assembler automatisch ein Operandenpräfix für den Befehl, der den Prozessor zur Ausführung einer 32-Bit-Operation zwingt, obwohl sein Standard-Code-Segment-Attribut ist 16-Bit.

Das 32-Bit-Operandenpräfix ermöglicht einem Real-Adress-Modus-Programm die Verwendung der 32-Bit-Allzweckregister (EAX, EBX, ECX, EDX, ESP, EBP, ESI und EDI).

Beim Verschieben von Daten im 32-Bit-Modus zwischen einem Segmentregister und einem 32-Bit-Allzweckregister benötigt der Pentium Pro-Prozessor kein 16-Bit-Operandengrößenpräfix; jedoch erfordern einige Assembler dieses Präfix. Der Prozessor nimmt an, dass die 16 niedrigstwertigen Bits des Universalregisters der Ziel- oder Quelloperand sind. Wenn ein -Wert von einem Segmentselektor in ein 32-Bit-Register verschoben wird, füllt der Prozessor die zwei höherwertigen Bytes des Registers mit Nullen.

Blockquote AMD:

3.3.2. 32-Bit- und 16-Bit-Adress- und Operandengrößen Der Prozessor kann für 32-Bit- oder 16-Bit-Adress- und Operandengrößen konfiguriert werden. Bei 32-Bit-Adress- und -Operandengrößen ist die maximale lineare Adresse oder der maximale Segmentoffset FFFFFFFFH (2^32-1), und Operandengrößen sind normalerweise 8 Bit oder 32 Bit. Bei 16-Bit-Adress- und -Operandengrößen ist die maximale lineare Adresse oder der Segmentoffset FFFFH (2^16-1), und Operandengrößen sind typischerweise 8 Bits oder 16 Bits. Bei Verwendung der 32-Bit-Adressierung besteht eine logische Adresse (oder Fernzeiger) aus einem 16-Bit-Segment Selektor und einem 32-Bit-Offset; Bei Verwendung einer 16-Bit-Adressierung besteht sie aus einem 16-Bit-Segmentselektor und einem 16-Bit-Offset. Befehlspräfixe ermöglichen vorübergehende Überschreibungen der Standardadress- und/oder Operandengrößen von innerhalb eines Programms. Im geschützten Modus definiert der Segmentdeskriptor für den aktuell ausgeführten Code die Standardadresse und die Operandengröße. Ein Segmentdeskriptor ist eine Systemdatenstruktur , die normalerweise für den Anwendungscode nicht sichtbar ist. Assembler-Direktiven ermöglichen die Standardadresse Adressierung und Operandengröße für ein Programm ausgewählt werden. Der Assembler und andere Tools setzen dann den Segmentdeskriptor für das Codesegment entsprechend hoch. Im Real-Adress-Modus beträgt die Standardadressierungs- und Operandengröße 16 Bit. Ein Adressgrößen-Override kann im Real-Adress-Modus verwendet werden, um eine 32-Bit-Adressierung zu ermöglichen. Die maximal zulässige lineare 32-Bit-Adresse ist jedoch immer noch 000FFFFFH (2^20-1).

3.6. OPERAND-SIZE UND ADDRESS-SIZE-ATTRIBUTE Wenn der Prozessor im geschützten Modus ausgeführt wird, hat jedes Code-Segment ein Standard-Operanden-Größe Attribut und Adress-Größe-Attribut. Diese Attribute werden mit dem Flag D (Standardgröße) im Segmentdeskriptor für das Codesegment ausgewählt (siehe Kapitel 3, Geschützter-Modus-Speicher Management, im Intel Architecture Software Developer's Manual, Band 3). Wenn das Flag D gesetzt ist, werden die 32-Bit-Operandengrößen- und Adressgrößenattribute ausgewählt; Wenn das Flag deaktiviert ist, werden die 16-Bit-Attribute ausgewählt. Wenn der Prozessor im Real-Adress-Modus, Virtual-8086-Modus oder SMM (System-Management-Modus) ausgeführt wird, sind die Standardgrößen für Operandengröße und Adressgröße immer 16 Bits. Das Operandengrößenattribut wählt die Operandengrößen aus, für die Anweisungen ausgeführt werden. Wenn das 16-Bit-Operandengrößenattribut in Kraft ist, können Operanden im Allgemeinen entweder 8 Bits oder 16 Bits sein, und , wenn das 32-Bit-Operandengrößenattribut in Kraft ist, können Operanden im Allgemeinen 8 Bits oder 32 Bits sein. Das Attribut "address-size" wählt die Größe der Adressen aus, die zum Adressieren des Speichers verwendet werden: 16 Bits oder 32 Bits. Wenn das 16-Bit-Adressgrößenattribut in Kraft ist, sind Segmentoffsets und Verschiebungen 16 Bits. Diese Einschränkung begrenzt die Größe eines Segments, das an 64 KByte adressiert werden kann. Wenn das 32-Bit-Adressgrößenattribut in Kraft ist, sind Segmentoffsets und Verschiebungen 32 Bit, wodurch Segmente mit bis zu 4 GByte adressiert werden können. Das standardmäßige Operandengrößenattribut und/oder Adressgrößenattribut kann für eine bestimmte -Anweisung außer Kraft gesetzt werden, indem ein Operandengrößen- und/oder Adressgrößenpräfix zu einer Anweisung hinzugefügt wird (siehe "Anweisungsvorgaben" in Kapitel 2 des Intel Architecture Software Entwicklerhandbuch, Band 3).Die Wirkung dieses Präfixes gilt nur für die Anweisung, an die es angehängt ist. Tabelle 3-1 zeigt die effektive Operandengröße und die Adressgröße (bei Ausführung im geschützten Modus) abhängig von den Einstellungen des D-Flags und der Operandengrößen- und Adressgrößenpräfixe.

Dirk

Verwandte Themen