Frage

Ich bin daran interessiert, als Bildungsprojekt einen x86-Dissembler zu schreiben.

Die einzige wirkliche Ressource, die ich gefunden habe, ist die von Spiral Space: „Wie schreibe ich einen Disassembler?".Obwohl dies eine schöne allgemeine Beschreibung der verschiedenen Komponenten eines Disassemblers ist, bin ich an detaillierteren Ressourcen interessiert.Ich habe auch mal kurz reingeschaut NASMs Quellcode, aber es ist ziemlich schwierig, daraus zu lernen.

Mir ist klar, dass eine der größten Herausforderungen dieses Projekts der ziemlich große x86-Befehlssatz ist, mit dem ich umgehen muss.Ich interessiere mich auch für die Grundstruktur, grundlegende Disassembler-Links usw.

Kann mir jemand detaillierte Ressourcen zum Schreiben eines x86-Disassemblers nennen?

War es hilfreich?

Lösung

Hier finden Sie aktuelle Abschnitt 17.2 der 80386 Programmierer Referenzhandbuch . Ein Disassembler ist wirklich nur ein besserer rel="noreferrer">. Die Schritte in der Demontage sind:

  1. Überprüfen Sie, ob das aktuelle Byte ein Befehl Präfix-Byte (F3, F2 oder F0) ist; wenn ja, dann haben Sie einen REP / REPE / REPNE / LOCK Präfix bekommen. Rückt zum nächsten Byte.
  2. Überprüfen Sie, ob das aktuelle Byte eine Adresse Größe Byte (67) ist. Wenn ja, dekodieren Adressen in dem Rest der Anweisung in 16-Bit-Modus, wenn zur Zeit in 32-Bit-Modus oder dekodieren Adressen in 32-Bit-Modus, wenn zur Zeit in 16-Bit-Modus
  3. Überprüfen Sie, ob das aktuelle Byte ein Operand Größe Byte (66) ist. Wenn ja, dekodieren Direktoperanden in 16-Bit-Modus, wenn zur Zeit in 32-Bit-Modus oder dekodieren Direktoperanden in 32-Bit-Modus, wenn zur Zeit in 16-Bit-Modus
  4. Überprüfen Sie, ob das aktuelle Byte ein Segment Korrektur-Byte ist (2E, 36, 3E, 26, 64 oder 65). Wenn der so ist, verwenden, um die entsprechenden Segmentregister für Adressen anstelle der Standard-Segmentregister dekodieren.
  5. Das nächste Byte ist der Opcode. Wenn der Opcode 0F ist, dann ist es ein erweiterter Opcode, und das nächste Byte als erweiterten Operationscode lesen.
  6. Abhängigkeit von dem bestimmten Operationscode, eingelesen und dekodieren einen Mod R / M-Byte, einen Skalenindex Base (SIB) Byte, eine Verschiebung (0, 1, 2 oder 4 Bytes), und / oder einen Sofortwert ( 0, 1, 2 oder 4 Bytes). Die Größen dieser Felder hängen von der Opcode, Adressgröße überschreiben, und Operandengröße überschreibt zuvor decodiert.

Der Opcode sagt Ihnen, die Operation durchgeführt wird. Die Argumente des Opcodes können die Werte der Mod R / M, SIB, Verschiebung und unmittelbaren Wert decodiert werden, bilden. Es gibt viele Möglichkeiten und viele Sonderfälle, aufgrund der komplexen Natur des x86. Siehe die Links für eine noch gründlichere Erklärung.

Andere Tipps

Ich würde empfehlen, einige Open-Source-Disassembler Check-out, vorzugsweise distorm und vor allem „disOps (Anleitung Sets DataBase) "(Strg + es auf der Seite finden).

Die Dokumentation selbst ist voll von saftigen Informationen über OP-Codes und Anweisungen.

Zitat von https://code.google.com / p / distorm / wiki / x86_x64_Machine_Code

  

80x86 Anweisung:

     

Ein 80x86-Befehl wird auf ein geteiltes   Anzahl der Elemente:

     
      
  1. Instruction Präfixe, beeinflusst das Verhalten der Anweisung des   Betrieb.
  2.   
  3. Mandatory Präfix als Opcode-Byte verwendet für SSE-Befehle.
  4.   
  5. Opcode Bytes, könnte eine oder mehr Bytes (bis zu 3 ganz Byte).
  6.   
  7. ModR / M-Byte ist optional und manchmal einen Teil der enthalten könnte   Opcode selbst.
  8.   
  9. SIB-Byte ist optional und stellt komplexen Speicher indirection   Formen an.
  10.   
  11. Weg ist optional und es ist ein Wert einer unterschiedlichen Größe   Bytes (Byte, Wort lang) und als eine verwendet   gegenüber.
  12.   
  13. Sofortige ist optional und wird als allgemeiner Zahlenwert verwendet gebaut   von einer unterschiedlichen Größe des Bytes (Byte,   Wort, lang).
  14.   
     

Das Format sieht wie folgt aus:

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

Die Datenstrukturen und Dekodierungsphasen erläutert in https://code.google.com / p / distorm / wiki / diStorm_Internals

Zitat:

  

Die Decodierung Phasen

     
      
  1. [Präfixe]
  2.   
  3. [Fetch Opcode]
  4.   
  5. [Filter Opcode]
  6.   
  7. [Auszug Operand (s)]
  8.   
  9. [Textformatierung]
  10.   
  11. [Hex Dump]
  12.   
  13. [Decoded Instruction]
  14.   

Jeder Schritt wird auch erklärt.


Die ursprünglichen Links werden aus historischen Gründen gehalten:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Code und http://code.google.com/p/distorm/wiki/diStorm_Internals

Starten Sie mit einigen kleinen Programm, das zusammengesetzt ist, und das gibt Ihnen sowohl den generierten Code und die Anweisungen. Holen Sie sich einen Verweis mit der Befehlsarchitektur , und die Arbeit durch einen Teil des generierten Code mit der Architektur referenzieren, von Hand. Sie finden, dass die Anweisungen, um eine sehr stereotypisch Struktur von inst op op op haben mit unterschiedlicher Anzahl von Operanden. Alles, was Sie tun müssen, ist die Hex oder Oktaldarstellung des Codes übersetzen Sie die Anweisungen entsprechen; ein wenig herumspielen wird es zeigen.

Das Verfahren, automatisiert, ist der Kern eines Disassembler. Idealerweise sind Sie wahrscheinlich einen n-Array von Befehlsstrukturen konstruieren wollen intern (oder extern, wenn das Programm wirklich groß ist). Anschließend können Sie das Array in die Anweisungen in Assembler-Format übersetzen.

Sie benötigen eine Tabelle mit Opcodes zum Laden.

Die grundlegende Suchdatenstruktur ist ein Versuch, eine Tabelle reicht jedoch aus, wenn Ihnen die Geschwindigkeit nicht so wichtig ist.

Um den Basis-Opcode-Typ zu erhalten, beginnen Sie mit einer Übereinstimmung in der Tabelle.

Es gibt einige Standardmethoden zum Dekodieren von Registerargumenten.Allerdings gibt es genügend Sonderfälle, sodass die meisten davon einzeln implementiert werden müssen.

Da dies lehrreich ist, werfen Sie einen Blick auf ndisasm.

Kasse objdump Quellen -. Es ist ein großes Werkzeug, es enthält viele Opcode Tabellen und die Quellen eine schöne Basis bieten können eigene Disassembler für die Herstellung

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top