The x86 has a quite complex opcode-parser with multiple states. First it looks for the legacy prefixes like REP
, LOCK
, address- and operand-override-prefixes and probably just sets internal flags. Then it looks for mandatory and rex prefixes and probably sets other internal flags. After this, the parser expects the actual instruction...or a 0x0f-prefix for more instructions. Even this instruction-byte may contain other data, e.g.registers could be encoded there, so depending on the highest three bits (0bxxx.....) of the instruction, the parser has to decide, whether the instruction encodes an register (e.g. 0b000xxx110: push xxx
, where xxx is es
, cs
, ss
or ds
) or not. depending on the instruction, the parser then looks for an ModR/M-field and evaluates this. When this ModR/M-field indicates, there is an SIB-field to, then, guess what?, it evaluates the SIB-field. There could be, depending on the instruction, ModR/M-field or SIB-field, an immediate offset and/or an immediate value at the end.
I do not know, how the processor actually stores this stuff. Maybe there is an register for the instruction, a flag-register, a register, where the destination-register-number is stored, a register for the immediate value and some kind of representation of used addresses.
Anyway, there is not this instruction-register you may heard for RISC-processors and even if, just because the length of general registers is 64bit, other registers does not have to be this size. E.g. the Streaming SIMD Extensions provide xmm-registers, that are 128bit in size. They could contain a full 15-byte valid x86-instruction.
You can find the structure of this parser on page 5 here.