kernel.S 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ; kernel.S - 中断处理程序
  3. ; 功能: 存储各个中断入口程序的地址,形成 intr_entry_table 数组
  4. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5. [bits 32]
  6. %define ERROR_CODE nop
  7. %define ZERO push 0
  8. extern put_str ; 声明外部函数
  9. extern idt_table ; idt_table 是 C 中注册的中断处理程序数组
  10. section .data
  11. intr_str db "interrup occur!", 0xa, 0
  12. global intr_entry_table
  13. intr_entry_table:
  14. %macro VECTOR 2
  15. section .text
  16. intr%1entry: ; 每个中断处理程序都要压入中断向量号,所以一个中断类型一个中断处理程序
  17. %2
  18. ; 保存上下文环境
  19. push ds
  20. push es
  21. push fs
  22. push gs
  23. pushad ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi
  24. ; 如果从片上进入的中断,除了从片上发送 EOI 外,还要往主片上发送 EOI
  25. mov al, 0x20 ; EOI 中断结束命令
  26. out 0xa0, al ; 发送给从片
  27. out 0x20, al ; 发送给主片
  28. push %1 ; 不管 idt_table 中的目标程序是否需要参数,都保存中断向量号,调试方便
  29. call [idt_table + %1 * 4] ; 调用中断处理程序(中断处理程序的地址存储在 idt_table 中,是 C 中注册的中断处理程序数组)
  30. jmp intr_exit ; 中断处理程序执行完毕,跳转到中断退出程序
  31. section .data
  32. dd intr%1entry ; 存储各个中断入口程序的地址,形成 intr_entry_table 数组
  33. %endmacro
  34. VECTOR 0x00, ZERO
  35. VECTOR 0x01, ZERO
  36. VECTOR 0x02, ZERO
  37. VECTOR 0x03, ZERO
  38. VECTOR 0x04, ZERO
  39. VECTOR 0x05, ZERO
  40. VECTOR 0x06, ZERO
  41. VECTOR 0x07, ZERO
  42. VECTOR 0x08, ZERO
  43. VECTOR 0x09, ZERO
  44. VECTOR 0x0a, ZERO
  45. VECTOR 0x0b, ZERO
  46. VECTOR 0x0c, ZERO
  47. VECTOR 0x0d, ZERO
  48. VECTOR 0x0e, ZERO
  49. VECTOR 0x0f, ZERO
  50. VECTOR 0x10, ZERO
  51. VECTOR 0x11, ZERO
  52. VECTOR 0x12, ZERO
  53. VECTOR 0x13, ZERO
  54. VECTOR 0x14, ZERO
  55. VECTOR 0x15, ZERO
  56. VECTOR 0x16, ZERO
  57. VECTOR 0x17, ZERO
  58. VECTOR 0x18, ZERO
  59. VECTOR 0x19, ZERO
  60. VECTOR 0x1a, ZERO
  61. VECTOR 0x1b, ZERO
  62. VECTOR 0x1c, ZERO
  63. VECTOR 0x1d, ZERO
  64. VECTOR 0x1e, ERROR_CODE
  65. VECTOR 0x1f, ZERO
  66. VECTOR 0x20, ZERO ; 时钟中断对应的入口
  67. VECTOR 0x21, ZERO ; 键盘中断对应的入口
  68. VECTOR 0x22, ZERO ; 级联用的
  69. VECTOR 0x23, ZERO ; 串口 2 对应的入口
  70. VECTOR 0x24, ZERO ; 串口 1 对应的入口
  71. VECTOR 0x25, ZERO ; 并口 2 对应的入口
  72. VECTOR 0x26, ZERO ; 软盘对应的入口
  73. VECTOR 0x27, ZERO ; 并口 1 对应的入口
  74. VECTOR 0x28, ZERO ; 实时时钟对应的入口
  75. VECTOR 0x29, ZERO ; 重定向
  76. VECTOR 0x2a, ZERO ; 保留
  77. VECTOR 0x2b, ZERO ; 保留
  78. VECTOR 0x2c, ZERO ; ps/2 鼠标
  79. VECTOR 0x2d, ZERO ; fpu 浮点单元异常
  80. VECTOR 0x2e, ZERO ; 硬盘
  81. VECTOR 0x2f, ZERO ; 保留
  82. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0x80 号中断 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  83. [bits 32]
  84. extern syscall_table
  85. section .text
  86. global syscall_handle
  87. syscall_handle:
  88. ; 保存上下文环境
  89. push 0 ; 压入 0,使栈中格式统一
  90. push ds
  91. push es
  92. push fs
  93. push gs
  94. pushad ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi
  95. push 0x80
  96. ; 为系统调用子功能传入参数
  97. push edx ; 系统调用中第 3 个参数
  98. push ecx ; 系统调用中第 2 个参数
  99. push ebx ; 系统调用中第 1 个参数
  100. ; 调用子功能处理函数
  101. call [syscall_table + eax*4]
  102. add esp, 12 ; 跨过上面的三个参数
  103. ; 将 call 调用后的返回值存入当前内核栈中 eax 的位置
  104. mov [esp + 8 *4], eax
  105. jmp intr_exit ; 返回,恢复上下文
  106. [bits 32]
  107. section .text
  108. global intr_exit
  109. intr_exit:
  110. add esp, 4 ; 跳过中断向量号
  111. popad ; 恢复通用寄存器的值
  112. pop gs
  113. pop fs
  114. pop es
  115. pop ds
  116. add esp, 4 ; 由于中断发生时,CPU 会自动压入错误码,所以在中断退出时,需要将错误码弹出
  117. iretd ; 从中断返回