;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; kernel.S - 中断处理程序 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [bits 32] %define ERROR_CODE nop %define ZERO push 0 extern put_str ; 声明外部函数 extern idt_table ; idt_table 是 C 中注册的中断处理程序数组 section .data intr_str db "interrup occur!", 0xa, 0 global intr_entry_table intr_entry_table: %macro VECTOR 2 section .text intr%1entry: ; 每个中断处理程序都要压入中断向量号,所以一个中断类型一个中断处理程序 %2 ; 保存上下文环境 push ds push es push fs push gs pushad ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi ; 如果从片上进入的中断,除了从片上发送 EOI 外,还要往主片上发送 EOI mov al, 0x20 ; EOI 中断结束命令 out 0xa0, al ; 发送给从片 out 0x20, al ; 发送给主片 push %1 ; 不管 idt_table 中的目标程序是否需要参数,都保存中断向量号,调试方便 call [idt_table + %1 * 4] ; 调用中断处理程序(中断处理程序的地址存储在 idt_table 中,是 C 中注册的中断处理程序数组) jmp intr_exit ; 中断处理程序执行完毕,跳转到中断退出程序 section .data dd intr%1entry ; 存储各个中断入口程序的地址,形成 intr_entry_table 数组 %endmacro section .text global intr_exit intr_exit: add esp, 4 ; 跳过中断向量号 popad ; 恢复通用寄存器的值 pop gs pop fs pop es pop ds add esp, 4 ; 由于中断发生时,CPU 会自动压入错误码,所以在中断退出时,需要将错误码弹出 iretd ; 从中断返回 VECTOR 0x00, ZERO VECTOR 0x01, ZERO VECTOR 0x02, ZERO VECTOR 0x03, ZERO VECTOR 0x04, ZERO VECTOR 0x05, ZERO VECTOR 0x06, ZERO VECTOR 0x07, ZERO VECTOR 0x08, ZERO VECTOR 0x09, ZERO VECTOR 0x0a, ZERO VECTOR 0x0b, ZERO VECTOR 0x0c, ZERO VECTOR 0x0d, ZERO VECTOR 0x0e, ZERO VECTOR 0x0f, ZERO VECTOR 0x10, ZERO VECTOR 0x11, ZERO VECTOR 0x12, ZERO VECTOR 0x13, ZERO VECTOR 0x14, ZERO VECTOR 0x15, ZERO VECTOR 0x16, ZERO VECTOR 0x17, ZERO VECTOR 0x18, ZERO VECTOR 0x19, ZERO VECTOR 0x1a, ZERO VECTOR 0x1b, ZERO VECTOR 0x1c, ZERO VECTOR 0x1d, ZERO VECTOR 0x1e, ERROR_CODE VECTOR 0x1f, ZERO VECTOR 0x20, ZERO