Was ist die tatsächliche Beziehung zwischen Baugruppe, Maschinencode, Bytecode und Opcode?

7

Was ist die tatsächliche Beziehung zwischen Baugruppe, Maschinencode, Bytecode und Opcode?

Ich habe die meisten SO-Fragen zum Assembly- und Maschinencode gelesen, zB dies , aber sie sind zu hoch und zeigen keine Beispiele von tatsächlichem Assemblercode, der in Maschinencode umgewandelt wird. Daher verstehe ich immer noch nicht, wie es auf einer tieferen Ebene funktioniert.

Die ideale Antwort auf diese Frage würde ein spezifisches Beispiel für einen Assembler-Code zeigen, wie zum Beispiel das unten stehende Snippet, und wie jeder Assembly-Befehl dem Maschinencode, Bytecode und / oder Opcode zugeordnet wird. Eine solche Antwort wäre für zukünftige Menschen, die Montage lernen, sehr hilfreich, denn bisher habe ich in den letzten Tagen des Grabens keine klare Zusammenfassung gefunden.

Hauptsache ich suche:

  1. ein Code-Schnipsel
  2. ein Code-Schnipsel
  3. Eine Zuordnung zwischen dem Codeausschnitt und dem Maschinencode (wie man das Mapping vornimmt, oder zumindest einige allgemeine Beispiele, und wie wissen wie man das macht, wo es ist all diese Informationen im Web)
  4. wie man den Maschinencode interpretiert (wie Opcodes irgendwie verwandt sind, und wo ist all die Information im Web darüber, was all diese Zahlen bedeuten )

Hinweis: Ich habe keinen Informatik-Hintergrund, also bin ich in den letzten Jahren langsam tiefer gegangen und habe jetzt den Punkt erreicht, dass ich Assembler- und Maschinencode verstehen möchte.

Beziehung zwischen Baugruppe und Maschinencode

Mein derzeitiges Verständnis ist, dass ein "Assembler" (wie NASM) Assembler-Code nimmt und daraus Maschinencode erstellt.

Wenn Sie also eine Assembly wie dieses example.asm :

kompilieren %Vor%

(kompilieren Sie es mit nasm -f macho64 -o example.o example.asm ). Es gibt diese example.o Objektdatei aus:

%Vor%

(das ist der gesamte Inhalt von example.o ). Wenn Sie dann das mit ld -o example example.o "verknüpfen", erhalten Sie mehr Maschinencode:

%Vor%

Aber wie ist es von den Montageanweisungen zu diesen Zahlen gegangen? Gibt es eine Art Standardreferenz, die all diese Zahlen auflistet, und was sie bedeuten, für welche Architektur Sie auch immer sind (ich benutze x86-64 über NASM unter OSX) und wie jeder Zahlensatz zu jeder Assembleranweisung gehört ?

Ich verstehe, dass der Maschinencode für jede Maschine anders ist, und es gibt dutzende, wenn nicht Hunderte von verschiedenen Arten von Maschinen. Daher suche ich derzeit nicht danach, wie die Assemblierung in alle transformiert wird (das wäre kompliziert). Ich bin nur an einem Beispiel interessiert, das veranschaulicht, wie die Transformation funktioniert, und jede Architektur kann als Beispiel dienen. Und von diesem Punkt an könnte ich nach der spezifischen Architektur suchen, an der ich interessiert bin, und die Zuordnung finden.

Beziehung zwischen Assembly und Bytecode (oder heißt es "Opcode"?)

Nach meiner bisherigen Lektüre wird die Baugruppe in Maschinencode umgewandelt, wie oben gezeigt.

Aber jetzt bin ich verwirrt. Ich sehe Leute über Bytecode sprechen, wie zum Beispiel in dieser SO-Antwort , die Zeug wie folgt zeigt:

%Vor%      

Die Assembly für diese Funktion würde folgendermaßen aussehen:

%Vor%

Also werde ich verwirrt. Wenn ich etwas grabe, kann ich nicht sagen, ob jede dieser 2-stelligen hexadezimalen Zahlen wie 13 82 6a jeweils einzeln "Opcodes" genannt werden, und der ganze Satz davon wird "Bytecode" als Sammelbegriff genannt. Darüber hinaus kann ich keine Tabelle finden, die alle diese 2-stelligen Hex-Zahlen auflistet, und ihre Beziehung zu Maschinencode oder Assembly.

