32位保护模式下IDT配置异常:触发中断后CPU跳转至未知地址
32位保护模式下IDT配置问题:触发#0中断后跳转到未知地址
我正在尝试配置IDT(中断描述符表),当前处于32位保护模式,使用QEMU进行调试。目前仅创建了#0号条目(除零错误),尝试通过int 0x0触发该中断,但触发后CPU跳转到了未知地址。
相关代码
main.s
_start: lidt [idt_descriptor] sti int 0x0 hlt
中断描述符表定义
idt_descriptor: dw idt_end - idt_start - 1 dd idt_start idt_start: dw isr_0 dw 1 ; 代码段选择子为1 db 0 db 10001111b dw 0 idt_end:
#0号中断服务程序(ISR)
isr_0: mov eax, string call kprint iret string: db "Inside ISR", 0
问题原因及修复方案
- IDT条目地址不完整:32位中断门描述符需要把ISR的32位地址拆分为低16位和高16位分别存储,你当前只设置了低16位(
dw isr_0),最后一个dw 0字段没有填入地址的高16位,导致CPU计算出错误的跳转地址。 - 代码段选择子错误:保护模式下的段选择子格式是「段描述符索引×8 + 特权级」,你用的
1不符合这个规则。如果GDT中第一个有效代码段的索引是1,特权级为0(内核级),正确的选择子应该是0x08。
修复后的IDT条目
idt_start: dw isr_0 & 0xffff ; ISR地址低16位 dw 0x08 ; 内核代码段选择子(匹配GDT中的代码段描述符) db 0 ; 保留位,固定为0 db 10001111b ; P=1(有效)、DPL=0(内核特权级)、32位中断门 dw (isr_0 >> 16) & 0xffff; ISR地址高16位 idt_end:
额外注意事项
- 中断处理程序需要先保存通用寄存器,避免破坏上下文,执行完后再恢复:
isr_0: pusha ; 保存所有通用寄存器 mov eax, string call kprint popa ; 恢复寄存器 iret string: db "Inside ISR", 0 - 确认GDT已正确加载,代码段描述符的基址和限长覆盖了ISR代码所在的内存区域。
内容的提问来源于stack exchange,提问作者OutsideApe3019
相关产品推荐
相关产品推荐

