| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; kernel.S - 中断处理程序
- ; 功能: 存储各个中断入口程序的地址,形成 intr_entry_table 数组
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- [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 ; 时钟中断对应的入口
- VECTOR 0x21, ZERO ; 键盘中断对应的入口
- VECTOR 0x22, ZERO ; 级联用的
- VECTOR 0x23, ZERO ; 串口 2 对应的入口
- VECTOR 0x24, ZERO ; 串口 1 对应的入口
- VECTOR 0x25, ZERO ; 并口 2 对应的入口
- VECTOR 0x26, ZERO ; 软盘对应的入口
- VECTOR 0x27, ZERO ; 并口 1 对应的入口
- VECTOR 0x28, ZERO ; 实时时钟对应的入口
- VECTOR 0x29, ZERO ; 重定向
- VECTOR 0x2a, ZERO ; 保留
- VECTOR 0x2b, ZERO ; 保留
- VECTOR 0x2c, ZERO ; ps/2 鼠标
- VECTOR 0x2d, ZERO ; fpu 浮点单元异常
- VECTOR 0x2e, ZERO ; 硬盘
- VECTOR 0x2f, ZERO ; 保留
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0x80 号中断 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- [bits 32]
- extern syscall_table
- section .text
- global syscall_handle
- syscall_handle:
- ; 保存上下文环境
- push 0 ; 压入 0,使栈中格式统一
- push ds
- push es
- push fs
- push gs
- pushad ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi
-
- push 0x80
- ; 为系统调用子功能传入参数
- push edx ; 系统调用中第 3 个参数
- push ecx ; 系统调用中第 2 个参数
- push ebx ; 系统调用中第 1 个参数
- ; 调用子功能处理函数
- call [syscall_table + eax*4]
- add esp, 12 ; 跨过上面的三个参数
- ; 将 call 调用后的返回值存入当前内核栈中 eax 的位置
- mov [esp + 8 *4], eax
- jmp intr_exit ; 返回,恢复上下文
|