Zusammenfassend freue ich mich sehr auf ein Beispiel, das zeigt, wie Assembleranweisungen dem Maschinencode zugeordnet werden, und es ist eine Beziehung zu Bytecode und / oder Opcode. (Ich suche nicht, wie ein Compiler das macht, wie das allgemeine Mapping funktioniert). Ich denke, das würde es nicht nur für mich selbst erklären, sondern für viele Menschen auf der Straße, die mehr über den Bare Metal erfahren wollen.

Ein weiterer Grund, warum dies wertvoll wäre, ist, dass man verstehen kann, wie der LLVM-Compiler Maschinencode erzeugt. Haben sie eine Art "vollständige Liste" von 2-stelligen Opcodes oder 4-stelligen Maschinencode-Sequenzen und wissen genau, wie diese auf eine architekturspezifische Baugruppe abgebildet werden? Woher haben sie diese Informationen? Eine Antwort auf diese allgemeine Frage würde deutlich machen, wie LLVM seine Code-Generierung implementiert hat.

Aktualisieren

Aktualisierung von @ HansPassants Kommentar. Es interessiert mich eigentlich nicht, was die tatsächlichen Unterscheidungen zwischen den Wörtern sind, tut mir leid, wenn das nicht klar war.Ich möchte das nur wissen: Wie stellt Assembly den Code der Maschine dar (und wo sind die Orte, an denen man nach den Referenzen suchen muss, die diese Informationen im Web enthalten), und werden irgendwo in diesem Prozess Opcodes oder Bytecode verwendet? Und wenn ja wie?

    
Lance Pollard 23.12.2014, 23:15
quelle

6 Antworten

7

Ja, jede Architektur hat eine Befehlssatzreferenz, die angibt, wie Befehle codiert werden. Für x86 ist es die Entwicklerhandbuch für Intel® 64 und IA-32 Architekturen Band 2 (2A, 2B & amp; 2C): Befehlssatz-Referenz, AZ

Die meisten Assembler, einschließlich nasm , können eine Listendatei für Sie erstellen. Wenn Sie Ihren Beispielcode an nasm -l übergeben, erhalten Sie:

%Vor%

Sie können den generierten Maschinencode in der dritten Spalte sehen (die erste ist die Zeilennummer, die zweite Adresse).

Beachten Sie, dass die Ausgabe des Assemblers eine Objektdatei ist und die Ausgabe des Linkers eine ausführbare Datei ist. Beide haben eine komplexe Struktur und enthalten mehr als nur den Maschinencode. Aus diesem Grund unterscheidet sich Ihr hexdump von der obigen Auflistung.

Opcode wird im Allgemeinen als Teil des Maschinencode-Befehls betrachtet, der den auszuführenden Vorgang angibt. Zum Beispiel haben Sie im obigen Code B804000002 mov rax, 0x2000004 . Dort ist B8 der Opcode, 04000002 ist der unmittelbare Operand.

Bytecode wird normalerweise nicht im Assembly-Kontext verwendet, sondern könnte als Maschinencode für eine virtuelle Maschine betrachtet werden.

Für eine Komplettlösung ist x86 eine sehr komplizierte Architektur. Aber Ihr Beispielcode hat eine einfache Anweisung, die syscall . Sehen wir uns an, wie wir das in Maschinencode umwandeln können. Öffnen Sie das oben genannte Referenz-PDF und gehen Sie in Kapitel 4 zum Abschnitt über syscall . Sie sehen es sofort als Opcode 0F 05 aufgelistet. Da es keine Operanden benötigt, sind wir fertig, diese 2 Bytes sind der Maschinencode. Wie kehren wir es zurück? Gehe zu Appendix A: Opcode map . Abschnitt A.1 sagt uns: For 2-byte opcodes beginning with 0FH (Table A-3), skip any instruction prefixes, the 0FH byte (0FH may be preceded by 66H, F2H, or F3H) and use the upper and lower 4-bit values of the next opcode byte to index table rows and columns. . Okay, wir überspringen die 0F und teilen die 05 in 0 und 5 und suchen das in der Tabelle A-3 in Zeile # 0, Spalte # 5 nach. Wir finden es eine syscall Anweisung.

    
Jester 23.12.2014, 23:34
quelle
6
  

Gibt es eine Art Standardreferenz, die all diese Zahlen auflistet, und was sie bedeuten, für welche Architektur Sie sich auch interessieren und wie jede Zahlengruppe zu jeder Assembleranweisung gehört?

