2026-07-15
Stack Overflow: View Question
Tags: assembly, x86, nasm, interrupt, bootloader
Score: 5 | Views: 171
The asker is writing a minimal protected-mode bootloader in NASM and wants to install an IDT entry for the keyboard interrupt (IRQ1, vector 0x21 once PIC is remapped, or 0x09 by default). The IDT entry format is the sticking point: it's an 8-byte structure that splits the 32-bit handler address into two non-contiguous 16-bit halves — offset bits [15:0] at bytes 0-1, and offset bits [31:16] at bytes 6-7, with a segment selector, reserved byte, and type/attr byte sandwiched in between. The asker doesn't know how to compute those low and high halves from a label at assembly time.
Why this is more interesting than it looks: The naive C-brain approach would be to write helper code that shifts and masks at runtime. But an IDT entry is data — it wants a compile-time constant expression. NASM's expression evaluator can do this directly, and knowing the idiom unlocks a whole class of firmware/OS-dev tasks (GDT descriptors, ACPI tables, page directory entries with split fields).
The idiom in NASM:
kbd_handler:
; ... push regs, read port 0x60, EOI, iret ...
iret
idt_start:
; vector 0x21 (after PIC remap) — vectors 0..0x20 zeroed above
dw kbd_handler & 0xFFFF ; offset [15:0]
dw 0x08 ; kernel code selector
db 0 ; reserved
db 0x8E ; present, ring 0, 32-bit interrupt gate
dw (kbd_handler >> 16) & 0xFFFF ; offset [31:16]
idt_end:
idt_descriptor:
dw idt_end - idt_start - 1
dd idt_start
The & and >> operators evaluate at assembly time because kbd_handler resolves to an absolute address (given the [org 0x7c00] the bootloader uses).
Gotchas the asker will hit next:
[org 0x7c00], labels are already absolute — good. Without it, kbd_handler would be a file offset and the CPU would jump into the weeds.sti. Easy to forget after loading the IDTR with lidt [idt_descriptor].& 0xFFFF and >> 16 at build time is the whole trick.
