启用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
相关产品推荐
相关产品推荐

