Die Maschinensprache (auch Maschinencode) ist die einzige Sprache, die ein Prozessor direkt ausführen kann: Programme bestehen hier aus langen Folgen von Binärbefehlen — Bitmustern aus Nullen und Einsen. Jede höhere Programmiersprache muss letztlich in diesen Befehlscode übersetzt werden, bevor die CPU ihn abarbeitet.

Vom Assembler zum Binärcode

Für Menschen ist Maschinensprache kaum lesbar. Deshalb arbeitet man meist mit dem Assembler, der jeden Maschinenbefehl als einprägsame Abkürzung (Mnemonik) darstellt — zum Beispiel MOV, ADD oder JMP. Der Assembler übersetzt diese Mnemoniken 1:1 in die binären Opcodes des Prozessors. Was der Assembler als ADD EAX, EBX anzeigt, ist im Speicher ein Bitmuster, das die CPU als „Addiere den Inhalt von Register EBX zu Register EAX“ dekodiert. Werkzeuge wie objdump -d oder ein Hexeditor machen diesen Binärcode sichtbar.

Aufbau eines Maschinenbefehls

Ein Maschinenbefehl besteht im Kern aus zwei Teilen:

  • Opcode: der Befehlscode — welche Operation ausgeführt wird (Addition, Sprung, Vergleich und so weiter).
  • Operanden: die beteiligten Werte — Register, Speicheradressen oder unmittelbare Konstanten (Immediates).

Die genaue Kodierung hängt von der Instruction Set Architecture (ISA) ab, dem Vertrag zwischen Software und Hardware. x86-Prozessoren verwenden Befehle variabler Länge von 1 bis 15 Byte, ARM- und RISC-V-Prozessoren meist feste 32-Bit-Befehle (plus kompakte Varianten). Was auf einer Architektur läuft, läuft auf keiner anderen — Maschinensprache ist nicht portabel.

Wie die CPU Maschinensprache ausführt

Die Ausführung folgt dem Fetch-Decode-Execute-Zyklus: Die CPU holt den nächsten Befehl aus dem Speicher, die Steuerung dekodiert den Opcode, und die Rechenwerke (ALU, Register) führen die Operation aus. Weil die Hardware genau dafür gebaut ist, ist Maschinensprache die schnellste Ausführungsform — aber auch die aufwendigste, sie von Hand zu schreiben.

Abgrenzung zu anderen Ausführungsformen

Ein Compiler übersetzt Quellcode über die Zwischendarstellung — etwa den Drei-Adress-Code — und die Codegenerierung bis zur Maschinensprache, meist über den Umweg des Assemblers. Dabei bildet die Registerallokation die unbegrenzten Zwischenwerte auf die wenigen echten CPU-Register ab. Auch Konstanten, die der Compiler durch Konstantenfaltung vorberechnet hat, erscheinen als Immediate-Operanden im Maschinencode.

Anders arbeiten Interpreter: Sie führen Quellcode oder Bytecode direkt aus, ohne Maschinensprache zu erzeugen. Bytecode ist ausdrücklich keine Maschinensprache — er wird von einer virtuellen Maschine abgearbeitet und erst bei Bedarf (JIT) in nativen Maschinencode übersetzt.

Kompilierte Sprachen wie C oder Rust erzeugen am Ende eine ausführbare Datei, deren Inhalt Maschinensprache ist; der Linker hat die einzelnen Objektdateien zuvor zusammengefügt.