Der Opcode (Operationscode) ist der Teil einer Maschineninstruktion, der die auszuführende Operation codiert — etwa Addieren, Laden oder Springen. Jede Instruktion besteht aus einem Opcode und optionalen Operanden (Registern, unmittelbaren Werten oder Speicheradressen). Der Opcode ist damit das Herzstück der Maschinensprache: die Bytes, die der Prozessor direkt decodiert und ausführt.
Wie ein Opcode aufgebaut ist
Die genaue Bitbreite und Aufteilung des Opcodes hängt vom Instruktionssatz (ISA) ab:
- x86: Opcodes sind 1 bis 3 Bytes lang und werden durch Präfixe (z.B. 0x66 für 16-Bit-Operanden, REX für 64-Bit) variiert. Beispiele:
0x90= NOP,0xE9= Sprung mit 32-Bit-Relativoffset,0xB8= MOV in das Register RAX. - ARM (AArch32): Instruktionen sind immer 32 Bit breit; die oberen 4 Bits codieren eine bedingte Ausführung (Condition Code), der Opcode steckt in einem festen Feld.
- RISC-V: Basisinstruktionen sind ebenfalls 32 Bit breit; der Opcode liegt in den unteren 7 Bits, weitere Funktionsfelder (Funct3/Funct7) verfeinern die Operation. Eine kompakte 16-Bit-Erweiterung (RVC) reduziert den Speicherbedarf.
Vom Opcode zum Assembler
Der Assembler übersetzt Mnemonics wie MOV oder ADD in die entsprechenden Opcodes; ein Disassembler arbeitet umgekehrt. Während CISC-Prozessoren wie x86 sehr viele verschiedene Opcode-Formate besitzen, halten RISC-Architekturen die Codierung regelmäßig und einheitlich. Aufwendige CISC-Befehle werden intern häufig in mehrere Mikrooperationen zerlegt (Mikrocode).
Wo Opcodes entstehen
Der Compiler erzeugt im Rahmen der Codegenerierung die konkreten Instruktionen samt Opcodes. Auch virtuelle Maschinen wie die JVM verwenden dieses Prinzip: Ihr Bytecode ist ein abstrakter Befehlssatz, dessen „Opcodes“ der Interpreter beziehungsweise JIT-Compiler zur Laufzeit verarbeitet. Die Reihenfolge, in der mehrbyte-Werte im Speicher abgelegt werden, bestimmt dabei die Endianness des Systems.