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

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

Ich habe die meisten SO-Fragen zu Baugruppen- und Maschinencode gelesen, z. B.Die, aber sie sind zu hoch und zeigen keine Beispiele für den tatsächlichen Assembly-Code, der in Maschinencode umgewandelt wird. Daher verstehe ich immer noch nicht, wie es auf einer tieferen Ebene funktioniert.

Die ideale Antwort auf diese Frage zeigt ein bestimmtes Beispiel für einen Assembly-Code, z. B. den folgenden Ausschnitt, und wie jede Assembly-Anweisung auf Maschinencode, Bytecode und / oder Opcode abgebildet wird. Eine Antwort wie diese wäre für zukünftige Leute, die die Montage lernen, sehr hilfreich, da ich in den letzten Tagen des Grabens noch keine klare Zusammenfassung gefunden habe.

Die wichtigsten Dinge, die ich suche, sind:

ein Ausschnitt aus dem Assembler-Code ein Ausschnitt aus dem Maschinencode eine Zuordnung zwischen dem Snippet der Baugruppe und dem Maschinencode (wie macht man das Mapping oder zumindest einige allgemeine Beispiele und wie macht mankenn wie das geht, wo sind all diese Informationen im Web) wie man den Maschinencode interpretiert (wie sind Opcodes irgendwie verwandt, und wo sind alle Informationen im Web darüber, was all diese Zahlenbedeute)

Hinweis: Ich habe keine Informatikkenntnisse und bin in den letzten Jahren nur langsam auf ein niedrigeres Niveau gekommen. Jetzt möchte ich Baugruppen- und Maschinencode verstehen.

Relation zwischen Baugruppe und Maschinencode

ein gegenwärtiges Verständnis ist, dass ein "Assembler" (wie NASM) Assembly-Code nimmt und daraus Maschinencode erstell

Also, wenn Sie eine Assembly wie diese kompilierenexample.asm:

global main
section .text

main:
  call write

write:
  mov rax, 0x2000004
  mov rdi, 1
  mov rsi, message
  mov rdx, length
  syscall

section .data
message: db 'Hello, world!', 0xa
length: equ $ - message

(kompiliere es mitnasm -f macho64 -o example.o example.asm). Es gibt dieseexample.o Objektdatei:

cffa edfe 0700 0001 0300 0000 0100 0000
0200 0000 0001 0000 0000 0000 0000 0000
1900 0000 e800 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
2e00 0000 0000 0000 2001 0000 0000 0000
2e00 0000 0000 0000 0700 0000 0700 0000
0200 0000 0000 0000 5f5f 7465 7874 0000
0000 0000 0000 0000 5f5f 5445 5854 0000
0000 0000 0000 0000 0000 0000 0000 0000
2000 0000 0000 0000 2001 0000 0000 0000
5001 0000 0100 0000 0005 0080 0000 0000
0000 0000 0000 0000 5f5f 6461 7461 0000
0000 0000 0000 0000 5f5f 4441 5441 0000
0000 0000 0000 0000 2000 0000 0000 0000
0e00 0000 0000 0000 4001 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0200 0000 1800 0000
5801 0000 0400 0000 9801 0000 1c00 0000
e800 0000 00b8 0400 0002 bf01 0000 0048
be00 0000 0000 0000 00ba 0e00 0000 0f05
4865 6c6c 6f2c 2077 6f72 6c64 210a 0000
1100 0000 0100 000e 0700 0000 0e01 0000
0500 0000 0000 0000 0d00 0000 0e02 0000
2000 0000 0000 0000 1500 0000 0200 0000
0e00 0000 0000 0000 0100 0000 0f01 0000
0000 0000 0000 0000 0073 7461 7274 0077
7269 7465 006d 6573 7361 6765 006c 656e
6774 6800 

(das ist der gesamte Inhalt vonexample.o). Wenn Sie dann "verlinken", dass mitld -o example example.o, es gibt Ihnen mehr Maschinencode:

