You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:01:02