Search code examples
assemblyx86opcodemachine-codeno-op

Why was NOP assigned to 0x90 in x86 assembly?


Why was nop assigned to 0x90 on intel x86 assembly?

Intuitively I would expect that 0x00 would map to nop (which is also xchg eax, eax at intel x86) as it is the case for ARM A32 and some other architectures.


Solution

  • 0x00000000 is not actually NOP on ARM A32 though it behaves like one; it's actually andeq r0, r0, r0 whereas a real NOP is 0xe1a00000 (mov r0, r0). It's a rather bad idea to have the NUL byte be a NOP because that makes every empty memory region a free NOP slide, greatly increasing the risk for attacks. Modern architectures generally try to make all zeroes be a break instruction or similar to avoid this attack vector. For example, ARM A64 makes 0x00000000 a permanently undefined instruction udf 0.

    0x90 is actually just one instruction of the 0x90 + r opcode family which stands for xchg r32, eax. eax is register 0, so 0x90 stands for xchg eax, eax which is a NOP. In long mode, 0x90 is special cased not to zero out the high 32 bit of rax to keep its function as a single byte NOP.