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

如何避免ISR(中断服务例程)陷入循环?QEMU自制OS开发问题

问题:除零中断触发后ISR陷入无限循环

我正在编写一款运行在QEMU上的操作系统,自定义了ISR。用__asm__ ("int $0");手动触发中断时能正常处理,但执行除零代码:

int a = 0;
int b = 5;
int c = b/a;

会导致中断处理程序反复调用,陷入循环。试过清除标志位、屏蔽中断都没用。

相关代码

C++中断处理函数

void ISR::__interrupt_handler(InterruptRegister *reg) {
    disp.print_screen("Recieved interrupt: ");
    char s[3];
    int_to_string(reg->int_no, s);
    disp.print_screen(s);
// 省略其他代码
}

汇编中断处理代码

[extern interrupt_handler]

; Common Interrupt Service Routine
isr_common:
    cli ; Disable interrupts
    ; Save the registers
    pusha
    mov ax, ds ; Save the data segment
    push eax; Save the data segment
    mov ax, 0x10 ; Set the data segment to 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Call the interrupt handler
    push esp ; Push the stack pointer
    call interrupt_handler
    pop eax ; Pop the stack pointer

    ; Restore the registers
    pop eax
    mov eax, 1
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    popa

    ;Clean the pushed error code
    add esp, 8

    ;sti ; Enable interrupts
    iret ; Pops CS, EIP, EFLAGS, SS, ESP

isr0:
    push byte 0
    push byte 0
    jmp isr_common

问题原因与解决办法

1. 除零中断循环的核心原因

除零异常属于故障类异常,处理器触发这类异常时,会把EIP指向导致异常的那条指令。当你用iret返回时,处理器会重新执行这条指令,自然再次触发除零异常,陷入死循环。

而手动用int $0触发的是软件中断(陷阱类异常),EIP会指向中断指令的下一条,返回后不会重复执行触发指令,所以能正常退出。

2. 汇编代码中的致命错误

看你的寄存器恢复段:

pop eax
mov eax, 1
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

你把之前保存的ds值从栈里弹出后,直接把eax改成了1,用这个错误的段值恢复段寄存器!这会导致后续内存访问错误,甚至间接加重中断循环问题。正确写法应该是:

pop eax ; 弹出之前保存的ds值
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

3. 打破循环的关键操作

要终止除零中断的循环,必须在中断处理函数中修改EIP寄存器,让处理器跳过导致除零的指令:

  • 确保InterruptRegister结构体包含eip字段(对应栈中保存的EIP值)。
  • 当检测到中断号为0(除零)时,把reg->eip增加对应指令的长度(x86平台上除法指令长度通常是2-3字节,需根据实际机器码确定)。这样iret返回后,处理器会执行下一条指令,不会重复触发异常。

4. 栈平衡修正

你的isr0中先push byte 0(占位错误码)再push byte 0(中断号),栈中此时只有两个字节数据。但你用了add esp, 8来清理,这会破坏栈平衡,导致iret时弹出错误的EIP/FLAGS值,引发更严重问题。应该改成add esp, 4。

5. 其他细节

  • 不需要在isr_common开头执行cli,处理器触发异常时会自动清除IF标志位(屏蔽可屏蔽中断),除非你在处理过程中需要手动开中断。

内容的提问来源于stack exchange,提问作者Jjkivai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:35:12