Ja, obwohl sie sehr komplex sein können. Außerdem sind sie aufgrund der Verbreitung von Assemblern und Compilern auch schwer zu finden, weil sie von niemandem verwendet werden.

  

Beziehung zwischen Assembly und Bytecode

  • Maschinencode - Ein oder mehrere Werte, die in eine CPU eingelesen werden. Jede Zahl ist ein "Befehl" oder "Opcode" und kann von einem oder mehreren Parametern gefolgt werden, auf die zu reagieren ist. Im verknüpften Code weist 13 den Prozessor an, eine Zeichenfolge auf den Stapel zu schieben.
  • OpCode - Der Wert für einen Befehl: Im Beispiel ist der Opcode für das Drücken einer Zeichenfolge 13 .
  • Assembly - lesbare Anweisungen für den internen Maschinencode einer CPU. So ziemlich immer eine Bauanleitung pro Maschinencode-Anweisung. In meinem Code, mit dem Sie verbunden sind, wird die Anweisung "assembly" PushString der Maschinenanweisung 13 zugeordnet.
  • Bytecode - Da jeder Prozessor einen anderen Maschinencode verwendet, kompilieren Programme manchmal zu einem Maschinencode für eine imaginäre "virtuelle Maschine" und haben dann ein Programm, das diesen gefälschten Maschinencode liest und ausführt (entweder über Emulation oder JIT ). Java und C # und VB tun dies. Dieser "falsche" Maschinencode wird "Bytecode" genannt, obwohl die Begriffe oft synonym verwendet werden.

Ich sollte beachten, dass die Bytecode-Anweisungen, die in diesem Post und in meinem anderen Beitrag, den Sie verlinkt haben, verwendet werden, vereinfachte Auszüge aus einem proprietären Byte-Code sind, mit dem ich bei meiner Firma arbeite. Wir haben eine proprietäre Programmiersprache, die zu diesem Bytecode kompiliert, der von unserem Produkt interpretiert wird, und einige der Werte, die ich erwähnte, sind echte Bytecodes, die wir tatsächlich verwenden. 13 ist eigentlich pushAnything mit komplexen Parametern, aber ich behalte die Dinge für die Antwort einfach.

    
Mooing Duck 23.12.2014 23:39
quelle
6

Sie haben eindeutig eigene Hausaufgaben gemacht, und ich sage gute Sachen (und habe Ihnen eins gewählt).

Wie Sie erfahren, je mehr Sie lesen, desto mehr sagen Sie "huh?"

Okay, zuerst, wenn Sie auf das Wort "Bytecode" stoßen, schließen Sie einfach das Fenster und hören Sie auf zu lesen, weil Sie sich auf dem falschen Weg befinden; wahrscheinlich eine Tangente im besten Fall und im schlimmsten Fall könnte man jemanden lesen, der versucht klüger zu klingen, als er wirklich ist, indem er technisch klingende Schlagworte in sein Schreiben wirft.

Was nun das Wort "Opcode" betrifft, so gibt es diese wirklich, aber verstehen Sie, dass diese Zahlen tatsächlich symbolisch sind, damit die Menschen sie begrifflich erfassen können. Im wirklichen Leben sind sie super-ultra-winzige Schalter.

Wenn Sie Geschichte und Technologie vor dem Internet (oder Farbfernsehen) wirklich mögen, schlagen Sie Sätze wie Schmetterlingsschalter, Vakuumröhren, Schmetterlingsmädchen nach und ich vergesse die anderen Wörter. Dies war zurück, bevor Transistoren existierten. Die ursprünglichen riesigen Computer verwendeten tatsächlich Vakuumröhren und erzeugten genügend Wärme, um einen gesamten Boden (oder zwei oder drei) eines Bürogebäudes im tiefsten Winter zu erwärmen. Die Stromaufnahme war erstaunlich.

Die Sache, die Sie dabei beachten sollten, ist, dass diese Computer "programmiert" wurden, indem man einzeln Schmetterlingsschalter umlegte ("Fledermausgriffe" waren ein anderer Begriff), die einzelne Leitungen von einzelnen Röhren verbanden und trennten was noch.

Die Fakten waren: Sie programmierten einen Computer, indem Sie die Fledermausgriffe umdrehten, die mit den Leitungen verbunden waren, die mit verschiedenen Röhren verbunden waren.

Schneller Vorlauf nach Heute ...

