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

启用sti指令在真实硬件触发Invalid Opcode中断,QEMU中运行正常

真实硬件启用中断后触发无效操作码中断的问题

我基于Carlos Fenollosa的旧教程开发操作系统,在设置IDT(中断描述符表)和处理IRQ(中断请求)时遇到问题:QEMU模拟器中运行一切正常,但在真实硬件上,启用中断后系统立即挂起——isr_handler会收到一次无效操作码中断,之后系统停机。

我参考过类似问题的解决方案,原问题作者通过添加缺失的处理程序和中断结束(EOI)例程解决了问题,我已经按照教程实现了相关代码,但问题仍未解决,恳请解释QEMU与真实硬件的行为差异并提供修复方案。

已实现的C代码

// Sets first 32 IDT gates
void isr_install() {
    set_idt_gate(0,  (u32) isr0);
    set_idt_gate(1,  (u32) isr1);
    set_idt_gate(2,  (u32) isr2);
    set_idt_gate(3,  (u32) isr3);
    set_idt_gate(4,  (u32) isr4);
    set_idt_gate(5,  (u32) isr5);
    set_idt_gate(6,  (u32) isr6);
    set_idt_gate(7,  (u32) isr7);
    set_idt_gate(8,  (u32) isr8);
    set_idt_gate(9,  (u32) isr9);
    set_idt_gate(10, (u32) isr10);
    set_idt_gate(11, (u32) isr11);
    set_idt_gate(12, (u32) isr12);
    set_idt_gate(13, (u32) isr13);
    set_idt_gate(14, (u32) isr14);
    set_idt_gate(15, (u32) isr15);
    set_idt_gate(16, (u32) isr16);
    set_idt_gate(17, (u32) isr17);
    set_idt_gate(18, (u32) isr18);
    set_idt_gate(19, (u32) isr19);
    set_idt_gate(20, (u32) isr20);
    set_idt_gate(21, (u32) isr21);
    set_idt_gate(22, (u32) isr22);
    set_idt_gate(23, (u32) isr23);
    set_idt_gate(24, (u32) isr24);
    set_idt_gate(25, (u32) isr25);
    set_idt_gate(26, (u32) isr26);
    set_idt_gate(27, (u32) isr27);
    set_idt_gate(28, (u32) isr28);
    set_idt_gate(29, (u32) isr29);
    set_idt_gate(30, (u32) isr30);
    set_idt_gate(31, (u32) isr31);

     // Remap the PIC (note 0x2X is parent, 0xAX is child)
    set_port_byte(0x20, 0x11);
    set_port_byte(0xA0, 0x11);

    set_port_byte(0x21, 0x20);
    set_port_byte(0xA1, 0x28);

    set_port_byte(0x21, 0x04);
    set_port_byte(0xA1, 0x02);

    set_port_byte(0x21, 0x01);
    set_port_byte(0xA1, 0x01);

    set_port_byte(0x21, 0x0);
    set_port_byte(0xA1, 0x0); 

    // Install the IRQs
    set_idt_gate(32, (u32) irq0);
    set_idt_gate(33, (u32) irq1);
    set_idt_gate(34, (u32) irq2);
    set_idt_gate(35, (u32) irq3);
    set_idt_gate(36, (u32) irq4);
    set_idt_gate(37, (u32) irq5);
    set_idt_gate(38, (u32) irq6);
    set_idt_gate(39, (u32) irq7);
    set_idt_gate(40, (u32) irq8);
    set_idt_gate(41, (u32) irq9);
    set_idt_gate(42, (u32) irq10);
    set_idt_gate(43, (u32) irq11);
    set_idt_gate(44, (u32) irq12);
    set_idt_gate(45, (u32) irq13);
    set_idt_gate(46, (u32) irq14);
    set_idt_gate(47, (u32) irq15);

    set_idt();
}

/*
Runs when interrupt occurs
*/
void isr_handler(registers_t* reg) {
    // Debug messages; how I know it is an invalid opcode error
}

/*
Handles interrupt requests
*/
void irq_handler(registers_t* reg) {
    if (reg->int_no > 39) {
        set_port_byte(0xA0, 0x20);  // Send EOI command
    }
    set_port_byte(0x20, 0x20);      // Send EOI command

    if (interrupt_handlers[reg->int_no] != 0) {
        interrupt_handlers[reg->int_no](reg);    // Call handler
    }
}

更新内容:寄存器调试输出

根据建议,我输出了registers_t的所有寄存器值:

ds          = -1028128752 (0xC2B8A1A0)
edi         = 9248
esi         = 37035
ebp         = 589720
ebx         = 65535
edx         = 32
ecx         = 0
eax         = -1028128752 (0xC2B8A1A0)
int_no      = 6
err_code    = 0
eip         = -1028128752 (0xC2B8A1A0)
cs          = 8
eflags      = 65558
esp         = 12857
ss          = 589732

使用的ISR汇编例程

; Common ISR code
isr_common_stub:
    ; 1. Save CPU state
    pusha
    mov ax, ds
    push eax
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    push esp ; registers_t* r
    ; 2. Call C handler
    cld
    call isr_handler
    
    ; 3. Restore state
    pop eax 
    pop eax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    popa
    add esp, 8 ; Cleans up the pushed error code and pushed ISR number
    iret

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:53:15