32位保护模式下Bootloader的IDT条目生成函数异常导致QEMU反复重启问题排查
makeidt Function for 32-bit Protected Mode IDT Let's break down the issues in your makeidt function step by step—your IDT entries are being constructed incorrectly, which is why your system keeps rebooting when you trigger the interrupt. First, let's recap the structure of a 32-bit interrupt gate descriptor (the type you need here):
A valid 8-byte interrupt gate looks like this:
| Bytes 0-1 | Bytes 2-3 | Byte 4 | Byte 5 | Bytes 6-7 |
|---|---|---|---|---|
| Offset 0-15 (low 16 bits of handler) | GDT/LDT Selector | 0 (reserved for 32-bit gates) | Attributes | Offset 16-31 (high 16 bits of handler) |
The attribute byte (byte 5) has these bits:
- Bit 7: P (Present) → 1 for valid gates
- Bits 6-5: DPL (Descriptor Privilege Level) → your
clvalue - Bit 4: S (Storage Segment) → 0 for system gates
- Bits 3-0: Type → 0xE for 32-bit interrupt gates
Issues in Your makeidt Code
Incorrect field ordering & storage
Your function returns the IDT entry aseax:edx, then you storeeaxat[idt]andedxat[idt+4]. This reverses the low and high 32-bit halves of the IDT entry. The low 32 bits (offset low + selector) should go to[idt], and the high 32 bits (attributes + offset high) to[idt+4].Broken selector construction
You're mishandling the GDT selector:- The selector is a 16-bit value:
(index << 3) | RPL. Since you're using a GDT segment, TI (bit 2) stays 0. - Your code mixes the selector with the handler's low offset and privilege level incorrectly, corrupting both fields.
- The selector is a 16-bit value:
Wrong attribute byte calculation
Your bit-shifting logic for the attribute byte is flawed. You end up with0xE7instead of the correct0xEE(for P=1, DPL=3, Type=0xE). Your shifts and ORs don't align the bits to their correct positions in the attribute byte.Misplaced handler offset bits
You're splitting the handler address (edx) into the wrong parts of the IDT entry, swapping low and high offset positions.
Fixed makeidt Function
Here's the corrected version that properly constructs a 32-bit interrupt gate:
makeidt: ; Inputs: ; cl = DPL (privilege level, 0-3) ; ax = GDT segment index (for code segment) ; edx = handler function pointer ; ch = Present flag (1 = valid, 0 = invalid) ; Output: ; eax = low 32 bits of IDT entry (offset low + selector) ; edx = high 32 bits of IDT entry (attributes + offset high) ; Build low 32 bits: [offset 0-15][selector] mov eax, edx and eax, 0x0000FFFF ; Isolate offset low 16 bits (bytes 0-1) mov ebx, eax ; Save offset low temporarily mov ax, [esp+12] ; Restore original GDT index (since we overwrote ax) shl ax, 3 ; Convert GDT index to selector base (TI=0) or al, cl ; Add RPL to selector (match DPL for simplicity) mov ebx, ebx ; Restore offset low to ebx shl ebx, 16 ; Move selector to upper 16 bits of ebx or eax, ebx ; eax now = [offset low][selector] (low 32 bits) ; Build high 32 bits: [0][attributes][offset high] mov edx, [esp+8] ; Restore original handler pointer shr edx, 16 ; Isolate offset high 16 bits (bytes 6-7) mov ebx, 0 mov bl, ch shl bl, 7 ; Set Present bit (bit7) mov bh, cl shr bh, 3 or bl, bh ; Set DPL bits (6-5) or bl, 0x0E ; Set S=0 and Type=0xE (interrupt gate) shl ebx, 16 ; Move attribute byte to correct position or edx, ebx ; edx now = [0][attributes][offset high] (high 32 bits) ret answerh dd 0 ; No longer needed with corrected logic
Corrected Call Flow
When storing the IDT entry, make sure you're putting the low 32 bits first, then the high 32 bits:
mov edx, intcode mov ax, 2 ; GDT index for your code segment mov ch, 1 ; Mark gate as present mov cl, 3 ; DPL=3 call makeidt mov [idt], eax ; Store low 32 bits of interrupt gate mov [idt+4], edx ; Store high 32 bits lidt [idtdesc] mov ebx, string sti int 0 cli
Additional Notes
- Double-check that your GDT index 2 points to a valid 32-bit code segment (with appropriate privileges matching your DPL=3 setting if needed).
- The
iretin yourintcodehandler is correct for 32-bit mode, but ensuremyfunctdoesn't corrupt any registers that need to be preserved (push/pop them if it does).
内容的提问来源于stack exchange,提问作者Sasidhar

