2016-07-20 32 views
1

In x86, ich verstehe, dass Multi-Byte-Objekte im Speicher Little Endian Stil gespeichert sind.Linux x86 CPU Anweisung Layout Confusion

Wenn es um CPU-Befehle geht, bestimmt der OPCODE den Zweck der Anweisung und die Daten/Speicheradressen können dem Opcode in seinem codierten Format folgen. Nach meinem Verständnis sollte der Opcode-Teil des Befehls das höchstwertige Byte sein und somit an der höchsten Adresse irgendeiner gegebenen Befehlscodierungsdarstellung erscheinen.

Kann jemand das Speicherlayout auf diesem x86 linux gdb Beispiel erklären? Ich könnte mir vorstellen, dass der Opcode 0xb8 wegen des höchstwertigen Bytes an einer höheren Adresse erscheinen würde.

(gdb) disassemble _start 

Dump of assembler code for function _start: 
0x08048080 <+0>: mov eax,0x11223344 

(gdb) x/1xb _start+0 
0x8048080 <_start>:  0xb8 
(gdb) x/1xb _start+1 
0x8048081 <_start+1>: 0x44 
(gdb) x/1xb _start+2 
0x8048082 <_start+2>: 0x33 
(gdb) x/1xb _start+3 
0x8048083 <_start+3>: 0x22 
(gdb) x/1xb _start+4 
0x8048084 <_start+4>: 0x11 

Es scheint, die Anweisung MOV EAX, 0x11223344 ist Kodierung als 0x11 0x22 0x33 0x44 0xB8.

Fragen.

1.) Wie weiß die CPU, wie viele Bytes der Befehl aufnehmen wird, wenn das erste Byte, das er sieht, kein Opcode ist?

2.) Ich frage mich, ob vielleicht x86-CPU-Anweisungen nicht einmal Endian-Ness haben und eine Art von String in Betracht ziehen? (wahrscheinlich weit weg)

+1

# 2 ist korrekt.Anweisungen haben keine Endianität, obwohl in ihnen eingebettete Konstanten dies tun. Wie Sie in Ihrem gdb-Dump sehen können, ist der Opcode ** ** das erste Byte (aber ihm können Präfix-Bytes vorangestellt werden). Siehe auch _Intel® 64 und IA-32 Architectures Software Developer's Manual Band 2: Befehlsreferenz, AZ, KAPITEL 2 INSTRUCTION FORMAT_ – Jester

+0

Ich kann Multibyte-Ganzzahlen mit einer CPU-Anweisung verwechseln, die mehr als ein Byte umfasst, wenn es um den Speicher geht Darstellung – htederson

+0

Dank Jester für den Hinweis, dass der Opcode * ist * das erste Byte der codierten Anweisung, die man von mir rutschte. – htederson

Antwort

5

x86 ist ein Befehlssatz variabler Länge, Sie beginnen mit einem einzelnen Byte, das keine Endianz hat, es ist wo auch immer es ist.

Dann kann es abhängig vom Opcode mehr Bytes geben und diese könnten zum Beispiel ein 32 Bit sofortiges sein, und (wenn diese Gruppe von Bytes eine unmittelbare oder eine Adresse irgendeiner Art ist), sind diese Bytes Little Endian. Angenommen, Sie haben die fünf Bytes ABCDE (keine Endianess, Think Array oder String). Das A-Byte ist der Opcode, das B-Byte wäre dann die unteren 8 Bits des Unmittelbaren und das E die oberen 8 Bits des Unmittelbaren.

Opcode ist ein schwer zu benutzender Begriff, in diesen älteren 8/16 Bit CISC-Prozessoren wie x86 war das ganze Byte ein Opcode, den Sie im Grunde genommen in einer Tabelle nachgesehen haben (und zwar im Prozessor) eine Tabelle, um herauszufinden, wie man es ausführt). Wenn Sie MIPS oder ARM oder andere (sicherlich RISC) Befehlssätze wie diese betrachten, ist nur ein Teil der 32 Bits der "Opcode" und in keinem dieser Fälle ist es der gleiche Satz von Bits von einer Anweisung zur anderen, Sie müssen sich verschiedene Stellen in der Anweisung ansehen (ja, es gibt Überlappungen, um die Decodierung vernünftig zu machen), MIPS ist viel konsistenter, man hat einen Blob an einer Stelle, aber man muss sich einen anderen Blob ansehen Bits zum vollständigen Decodieren. ARM Sie beginnen mit einem gemeinsamen Bit und während Sie Ihren Weg über Sie arbeiten, dekodieren Sie den Befehl weiter, dann müssen Sie möglicherweise einige zufällig aussehende Punkte greifen, um vollständig zu decodieren. Der Rest der Bits sind Operanden, welche Register zu verwenden oder unmittelbar oder was auch immer die Art von Sache in einem CISC, für die Sie eine Nachschlagetabelle benötigten (sind durch den Opcode impliziert, aber nicht durch Bits in dem Opcode definiert).

1) Das nächste Byte nach der vorherigen Anweisung wird als Opcode interpretiert, auch wenn es nicht dazu bestimmt ist, eins zu sein (wenn die Ausführung mit diesem Byte fortgesetzt wird und nicht verzweigt wird). Ich erinnere mich nicht an meine x86-Tabelle aus der Hand zu wissen, ob es irgendwelche undefinierten Anweisungen oder nicht, wenn undefiniert dann wird es einen Handler treffen, sonst wird es entschlüsseln, was es als Maschinencode findet und wenn es nicht richtig gebildet Anweisungen wird wahrscheinlich abstürzen, manchmal hast du Glück und es bringt etwas durcheinander und geht weiter, oder noch glücklicher und du kannst nicht sagen, dass es fast abgestürzt ist.

2) Sie sind richtig für diese 8/16-Bit CISC oder ähnliche Befehlssätze werden sie eher wie Zeichenfolgen behandelt, die Sie linear analysieren.

+0

Ja, ich bin mir bewusst, dass ARM und MIPS 16 Bit alternative Befehlssätze in einigen ihrer Kerne haben ARM sogar schlechter mit einem 16-Bit-Befehlssatz variabler Länge (thumb2-Erweiterungen zum Daumen). Plus all das Floating-Point-Zeug, vielleicht ein JAVA-Ding usw. Für obige Erklärungen ist es einfach in Ordnung, nur über einen festen 32-Bit-Befehl zu sprechen. Wenn Sie etwas googlen, sollten Sie die Kodierungen für Mips und Arm finden und vielleicht können Sie sehen, wie sie entschlüsseln, beide haben unterschiedliche Ansätze zu ihrem Design. –

+0

Danke dwell, ich schätze Ihre Einsicht. – htederson

+0

Ich denke, ich habe vielleicht die Frage 1) nicht beantwortet. Wie die CPU weiß, ist der Opcode, den sie liest, sagt es. Es weiß aus dem Opcode und/oder zusätzlichen Bytes, die folgen, wie viele Bytes insgesamt für diesen Befehl benötigt werden. Es hat eine variable Länge, so dass einige Anweisungen so kurz wie ein Byte sind und andere relativ lang sein können. Ich denke, die Frage, was die längste Intel-Anweisung ist, wurde mehrmals gestellt, nicht diese interessante IMO, aber einige Leute spielten mit. –