io.asm 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. ;; This file is part of asmc, a bootstrapping OS with minimal seed
  2. ;; Copyright (C) 2018-2019 Giovanni Mascellani <gio@debian.org>
  3. ;; https://gitlab.com/giomasce/asmc
  4. ;; This program is free software: you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. TERM_ROW_NUM equ 25
  15. TERM_COL_NUM equ 80
  16. TERM_BASE_ADDR equ 0xb8000
  17. %ifdef DEBUG
  18. section .bss
  19. term_row:
  20. resd 1
  21. term_col:
  22. resd 1
  23. section .text
  24. ;; Fill the VGA framebuffer with spaces char, with color light grey
  25. ;; on black
  26. ;; Destroys: EAX
  27. term_setup:
  28. xor eax, eax
  29. term_setup_loop:
  30. mov BYTE [2*eax+TERM_BASE_ADDR], ' '
  31. mov BYTE [2*eax+TERM_BASE_ADDR+1], 0x07
  32. inc eax
  33. cmp eax, TERM_ROW_NUM * TERM_COL_NUM
  34. jne term_setup_loop
  35. ;; Set the cursor position
  36. mov DWORD [term_row], 0
  37. mov DWORD [term_col], 0
  38. ret
  39. ;; void term_set_char(int row, int col, int char)
  40. term_set_char:
  41. ;; Computer the character address
  42. mov eax, [esp+4]
  43. mov edx, TERM_COL_NUM
  44. mul edx
  45. add eax, [esp+8]
  46. mov edx, 2
  47. mul edx
  48. add eax, TERM_BASE_ADDR
  49. ;; Store the new character
  50. mov dl, [esp+12]
  51. mov BYTE [eax], dl
  52. ret
  53. ;; void term_shift()
  54. ;; Destroys: EAX, EDX
  55. term_shift:
  56. xor eax, eax
  57. term_shift_loop:
  58. mov dl, [2*eax+TERM_BASE_ADDR+2*TERM_COL_NUM]
  59. mov [2*eax+TERM_BASE_ADDR], dl
  60. mov dl, [2*eax+TERM_BASE_ADDR+2*TERM_COL_NUM+1]
  61. mov [2*eax+TERM_BASE_ADDR+1], dl
  62. inc eax
  63. cmp eax, (TERM_ROW_NUM-1) * TERM_COL_NUM
  64. jne term_shift_loop
  65. ;; Clear last line
  66. term_shift_loop2:
  67. mov BYTE [2*eax+TERM_BASE_ADDR], ' '
  68. mov BYTE [2*eax+TERM_BASE_ADDR+1], 0x07
  69. inc eax
  70. cmp eax, TERM_ROW_NUM * TERM_COL_NUM
  71. jne term_shift_loop2
  72. term_shift_ret:
  73. ret
  74. ;; void term_put_char(int char)
  75. ;; Input char in CL
  76. ;; Destroys: EAX, EDX
  77. term_put_char:
  78. ;; If the character is a newline, jump to the newline code
  79. cmp cl, NEWLINE
  80. je term_put_char_newline
  81. ;; Set character
  82. mov eax, [term_row]
  83. mov edx, TERM_COL_NUM
  84. mul edx
  85. add eax, [term_col]
  86. mov [2*eax+TERM_BASE_ADDR], cl
  87. ;; Advance of one character and check for column overflow
  88. inc DWORD [term_col]
  89. cmp DWORD [term_col], TERM_COL_NUM
  90. jne term_put_char_finish
  91. ;; Move to the beginning of next row and check for row overflow
  92. term_put_char_newline:
  93. mov DWORD [term_col], 0
  94. inc DWORD [term_row]
  95. cmp DWORD [term_row], TERM_ROW_NUM
  96. jne term_put_char_finish
  97. ;; Reset the row position and shift all lines
  98. dec DWORD [term_row]
  99. call term_shift
  100. term_put_char_finish:
  101. ret
  102. SERIAL_PORT equ 0x3f8
  103. ;; void serial_setup()
  104. serial_setup:
  105. ;; Send command as indicated in https://wiki.osdev.org/Serial_Port
  106. mov edx, SERIAL_PORT
  107. add edx, 1
  108. mov eax, 0x00
  109. out dx, al
  110. mov edx, SERIAL_PORT
  111. add edx, 3
  112. mov eax, 0x80
  113. out dx, al
  114. mov edx, SERIAL_PORT
  115. add edx, 0
  116. mov eax, 0x03
  117. out dx, al
  118. mov edx, SERIAL_PORT
  119. add edx, 1
  120. mov eax, 0x00
  121. out dx, al
  122. mov edx, SERIAL_PORT
  123. add edx, 3
  124. mov eax, 0x03
  125. out dx, al
  126. mov edx, SERIAL_PORT
  127. add edx, 2
  128. mov eax, 0xc7
  129. out dx, al
  130. mov edx, SERIAL_PORT
  131. add edx, 4
  132. mov eax, 0x0b
  133. out dx, al
  134. ret
  135. ;; void serial_write_char(char c)
  136. ;; Input char in CL
  137. ;; Destroys: EAX, EDX
  138. serial_write_char:
  139. ;; Test until the serial is available for transmit
  140. mov edx, SERIAL_PORT + 5
  141. in al, dx
  142. and eax, 0x20
  143. je serial_write_char
  144. ;; Actually write the char
  145. mov al, cl
  146. mov edx, SERIAL_PORT
  147. out dx, al
  148. ret
  149. ;; Input char in CL
  150. ;; Destroys: EAX, EDX
  151. write_console:
  152. ;; Send stdout to terminal
  153. call term_put_char
  154. call serial_write_char
  155. ret
  156. stdout_setup:
  157. call term_setup
  158. call serial_setup
  159. ret
  160. ;; Input number in AL
  161. ;; Returns: AL (hex digit corresponding to input)
  162. num2hex:
  163. and al, 0xf
  164. add al, '0'
  165. cmp al, '9'
  166. jbe ret_simple
  167. add al, 'a' - '0' - 10
  168. ret
  169. ;; Input in EDX
  170. ;; Destroys: EAX, ECX
  171. write_hex:
  172. push edx
  173. mov eax, [esp]
  174. shr eax, 28
  175. call num2hex
  176. mov cl, al
  177. call write
  178. mov eax, [esp]
  179. shr eax, 24
  180. call num2hex
  181. mov cl, al
  182. call write
  183. mov eax, [esp]
  184. shr eax, 20
  185. call num2hex
  186. mov cl, al
  187. call write
  188. mov eax, [esp]
  189. shr eax, 16
  190. call num2hex
  191. mov cl, al
  192. call write
  193. mov eax, [esp]
  194. shr eax, 12
  195. call num2hex
  196. mov cl, al
  197. call write
  198. mov eax, [esp]
  199. shr eax, 8
  200. call num2hex
  201. mov cl, al
  202. call write
  203. mov eax, [esp]
  204. shr eax, 4
  205. call num2hex
  206. mov cl, al
  207. call write
  208. mov eax, [esp]
  209. shr eax, 0
  210. call num2hex
  211. mov cl, al
  212. call write
  213. pop edx
  214. ret
  215. single_stepping_handler:
  216. mov ebx, [instr_num]
  217. sub ebx, 0x036c7600
  218. test ebx, 0x0
  219. jnz single_stepping_handler_end
  220. cmp ebx, 0
  221. jl single_stepping_handler_end
  222. cmp ebx, 0x100000
  223. jge shutdown
  224. mov ebx, [esp+4]
  225. mov esi, str_instr_num
  226. call log
  227. mov edx, [instr_num]
  228. call write_hex
  229. mov esi, str_eip
  230. call log
  231. mov edx, [ebx+0x20]
  232. call write_hex
  233. mov esi, str_eax
  234. call log
  235. mov edx, [ebx+0x1c]
  236. call write_hex
  237. mov esi, str_ecx
  238. call log
  239. mov edx, [ebx+0x18]
  240. call write_hex
  241. mov esi, str_edx
  242. call log
  243. mov edx, [ebx+0x14]
  244. call write_hex
  245. mov esi, str_ebx
  246. call log
  247. mov edx, [ebx+0x10]
  248. call write_hex
  249. mov esi, str_esp
  250. call log
  251. mov edx, [ebx+0x0c]
  252. call write_hex
  253. mov esi, str_ebp
  254. call log
  255. mov edx, [ebx+0x08]
  256. call write_hex
  257. mov esi, str_esi
  258. call log
  259. mov edx, [ebx+0x04]
  260. call write_hex
  261. mov esi, str_edi
  262. call log
  263. mov edx, [ebx+0x00]
  264. call write_hex
  265. mov cl, NEWLINE
  266. call write
  267. single_stepping_handler_end:
  268. inc DWORD [instr_num]
  269. ret
  270. enable_single_stepping:
  271. mov DWORD [instr_num], 0x3180
  272. mov DWORD [0x10010], single_stepping_handler
  273. call [0x1001c]
  274. ret
  275. section .bss
  276. instr_num resd 1
  277. section .data
  278. str_instr_num db 'instr_num=', 0
  279. str_eip db ' EIP=', 0
  280. str_eax db ' EAX=', 0
  281. str_ecx db ' ECX=', 0
  282. str_edx db ' EDX=', 0
  283. str_ebx db ' EBX=', 0
  284. str_esp db ' ESP=', 0
  285. str_ebp db ' EBP=', 0
  286. str_esi db ' ESI=', 0
  287. str_edi db ' EDI=', 0
  288. %endif