Wenn du einen Opcode von 90h schreibst (ich glaube, das ist ein NOP in x86, jemand korrigiert mich und ich werde es reparieren), machst du (mit dem heutigen Hallo-Tech-Wowe-Zowee) das Gleiche wie die Schmetterlings-Girls schon in der Steinzeit der Computer.

Genauer gesagt "werfen" Sie diese "Schmetterlingsschalter" ...

  • 7 - AN
  • 6 - AUS
  • 5 - AUS
  • 4 - EIN
  • 3 - AUS
  • 2 - AUS
  • 1 - AUS
  • 0 - AUS

Hier ist der große Unterschied (und Teil des heutigen Hi-Tech Wowee-Zowee) ...

Sie mussten genau diese Schalter an genau einer Stelle auf den Boden werfen. Du wirst sie überall spiegeln, wo du willst. Drei andere Programme werden zusammenarbeiten und diese Entscheidungen für Sie treffen.

Diese drei Programme sind - Der Monteur - Der Linker - Der Lader

Ich hoffe also, dass dies die Grundlage dafür ist, dass Sie verstehen, dass der OPCODE eine mentale Repräsentation einer Menge kleiner Schalter ist, die "geöffnet" oder "geschlossen" werden. .

(Eigentlich hat der High-Tech-Wowe-Zowee es noch einen Schritt weiter gebracht, aber es ist der gleiche Effekt wie die Butterfly-Schalter früherer Generationen.)

Wie auch immer, es funktioniert so.

Menschen entschieden, dass es eine Anweisung geben würde, nichts zu tun; genannt ein NOP

Also, Sie tippen die Buchstaben NOP in Ihrem Texteditor so ein

%Vor%

Sie speichern dann die Datei.

Dann bitten Sie den Assembler, diese Datei zu assemblieren

Wenn der Assembler NOP sieht, erstellt er die 90 (in hex) in der Objekt -Datei, die er für den Linker erstellt.

Der Linker verwendet die Objektdatei und erstellt eine ausführbare Datei

Der Loader platziert diese ausführbare Datei wo immer sie will. (Anmerkung: In früheren Zeiten von Mikrocomputern musste der Softwareschreiber entscheiden, wohin er die ausführbare Datei legte; das war ein Konflikt-Köder, wie Sie es nicht glauben würden.)

Wie auch immer, das NOP wurde 90 an irgendeiner Stelle in der EXE Datei und der Loader hat es in einem guten Bereich für Sie gespeichert, basierend auf 179 Regeln, über die Sie sich keine Sorgen mehr machen müssen.

Der Lader wird dann aus dem Bild und lässt Ihr Programm die CPU haben.

Die CPU holt Ihre erste Anweisung und beginnt zu gehorchen.

Wenn die CPU zu dem Byte kommt, das 90 enthält, wird es dasselbe sein, wie der Schmetterling von Generationen nachher schaltet.

Während der Strom keine langen Kabel auf dem Boden bewegt, wird er sehr ähnliche (und funktional äquivalente) Dinge innerhalb des ASICs machen.

Nun, mit allem, was geschrieben wurde (danke, wenn du noch liest), kannst du diese einseitige Erklärung verstehen, was ein Opcode eigentlich ist ...

Der Opcode ist eine paradigmatische Darstellung von Schmetterlingsschaltern alter Zeiten.

Nun zu Ihrer zweiten Frage, was der Maschinencode ist.

Maschinencode ist ein Haufen Opcodes

Wenn etwas unklar ist, fragen Sie im Kommentarbereich und ich werde versuchen, diese Antwort zu bearbeiten.

    
User.1 24.12.2014 00:22
quelle
5

Kurz gesagt:

"Assembly" ist das, was Sie durch einen "Assembler" führen. Ein Assembler ist ein Programm, das mehrere Decks von Lochkarten einliest und sie zu einem einzigen Programm zusammenfügt.

Oder zumindest war das früher so. Jetzt werden die Karten durch Disketten ersetzt. Aber die Daten auf den "Karten" sind eine "Maschinensprache", die die numerischen Werte für die Maschinenanweisungen sind.

Aber moderne Assembler sind SAPs - Symbolic Assembler Programs - so können Sie die numerischen Werte durch Symbole ersetzen - sagen wir "LOD" für eine Ladeanweisung, "R1" für Register 1 und "label5" für die Befehlsadresse 26734.

