NKLegacy handles all 256 x86 interrupt vectors through assembly ISR stubs inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/pastaboy12345/NKLegacy/llms.txt
Use this file to discover all available pages before exploring further.
isr.asm that save CPU state, call a C dispatch function, then restore state and return with iret. Hardware IRQs additionally require the 8259 Programmable Interrupt Controller (PIC) to be remapped so that IRQ lines 0–15 do not collide with the reserved CPU exception vectors 0–31.
Assembly ISR Stubs
Source:ntoskrnl/arch/i386/isr.asm
Two NASM macros generate the per-vector entry points that the IDT points to. The macros normalize the stack layout so that a single common stub can handle both exception types.
ISR_NOERRCODE — exceptions without an error code
Used for exceptions where the CPU does not automatically push an error code (e.g., Division By Zero, Invalid Opcode, Machine Check). The macro pushes a dummy 0 so the stack layout matches registers_t exactly.
ISR_ERRCODE — exceptions that push an error code
Used for exceptions where the CPU already pushed a non-zero error code onto the stack (e.g., Double Fault, General Protection Fault, Page Fault). The macro only pushes the interrupt number — the CPU-pushed error code is already in place.
Exception vector table
| Vector | Name | Stub type |
|---|---|---|
| 0 | Division By Zero | ISR_NOERRCODE |
| 1 | Debug | ISR_NOERRCODE |
| 2 | Non-Maskable Interrupt | ISR_NOERRCODE |
| 3 | Breakpoint | ISR_NOERRCODE |
| 4 | Overflow | ISR_NOERRCODE |
| 5 | Bound Range Exceeded | ISR_NOERRCODE |
| 6 | Invalid Opcode | ISR_NOERRCODE |
| 7 | Device Not Available | ISR_NOERRCODE |
| 8 | Double Fault | ISR_ERRCODE |
| 9 | Coprocessor Segment Overrun | ISR_NOERRCODE |
| 10 | Invalid TSS | ISR_ERRCODE |
| 11 | Segment Not Present | ISR_ERRCODE |
| 12 | Stack-Segment Fault | ISR_ERRCODE |
| 13 | General Protection Fault | ISR_ERRCODE |
| 14 | Page Fault | ISR_ERRCODE |
| 15 | Reserved | ISR_NOERRCODE |
| 16 | x87 Floating-Point Exception | ISR_NOERRCODE |
| 17 | Alignment Check | ISR_ERRCODE |
| 18 | Machine Check | ISR_NOERRCODE |
| 19 | SIMD Floating-Point Exception | ISR_NOERRCODE |
| 20 | Virtualization Exception | ISR_NOERRCODE |
| 21 | Reserved | ISR_NOERRCODE |
| 22 | Reserved | ISR_NOERRCODE |
| 23 | Reserved | ISR_NOERRCODE |
| 24 | Reserved | ISR_NOERRCODE |
| 25 | Reserved | ISR_NOERRCODE |
| 26 | Reserved | ISR_NOERRCODE |
| 27 | Reserved | ISR_NOERRCODE |
| 28 | Reserved | ISR_NOERRCODE |
| 29 | Reserved | ISR_NOERRCODE |
| 30 | Security Exception | ISR_NOERRCODE |
| 31 | Reserved | ISR_NOERRCODE |
Common ISR stub
After pushing the interrupt number, all exception stubs jump toisr_common_stub, which saves the full CPU context, switches to the kernel data segment, then calls the C function isr_handler(registers_t *).
irq_common_stub that calls irq_handler instead. The C irq_handler sends EOI to the 8259 PIC automatically before dispatching the registered callback.
Hardware IRQ stubs (vectors 32–47)
8259 PIC — Programmable Interrupt Controller
Source:ntoskrnl/driver/pic/pic.h / ntoskrnl/driver/pic/pic.c
The IBM PC-compatible 8259 PIC originally maps IRQ0–IRQ7 to CPU vectors 0x00–0x07, which directly conflicts with the CPU’s own exception vectors. pic_init() reprograms both the master and slave PICs to remap these lines out of the exception range.
| IRQ lines | Default vectors | Remapped vectors |
|---|---|---|
| IRQ 0–7 (master PIC) | 0x00–0x07 | 0x20–0x27 (32–39) |
| IRQ 8–15 (slave PIC) | 0x70–0x77 | 0x28–0x2F (40–47) |
Port constants
pic_init
pic_send_eoi
irq >= 8, the slave PIC receives EOI first (via PIC2_CMD), then the master PIC receives EOI (via PIC1_CMD). For irq < 8, only the master PIC is signalled.
The IRQ line number (0–15), not the IDT vector number. For example, the keyboard is IRQ 1 (IDT vector 33).
pic_set_mask / pic_clear_mask
IRQ line (0–15). Lines 8–15 are automatically routed to the slave PIC’s mask register.
Port I/O Helpers
Source:ntoskrnl/arch/i386/io.h
All PIC and hardware driver code uses the following inline assembly wrappers for CPU I/O port access. Because these are static inline, they compile to a single instruction at each call site with zero function-call overhead.
io_wait() writes a dummy byte to I/O port 0x80 (a POST diagnostic port on PC hardware) to introduce a small pause between PIC command writes, which some older hardware requires.
Registering a Custom IRQ Handler
The steps below show the complete pattern for adding a new hardware IRQ handler. The keyboard driver (ntoskrnl/driver/keyboard/keyboard.c) follows exactly this pattern using IRQ line 1 (IDT vector 33).
Write a handler function
The handler must match the
isr_handler_t signature — it receives a pointer to the saved CPU state.Register the handler
Map the handler to the correct IDT vector. Hardware IRQ
n maps to IDT vector 32 + n.The C
irq_handler function in idt.c sends PIC EOI automatically for all vectors 32–47 before invoking the registered callback. Do not call pic_send_eoi from inside your handler — doing so would send EOI twice, which can cause spurious or missed interrupts on some hardware. Call pic_send_eoi only from contexts that bypass irq_handler entirely.