Why the x86 instruction is called ud2 and not just ud

Translated by a model; the original is in Russian.

· Technology
Microsoft's Raymond Chen unpacks where the “two” in the name of the x86 instruction that's guaranteed to raise an invalid-opcode exception came from.

cover.svg

While picking apart a crash dump or studying compiler output, you may run into the ud2 instruction. Raymond Chen, writing on his blog The Old New Thing, explains that this is an architecturally undefined instruction that is guaranteed to raise an “invalid opcode” exception. Compilers insert it to mark unreachable code: for instance, if a function marked [[noreturn]] does return control after all, the program will crash rather than tumble into the execution of random bytes.

That leaves the question posed in the title: why ud2 and not simply ud? Did ud0 and ud1 ever exist, and what did they do to fall out of favor?

How it all began

At first x86 had no standard “invalid” instruction at all. Anyone who needed to reliably provoke an exception had to hunt for a suitable byte sequence. Someone discovered that 0F FF had this property; someone else found that 0F B9 behaved the same way. Both sequences decoded internally as though they took two operands, but the operands went unused: the exception was raised sooner. So two camps of adherents formed—without any rivalry, since both tricks worked.

Then Intel shipped a new processor, and some programs stopped running. After much investigation the cause came to light: the code relied on 0F FF being an invalid instruction, and on the new chip its behavior had changed. The same story played out with 0F B9. Chen sees here a textbook illustration of Hyrum's Law: with a sufficient number of users, someone is bound to start relying on any observable quirk of behavior.

The arrival of ud2

Having realized that developers needed a reliable way to raise an exception, Intel made it official by adding a permanently invalid instruction, ud2. In hindsight the 0F FF variant was named ud0, the 0F B9 variant ud1, and ud2 remained the recommended choice.

The advantage of ud2 is that it's a two-byte instruction with no operands—there's no fussing with “random” decoded but unused source and destination. And that matters more than it seems: even if the processor doesn't use the extra operand bytes, it decodes them anyway. If that decoding runs into a missing page of memory, you get an access fault rather than an invalid-opcode exception. And some older processors raised the exception immediately after 0F FF without checking the rest—so, depending on where the instruction sat, the result could differ.

The takeaway is simple: ud2 behaves predictably and is guaranteed by the architecture—that's the one to lean on.


Source: Hacker News

Comments

Sign in, to comment.

  • No comments yet.