"Maschinensprache" ist die Art, wie individuelle Anweisungen (oder "Befehle", wenn Sie ein Brite sind) für die CPU dargestellt werden. Für einen symbolischen Assembler könnten Sie "LOD R1, LOOPCOUNT" haben, um die Anweisung darzustellen, den Wert des Wortes LOOPCOUNT in Register 1 zu laden. "LOD" ist übrigens der "Opcode" - die (symbolische Version von der numerische Wert, der dem Computer sagt, was als nächstes zu tun ist. (Und beachten Sie, dass jedes unterschiedliche Computerdesign eine andere Maschinensprache verwendet, möglicherweise mit anderen Symbolen für die Opcodes. Das meiste, was Sie im Internet finden, ist die eine oder andere Version der Intel Maschinensprache, aber Sie würden sagen, die IBM 370 zu radikal anders sein.)

"Bytecode" ist eine andere Art von "Maschinensprache", die auf einer "virtuellen Maschine" statt auf echter Hardware arbeitet. Der bekannteste Fall ist die Java Virtual Machine. "Bytecode" ist eine Notation, die der normalen "Maschinensprache" ähnelt, aber zu einem gewissen Grad idealisiert ist, da das Ausführen auf einer virtuellen Maschine es von einigen Realitäten einer realen Hardwareumgebung befreit.

    
Hot Licks 23.12.2014 23:43
quelle
5

Die Beziehung ist:

%Vor%

Die Assembler Anweisung ist menschlich lesbarer Code, wie zum Beispiel: mov rax, 0x2000004

Der Opcode ist der Teil des Maschinencodes, der sich auf die Anweisung bezieht, aber aus der Sicht der CPU (es ist also nicht nur MOV, sondern MOV, um sich zu registrieren). Zum Beispiel finden Sie hier für i386 MOV-Opcodes:

  • MOV reg32, immediate value wird als B8 + Registercode codiert (AX ist der erste, also ist es 0),
  • Auf den Opcode folgt der Operand 0x20000004, der in Little-Endian-Logik wie folgt codiert ist: 04 00 00 02

Byte-Code entspricht dem Maschinencode, aber für virtuelle Maschinen wie den JVM. Der Begriff Bytecode-Codes von den ersten Umgebungen, die diese Technologie verwendeten (p-Code aus der UCSD Pascal-Compiler), der ein Byte zum Codieren der virtuellen Anweisung verwendete. Hier finden Sie zum Beispiel die kleine P-Code-Sammlung und die neueren und umfangreicher JVM-Bytecode hier

Zu beachten: LLVM verwendet ein Zwischenformat (IF), das in einem komprimierten Formular auch bekannt als Bytecode. Dies ermöglicht eine neutrale Codeanalyse vor der Generierung von nativem Code durchzuführen.

    
Christophe 23.12.2014 23:43
quelle
2

Montage: Vom Menschen lesbare Instruktoren für den Assembler + Datenbytes + Operatoren

Maschinencode: Die tatsächlichen Bitfolgen, die die CPU versteht.

Es enthält:

  • der Opcode,
  • welche Register zu verwenden,
  • Offset vom PC-Register,
  • und ähnliche Informationen

Bytecode: Dies ist der Code, der von einem Interpreter gelesen wird (Die meisten Java-Implementierungen sind eigentlich ein Interpreter Dieser liest Bytecode und verwendet diesen Bytecode zur Auswahl eine Sequenz von Maschinencode, um die CPU tatsächlich ausführen zu lassen). Bytecode wird oft verwendet, um den gleichen Quellcode für mehrere verschiedene zu verwenden CPUs.

Opcode: Das erste (oder zwei) Byte des Maschinencodes. Es verhält sich wie ein Selektor um der CPU mitzuteilen, welche Mikrocodesequenz die CPU ausführen soll (so etwas wie eine switch-Anweisung in C)

Mikrocode: Die festverdrahteten Befehlssequenzen innerhalb der CPU, die verwendet werden führe den Maschinencode aus.
Es gibt viele Mikrocode-Sequenzen, mindestens eine Sequenz für jeden Opcode. Im Allgemeinen ist der Rest des Maschinencodes nur Parameter zu der Mikrocode-Sequenz, die durch den Opcode ausgewählt wird Jede Mikrocodesequenz enthält Anweisungen zu Öffnen / Schließen von Toren, Uhrendaten, Weiterleitung von Informationen zum / vom Akkumulator usw.

    
user3629249 24.12.2014 00:30
quelle