{"article":{"slug":"why-do-we-need-ud2-when-int-6-is-right-there","title":"Why do we need ud2 when int 6 is right there?","subtitle":null,"summary":"Raymond Chen explains why x86 has a dedicated ud2 undefined instruction rather than programs issuing int 6: the invalid-opcode exception is a fault that reports the faulting instruction's address, while a software interrupt is a trap reporting the next instruction, and operating systems deny user mode permission to issue int 6 anyway.","content_type":"blog_post","language":"en","canonical_url":"https://devblogs.microsoft.com/oldnewthing/20261019-00/?p=112781","author":{"name":"Raymond Chen","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"The Old New Thing","url":"https://devblogs.microsoft.com/oldnewthing/","listing_slug":null,"listing":null},"topics":[{"name":"x86","slug":"x86","url":"https://listedarticles.com/topics/x86"},{"name":"Operating Systems","slug":"operating-systems","url":"https://listedarticles.com/topics/operating-systems"},{"name":"Low-Level Programming","slug":"low-level-programming","url":"https://listedarticles.com/topics/low-level-programming"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":491,"reading_minutes":2,"published_at":"2026-10-19T14:00:00.000Z","added_at":"2026-10-20T23:08:43.032Z","updated_at":"2026-10-20T23:08:43.032Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/why-do-we-need-ud2-when-int-6-is-right-there","markdown_url":"https://listedarticles.com/articles/why-do-we-need-ud2-when-int-6-is-right-there.md","example":false,"citation":"Raymond Chen, The Old New Thing. \"Why do we need ud2 when int 6 is right there?.\" 19 Oct 2026. https://devblogs.microsoft.com/oldnewthing/20261019-00/?p=112781 (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://devblogs.microsoft.com/oldnewthing/20261019-00/?p=112781"},"body_markdown":"# Why do we need ud2 when int 6 is right there?\n\nRaymond Chen | The Old New Thing | October 19, 2026\n\nSome time ago, I mentioned that  [the `ud2` instruction was created to be an architecturally undefined instruction](https://devblogs.microsoft.com/oldnewthing/20260910-00/?p=112689 \"Why is the x86 undefined instruction called ud2? Why 2?\"). But why not just use an `int 6` instruction? It’s a two-byte instruction, just like `ud2`, and interrupt vector 6 is the invalid opcode vector, so a program could just invoke it manually and get whatever behavior the operating system assigns to an attempt to execute an invalid opcode.\n\nWell, not exactly.\n\nArchitecturally, the invalid opcode is a *fault*, which means that the address of the faulting instruction is reported to the exception handler. On the other hand, the `int 6` is a *trap*, which means that the address of the instruction *after* the `int 6` is reported to the handler.\n\nThis distinction between faults and traps reflects how they are used. A fault represents an error that the kernel could attempt to repair and retry. For example, a page fault could be repaired by paging the memory in. An access violation could be repaired by changing the page protections. A trap reports an operation that has already occurred and gives you a chance to do some special work in response to it before resuming execution. In the case of a software interrupt, the handler wants to process whatever the interrupt means, and then resume execution with the next instruction.\n\nNow, some faults are unlikely to be repaired, but reporting them as faults means that you have to take extra steps if you want to execute past them. If you just ignore the fault, the instruction restarts and faults again.\n\nIf you manually raise the `int 6` interrupt to simulate a #UD undefined instruction fault, the handler will think it’s dealing with a CPU-generated undefined instruction fault, so it expects the instruction pointer in the fault frame to point to the undefined instruction. But since `int` puts the address of the *next* instruction into the fault frame, the fault handler will look at the instruction and get confused as to why the invalid instruction fault was raised. “It says here that the faulting instruction is a `xor eax, eax`. That’s a perfectly legitimate instruction. Why did it fault?”\n\nOne case for inspecting the faulting instruction is to emulate missing instructions on older processors.\n\nFurthermore, in protected mode, you need to have permission to issue an `int 6`. The interrupt descriptor table describes what to do for each interrupt, as well as what CPU privilege level is permitted to invoke it explicitly. And to avoid exactly these types of problems where a user-mode program issues an `int 6` and confuses the #UD handler, all operating systems deny `int 6` privileges to user mode.\n\nSo even if you try to fake a #UD via an explicit `int 6`, it doesn’t work. To get the #UD undefined instruction fault, you have to issue an actual undefined instruction.\n","body_html":"<h1 id=\"why-do-we-need-ud2-when-int-6-is-right-there\">Why do we need ud2 when int 6 is right there?</h1>\n<p>Raymond Chen | The Old New Thing | October 19, 2026</p>\n<p>Some time ago, I mentioned that  <a href=\"https://devblogs.microsoft.com/oldnewthing/20260910-00/?p=112689\" title=\"Why is the x86 undefined instruction called ud2? Why 2?\" rel=\"nofollow ugc noopener\">the <code>ud2</code> instruction was created to be an architecturally undefined instruction</a>. But why not just use an <code>int 6</code> instruction? It’s a two-byte instruction, just like <code>ud2</code>, and interrupt vector 6 is the invalid opcode vector, so a program could just invoke it manually and get whatever behavior the operating system assigns to an attempt to execute an invalid opcode.</p>\n<p>Well, not exactly.</p>\n<p>Architecturally, the invalid opcode is a <em>fault</em>, which means that the address of the faulting instruction is reported to the exception handler. On the other hand, the <code>int 6</code> is a <em>trap</em>, which means that the address of the instruction <em>after</em> the <code>int 6</code> is reported to the handler.</p>\n<p>This distinction between faults and traps reflects how they are used. A fault represents an error that the kernel could attempt to repair and retry. For example, a page fault could be repaired by paging the memory in. An access violation could be repaired by changing the page protections. A trap reports an operation that has already occurred and gives you a chance to do some special work in response to it before resuming execution. In the case of a software interrupt, the handler wants to process whatever the interrupt means, and then resume execution with the next instruction.</p>\n<p>Now, some faults are unlikely to be repaired, but reporting them as faults means that you have to take extra steps if you want to execute past them. If you just ignore the fault, the instruction restarts and faults again.</p>\n<p>If you manually raise the <code>int 6</code> interrupt to simulate a #UD undefined instruction fault, the handler will think it’s dealing with a CPU-generated undefined instruction fault, so it expects the instruction pointer in the fault frame to point to the undefined instruction. But since <code>int</code> puts the address of the <em>next</em> instruction into the fault frame, the fault handler will look at the instruction and get confused as to why the invalid instruction fault was raised. “It says here that the faulting instruction is a <code>xor eax, eax</code>. That’s a perfectly legitimate instruction. Why did it fault?”</p>\n<p>One case for inspecting the faulting instruction is to emulate missing instructions on older processors.</p>\n<p>Furthermore, in protected mode, you need to have permission to issue an <code>int 6</code>. The interrupt descriptor table describes what to do for each interrupt, as well as what CPU privilege level is permitted to invoke it explicitly. And to avoid exactly these types of problems where a user-mode program issues an <code>int 6</code> and confuses the #UD handler, all operating systems deny <code>int 6</code> privileges to user mode.</p>\n<p>So even if you try to fake a #UD via an explicit <code>int 6</code>, it doesn’t work. To get the #UD undefined instruction fault, you have to issue an actual undefined instruction.</p>","headings":[{"level":1,"text":"Why do we need ud2 when int 6 is right there?","id":"why-do-we-need-ud2-when-int-6-is-right-there"}]}}