Probably just a historical question, if anyone knows.
From the Intel manual under
The one-byte NOP instruction is an alias mnemonic for the XCHG (E)AX, (E)AX instruction.
XCHG mnemonic is encoded as
90+reg encoding used as a second parameter in the exchange.
(E)AX has an encoding of
CX - 1,
DX - 2,
BX - 3 ect.) and from that
XCHG (E)AX,(E)AX has value of
I don't think that was the reason why
0x00 didn't become a
NOP, but from today's security perspective it would totally make sense to not have
0x00 as a
NOP. This is because today's architectures are mostly von Neumann architectures that happily mix data in between code. My guess is that
0x00 is the most common data value as it is used to initialize newly allocated memory and most default values for integers are also probably zero.
In code injection exploits you usually inject executable code as data and then trigger a bug to make the CPU execute this injected data.
If most data bytes are a
NOP when (mis)used as instruction, most of the data becomes a so-called nop slide.
A nop slide is very useful for an attacker as he might not be sure at which point exactly his injected code is in memory.
When everything before his injected code are
NOPs, he just needs to be lucky and hit somewhere into the nop slide which will then lead the CPU to execute the attacker’s injected code at the end.
That's why NOP slides can be used to defeat protections like ASLR, which loads memory at random positions.
I don't think all these security considerations where made at the point they designed the instruction set, but maybe they had a guess that its not a good idea to make the default value for most data also a
NOP when interpreted as instruction.