kernel.S 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. section .text
  35. global intr_exit
  36. intr_exit:
  37. add esp, 4 ; 跳过中断向量号
  38. popad ; 恢复通用寄存器的值
  39. pop gs
  40. pop fs
  41. pop es
  42. pop ds
  43. add esp, 4 ; 由于中断发生时,CPU 会自动压入错误码,所以在中断退出时,需要将错误码弹出
  44. iretd ; 从中断返回
  45. VECTOR 0x00, ZERO
  46. VECTOR 0x01, ZERO
  47. VECTOR 0x02, ZERO
  48. VECTOR 0x03, ZERO
  49. VECTOR 0x04, ZERO
  50. VECTOR 0x05, ZERO
  51. VECTOR 0x06, ZERO
  52. VECTOR 0x07, ZERO
  53. VECTOR 0x08, ZERO
  54. VECTOR 0x09, ZERO
  55. VECTOR 0x0a, ZERO
  56. VECTOR 0x0b, ZERO
  57. VECTOR 0x0c, ZERO
  58. VECTOR 0x0d, ZERO
  59. VECTOR 0x0e, ZERO
  60. VECTOR 0x0f, ZERO
  61. VECTOR 0x10, ZERO
  62. VECTOR 0x11, ZERO
  63. VECTOR 0x12, ZERO
  64. VECTOR 0x13, ZERO
  65. VECTOR 0x14, ZERO
  66. VECTOR 0x15, ZERO
  67. VECTOR 0x16, ZERO
  68. VECTOR 0x17, ZERO
  69. VECTOR 0x18, ZERO
  70. VECTOR 0x19, ZERO
  71. VECTOR 0x1a, ZERO
  72. VECTOR 0x1b, ZERO
  73. VECTOR 0x1c, ZERO
  74. VECTOR 0x1d, ZERO
  75. VECTOR 0x1e, ERROR_CODE
  76. VECTOR 0x1f, ZERO
  77. VECTOR 0x20, ZERO ; 时钟中断对应的入口
  78. VECTOR 0x21, ZERO ; 键盘中断对应的入口
  79. VECTOR 0x22, ZERO ; 级联用的
  80. VECTOR 0x23, ZERO ; 串口 2 对应的入口
  81. VECTOR 0x24, ZERO ; 串口 1 对应的入口
  82. VECTOR 0x25, ZERO ; 并口 2 对应的入口
  83. VECTOR 0x26, ZERO ; 软盘对应的入口
  84. VECTOR 0x27, ZERO ; 并口 1 对应的入口
  85. VECTOR 0x28, ZERO ; 实时时钟对应的入口
  86. VECTOR 0x29, ZERO ; 重定向
  87. VECTOR 0x2a, ZERO ; 保留
  88. VECTOR 0x2b, ZERO ; 保留
  89. VECTOR 0x2c, ZERO ; ps/2 鼠标
  90. VECTOR 0x2d, ZERO ; fpu 浮点单元异常
  91. VECTOR 0x2e, ZERO ; 硬盘
  92. VECTOR 0x2f, ZERO ; 保留
  93. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0x80 号中断 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  94. [bits 32]
  95. extern syscall_table
  96. section .text
  97. global syscall_handle
  98. syscall_handle:
  99. ; 保存上下文环境
  100. push 0 ; 压入 0,使栈中格式统一
  101. push ds
  102. push es
  103. push fs
  104. push gs
  105. pushad ; 保存通用寄存器的值, 依次是 eax, ecx, edx, ebx, esp, ebp, esi, edi
  106. push 0x80
  107. ; 为系统调用子功能传入参数
  108. push edx ; 系统调用中第 3 个参数
  109. push ecx ; 系统调用中第 2 个参数
  110. push ebx ; 系统调用中第 1 个参数
  111. ; 调用子功能处理函数
  112. call [syscall_table + eax*4]
  113. add esp, 12 ; 跨过上面的三个参数
  114. ; 将 call 调用后的返回值存入当前内核栈中 eax 的位置
  115. mov [esp + 8 *4], eax
  116. jmp intr_exit ; 返回,恢复上下文