Kann jemand erklären, diese direkt montiert x86 JMP-opcode?
In der Schule haben wir ein bootstrap-Programm zum ausführen von stand-alone-Programme, die ohne Betriebssystem. Ich studiere seit diesem Programm und wenn der geschützte Modus aktiviert ist, gibt es eine weit springen, ausgeführt durch die direkte Montage der opcode und die Operanden als Daten innerhalb des Programms. Dies war für den GNU-assembler:
/* this code immediately follows the setting of the PE flag in CR0 */
.byte 0x66, 0xEA .long TARGET_ADDRESS .word 0x0010 /* descriptor #2, GDT, RPL=0 */
Zunächst, warum würde man wollen, dies zu tun (anstelle der Anweisung Mnemonik)?
Bin ich auf der Suche auf der Intel-Handbücher, aber bin immer noch ein wenig verwirrt durch den code. Speziell in Band 2A, Seite 3-549, gibt es eine Tabelle der opcodes. Der relevante Eintrag:
EA *cp* JMP ptr16:32 WR. Gültige Springen weit, absolute Adresse im operandDen eigentlichen opcode, ist klar, aber das das erste byte, 0x66, hat mich verwirrt. Unter Bezugnahme auf die Tabelle im Intel-Handbuch, der cp scheint zu bedeuten, dass ein 6-byte-operand Folgen. Und natürlich 6 bytes Folgen in den nächsten beiden Zeilen. 0x66 kodiert für ein 'Operand-size override-Präfix'. Was hat das zu tun mit der cp in der Tabelle? Ich hatte erwartet, es werden einige hex-Wert für die cp, sondern es ist dieser override-Präfix. Kann jemand bitte deaktivieren Sie dieses, für mich?
Hier ist ein dump von od:
c022 **ea66 0000 0001 0010** ba52 03f2 c030TARGET_ADDRESS wurde definiert als 0x00010000.
Ich bin auch verwirrt ein wenig durch die Bedeutung der in den letzten zwei bytes. Aber dass scheint zu sein, ein anderes überhaupt nicht in Frage. Es ist schon ziemlich spät, und ich habe gestarrt, auf code-und die Intel-Handbücher für Stunden, so ich hoffe ich habe meinen Standpunkt zu vermitteln.
Dank für das schauen!
- Menschen nutzen opcodes (statt Anweisungen) aus 2 Gründen. Der erste Grund ist, wenn der assembler ist "weniger als ausreichend" und bietet keine Unterstützung für die Anleitung, die Sie benötigen (das ist/war üblich, wenn neue Anweisungen Hinzugefügt und ältere Monteure nicht unterstützen, Sie noch). Der zweite Grund ist, wenn der assembler unterstützt die Anweisung, die Sie benötigen, aber die Programmierer nicht wissen, wie Sie zu überzeugen, die assembler zu generieren. Im Grunde, ist es entweder schlechte tools (darunter auch alte Werkzeuge, verwirrende syntax und/oder schlechte Dokumentation) oder schlechte Programmierer.
- Hinweis: Mein Kommentar oben ist "im Allgemeinen" und gilt für alle Monteure. Ich nicht mit GAS, und habe keine Ahnung, ob es unterstützt die "32-bit-far-jump in 16-bit-code" - Befehl ist oder nicht (oder wie gut/schlecht die Dokumentation ist).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den 0x66 zeigt an, dass der JMP - (0xEA) bezieht sich auf sechs bytes. Der Standard bezieht sich auf 64K (16 bit) im real-mode oder 32 bit protected mode (wenn ich mich erinnere gut). Es erhöht, es enthält auch die segment-Deskriptor, der index des Segments entweder die GDT oder die LDT, was bedeutet, dass dieser code macht das, was ist traditionell genannt "long jump": ein Sprung, bei dem Kreuz über Segmente in der x86-Architektur. Das segment, in diesem Fall Punkte, um den zweiten Eintrag in der GDT. Wenn Sie schauen, bevor Sie in diesem Programm, Sie ' ll wahrscheinlich sehen, wie die GDT ist definiert in Bezug auf die segment-Startadresse und die Länge (schauen Sie in das Intel manual zu studieren, die GDT und die LDT-Tabellen, 32-bit-Eintrag, die Beschreibung jedes segment).
jmp ptr16:16
injmp ptr16:32
. Diese Antwort behauptet, die nicht-Präfix-version wärejmp rel16
oderjmp rel32
, aber das ist eine andere opcodeE9
nichtEA
.EA
ist immer einen far-jmp-mit sofortiger offset-und segment.Ich mit diesem ein bisschen. Einige Assembler wird nur Sprung zu einem LABEL . In diesem Fall wird die person will, um einen absoluten Sprung an eine bestimmte hard-codiert-offset. jmp TARGET_ADDRESS wird nicht funktionieren, ich vermute, so Sie setzen Sie ihn einfach als bytes zu bekommen, um dieses Problem.
0x66 gibt operand size override der aktuelle code segment size. Unter der Annahme, dass die aktuelle code-Größe ist 16-bit, der neue instruction pointer 32-bit, nicht 16 bit. Wenn die aktuellen code-segment-Größe ist 32-bit, die 0x66 wird die render-target-instruction-pointer) als 16-bit. Die aktuelle code-Größe-Attribut hängt von CS-Selektor im Einsatz und seine geladenen Attribute werden von der GDT/LDT-Tabelle. Im real-Modus der code-segment-Größe ist in der Regel 16-bit-außer in besonderen Fällen von "unreal" - Modus.