Por qué la instrucción indefinida de x86 se llama ud2 y no ud
Es la instrucción que los compiladores meten para que un programa se caiga en lugar de seguir ejecutando. Detrás del 2 hay dos variantes anteriores que nunca llegaron a nada.

ud2 es una instrucción indefinida a nivel arquitectónico en x86: lo único que garantiza es lanzar una excepción de opcode inválido. Los compiladores la generan para marcar código inalcanzable, por ejemplo después de una función marcada [[noreturn]] que por lo que sea retorna, de forma que el programa se caiga en vez de ejecutar lo que venga después. El detalle curioso es el nombre. Existe un ud0 y un ud1, y ninguno se usa.
De dos secuencias al instruction oficial
Al principio no había ninguna instrucción indefinida en la arquitectura. Quien quería forzar una excepción de opcode inválido tenía que buscar una secuencia de bytes que la provocara de forma fiable. Alguien dio con 0F FF. El decodificador la interpretaba internamente como si llevara dos parámetros, un registro destino y un registro o memoria fuente, aunque no se usaran: la excepción salta antes de que nada de eso importe. Por otra parte, otro encontró que 0F B9 hacía lo mismo. Dos bandos, el de 0F FF y el de 0F B9, sin demasiada pelea porque ambos funcionaban.
Luego Intel preparó su siguiente procesador y algo cambió. Puede que 0F FF dejara de lanzar la excepción, o que la empresa la reutilizara para una instrucción nueva, o que quedara indefinida pero ejecutando algo en lugar de excepcionar. El caso es que al correr software encima aparecieron programas que dejaban de funcionar, y tras la investigación correspondiente resultó que estaban apoyados en que 0F FF fuera un opcode inválido. Es la ley de Hyrum en estado puro: con suficientes usuarios, cualquier comportamiento observable acaba teniendo a alguien dependiendo de él.
Con 0F B9 pasó algo parecido. Ante la evidencia de que la gente quería una forma fiable de disparar la excepción, Intel la hizo oficial: creó una instrucción permanentemente inválida y soportada, y la llamó ud2. El nombre cuadra porque a la variante 0F FF se la rebautizó retroactivamente como ud0 y a la 0F B9 como ud1.
Por qué ud2 y no ud0 o ud1
La ventaja de ud2 es que ocupa dos bytes y no lleva parámetros, así que no hay que lidiar con operandos que se decodifican pero no se usan. Y eso importa más de lo que parece. Aunque el procesador no use esos operandos, los decodifica: si esa decodificación cruza a una página no presente, no se obtiene una excepción de opcode inválido sino un access violation. Peor aún, algunos procesadores antiguos lanzaban la excepción en cuanto decodificaban 0F FF, sin comprobar el resto, de modo que si la instrucción caía al final de una página el resultado podía ser una excepción de opcode inválido o un fallo de acceso, según el caso.
ud2 se comporta igual siempre y está garantizada por la arquitectura. Para quien escribe ensamblador en línea, monta un JIT o parchea código en caliente, la conclusión es sencilla: usar ud2 es lo portable, y confiar en 0F FF es apostar por un comportamiento que nunca se documentó y que ya falló una vez.