cffa edfe 0700 0001 0300 0080 0200 0000
0d00 0000 7803 0000 8500 0000 0000 0000
1900 0000 4800 0000 5f5f 5041 4745 5a45
524f 0000 0000 0000 0000 0000 0000 0000
0010 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 1900 0000 9800 0000
5f5f 5445 5854 0000 0000 0000 0000 0000
0010 0000 0000 0000 0010 0000 0000 0000
... 523 lines of this

Aber wie ist es von der Montageanleitung zu diesen Nummern gelaufen? Gibt es eine Art Standardreferenz, in der alle diese Nummern aufgeführt sind und was sie bedeuten, für welche Architektur Sie sich auch befinden (ich verwende x86-64 über NASM unter OSX) und wie jeder Satz von Nummern den einzelnen Montageanweisungen zugeordnet wird ?

Ich verstehe, dass der Maschinencode für jede Maschine unterschiedlich ist und es Dutzende, wenn nicht Hunderte verschiedener Maschinentypen gibt. Daher bin ich derzeit nicht auf der Suche nach der Umwandlung von Baugruppen in einzelne (das wäre kompliziert). Ich interessiere mich nur für ein Beispiel, das zeigt, wie die Transformation funktioniert, und jede Architektur kann als Beispiel dienen. Von diesem Punkt an konnte ich die spezifische Architektur, an der ich interessiert bin, untersuchen und das Mapping finden.

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

So wird nach meiner bisherigen Lektüre die Assembly wie oben gezeigt in Maschinencode umgewandelt.

Aber jetzt werde ich verwirrt. Ich sehe Leute, die über Bytecode sprechen, wie zBin dieser SO Antwort, zeige so etwas:

void myfunc(int a) {
  printf("%s", a);
}

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

OP Params OpName     Description
13 82 6a  PushString 82 means string, 6a is the address of "%s"
                     So this function pushes a pointer to "%s" on the stack.
13 83 00  PushInt    83 means integer, 00 means the one on the top of the stack.
                     So this function gets the integer at the top of the stack,
                     And pushes it on the stack again
17 13 88 Call        1388 is printf, so this calls the printf function
03 02    Pop         This pops the two things we pushed back off the stack
02       Return      This returns to the calling code.

Also dann werde ich verwirrt. Wenn ich ein bisschen grabe, kann ich nicht sagen, ob jede dieser zweistelligen Hex-Zahlen wie13 82 6a werden jeweils einzeln als "Opcodes" bezeichnet, und der gesamte Satz von ihnen wird als Sammelbegriff "Bytecode" bezeichnet. Außerdem kann ich keine Tabelle finden, in der alle diese zweistelligen Hexadezimalzahlen und ihre Beziehung zum Maschinencode oder zur Baugruppe aufgeführt sind.

Zusammenfassend freue ich mich sehr auf ein Beispiel, in dem gezeigt wird, wie Montageanweisungen Maschinencode zugeordnet werden und in welchem Verhältnis dieser zu Bytecode und / oder Opcode steht. (Ich suche nicht, wie ein Compiler das macht, nur wie das allgemeine Mapping funktioniert). Ich denke, das würde es nicht nur mir selbst, sondern vielen Leuten auf der Straße klar machen, die mehr über das Bare Metal erfahren möchten.

Ein anderer Grund, warum dies wertvoll zu wissen ist, ist, dass man verstehen kann, wie der LLVM-Compiler Maschinencode generiert. 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 Codegenerierung implementiert hat.

Aktualisiere

Aktualisierung von @ HansPassant's Kommentar. Es ist mir eigentlich egal, was die tatsächlichen Unterschiede zwischen den Wörtern sind, sorry, wenn das nicht klar war. Ich möchte nur Folgendes wissen: Wie ordnet sich die Baugruppe dem Maschinencode zu (und wo beginnt die Suche nach den Referenzen, die diese Informationen im Web enthalten), und werden Opcodes oder Bytecodes an einer beliebigen Stelle in diesem Prozess verwendet? Und wenn ja wie?

Antworten auf die Frage(12)

Ihre Antwort auf die Frage