library.asm 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. ;; This file is part of asmc, a bootstrapping OS with minimal seed
  2. ;; Copyright (C) 2018 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. NEWLINE equ 0xa
  15. SPACE equ 0x20
  16. TAB equ 0x9
  17. FEED equ 0xc
  18. RETURN equ 0xd
  19. VERTTAB equ 0xb
  20. ZERO equ 0x30
  21. NINE equ 0x39
  22. LITTLEA equ 0x61
  23. LITTLEF equ 0x66
  24. LITTLEN equ 0x6e
  25. LITTLER equ 0x72
  26. LITTLET equ 0x74
  27. LITTLEV equ 0x76
  28. LITTLEX equ 0x78
  29. SQ_OPEN equ 0x5b
  30. SQ_CLOSED equ 0x5d
  31. PLUS equ 0x2b
  32. APEX equ 0x27
  33. COMMA equ 0x2c
  34. SEMICOLON equ 0x3b
  35. COLON equ 0x3a
  36. DOT equ 0x2e
  37. QUOTE equ 0x22
  38. BACKSLASH equ 0x5c
  39. POUND equ 0x23
  40. DOLLAR equ 0x24
  41. AMPERSAND equ 0x26
  42. PERCENT equ 0x25
  43. AT_SIGN equ 0x40
  44. INPUT_BUF_LEN equ 1024
  45. MAX_SYMBOL_NAME_LEN equ 64
  46. MAX_SYMBOL_NAME_LEN_LOG equ 6
  47. SYMBOL_TABLE_LEN equ 4096
  48. section .bss
  49. symbol_names_ptr:
  50. resd 1
  51. symbol_locs_ptr:
  52. resd 1
  53. symbol_arities_ptr:
  54. resd 1
  55. symbol_num:
  56. resd 1
  57. initial_loc:
  58. resd 1
  59. current_loc:
  60. resd 1
  61. stage:
  62. resd 1
  63. section .text
  64. ;; Input number in AL
  65. ;; Returns: AL (hex digit corresponding to input)
  66. num2alphahex:
  67. and al, 0xf
  68. add al, LITTLEA
  69. ret
  70. ;; Emit character in CL
  71. ;; Destroys: EDX
  72. emit:
  73. ;; If we are in stage 1, write the character
  74. cmp DWORD [stage], 1
  75. jne emit_end
  76. mov edx, [current_loc]
  77. mov [edx], cl
  78. emit_end:
  79. ;; Increment current location
  80. inc DWORD [current_loc]
  81. ret
  82. ;; Emit dword in ECX
  83. ;; Destroys: ECX, EDX
  84. emit32:
  85. call emit
  86. shr ecx, 8
  87. emit24:
  88. call emit
  89. shr ecx, 8
  90. emit16:
  91. call emit
  92. shr ecx, 8
  93. call emit
  94. ret
  95. ;; Input in EAX
  96. ;; Destroys: ECX
  97. ;; Return: EAX (valid), EDX (number value)
  98. decode_number:
  99. ;; Empty string: return false
  100. cmp BYTE [eax], 0
  101. je ret_zero
  102. ;; Setup result
  103. xor edx, edx
  104. ;; Check hex string
  105. mov ecx, [eax]
  106. and ecx, 0xffff
  107. cmp ecx, '0x'
  108. jne decode_number_dec
  109. ;; Check bad hex string
  110. add eax, 2
  111. mov cl, [eax]
  112. test cl, cl
  113. jz ret_zero
  114. decode_number_hex:
  115. ;; Check for terminator
  116. xor ecx, ecx
  117. mov cl, [eax]
  118. test cl, cl
  119. jz ret_one
  120. ;; Check digit is valid
  121. sub cl, ZERO
  122. cmp cl, 10
  123. jb decode_number_hex_valid
  124. sub cl, LITTLEA - ZERO
  125. cmp cl, 6
  126. jae ret_zero
  127. add cl, 10
  128. decode_number_hex_valid:
  129. ;; Update result and pointer
  130. shl edx, 4
  131. add edx, ecx
  132. inc eax
  133. jmp decode_number_hex
  134. decode_number_dec:
  135. ;; Check for terminator
  136. xor ecx, ecx
  137. mov cl, [eax]
  138. test cl, cl
  139. jz ret_one
  140. ;; Check digit is valid
  141. sub cl, ZERO
  142. cmp cl, 10
  143. jae ret_zero
  144. ;; Update result and pointer
  145. shl edx, 1
  146. lea edx, [edx+4*edx]
  147. add edx, ecx
  148. inc eax
  149. jmp decode_number_dec
  150. ;; Input in EAX
  151. ;; Destroys: ECX, EDX
  152. ;; Returns: EAX
  153. atoi:
  154. call decode_number
  155. test eax, eax
  156. jz platform_panic
  157. mov eax, edx
  158. ret
  159. init_symbols:
  160. ;; Allocate symbol names table
  161. mov eax, SYMBOL_TABLE_LEN * MAX_SYMBOL_NAME_LEN
  162. call allocate
  163. mov [symbol_names_ptr], eax
  164. ;; Allocate symbol locations table
  165. mov eax, 4 * SYMBOL_TABLE_LEN
  166. call allocate
  167. mov [symbol_locs_ptr], eax
  168. ;; Allocate symbol arities table
  169. mov eax, 4 * SYMBOL_TABLE_LEN
  170. call allocate
  171. mov [symbol_arities_ptr], eax
  172. ;; Reset symbol_num
  173. mov DWORD [symbol_num], 0
  174. ret
  175. ;; Input in EDX
  176. ;; Destroys: EAX
  177. ;; Returns: ECX
  178. get_symbol_idx:
  179. push esi
  180. push edi
  181. ;; Set up registers and stack
  182. xor ecx, ecx
  183. get_symbol_idx_loop:
  184. ;; Check for termination
  185. cmp ecx, [symbol_num]
  186. je get_symbol_idx_end
  187. ;; Compute pointer to current symbol name
  188. mov esi, ecx
  189. shl esi, MAX_SYMBOL_NAME_LEN_LOG
  190. add esi, [symbol_names_ptr]
  191. ;; Compare with argument
  192. mov edi, edx
  193. call strcmp2
  194. ;; If strcmp returned 0, then we return
  195. cmp eax, 0
  196. je get_symbol_idx_end
  197. ;; Increment ecx and restart loop
  198. inc ecx
  199. jmp get_symbol_idx_loop
  200. get_symbol_idx_end:
  201. pop edi
  202. pop esi
  203. ret
  204. ;; Input in EDX
  205. ;; Returns: EAX (found), ECX (loc), EDX (arity)
  206. find_symbol:
  207. ;; Call get_symbol_idx and set return code
  208. call get_symbol_idx
  209. xor eax, eax
  210. cmp ecx, [symbol_num]
  211. je find_symbol_ret
  212. ;; Copy arity to EDX
  213. mov eax, [symbol_arities_ptr]
  214. mov edx, [eax+4*ecx]
  215. ;; Copy loc to ECX
  216. mov eax, [symbol_locs_ptr]
  217. mov ecx, [eax+4*ecx]
  218. ;; Return true
  219. mov eax, 1
  220. find_symbol_ret:
  221. ret
  222. ;; Input in EDX
  223. ;; Destroys: ECX
  224. ;; Returns: EAX (loc), EDX (arity)
  225. find_symbol_or_panic:
  226. call find_symbol
  227. cmp eax, 0
  228. je platform_panic
  229. mov eax, ecx
  230. ret
  231. ;; Input in EDX
  232. ;; Destroys: ECX, EDX
  233. ;; Return EAX (loc or zero)
  234. find_symbol_or_zero:
  235. cmp DWORD [stage], 1
  236. jne ret_zero
  237. call find_symbol_or_panic
  238. ret
  239. ;; Input in ESI
  240. ;; Destroys: EAX
  241. check_symbol_length:
  242. call strlen2
  243. cmp eax, 0
  244. jna platform_panic
  245. cmp eax, MAX_SYMBOL_NAME_LEN-1
  246. jnb platform_panic
  247. ret
  248. ;; Input in EAX (name), ECX (loc) and EDX (arity)
  249. ;; Destroys: EAX, ECX, EDX
  250. add_symbol:
  251. push esi
  252. push edi
  253. push edx
  254. push ecx
  255. push eax
  256. ;; Check input length
  257. mov esi, eax
  258. call check_symbol_length
  259. ;; Call find_symbol and check the symbol does not exist yet
  260. pop edx
  261. call get_symbol_idx
  262. cmp ecx, [symbol_num]
  263. jne platform_panic
  264. ;; Put the current symbol number in ebx and check it is not
  265. ;; overflowing
  266. cmp ecx, SYMBOL_TABLE_LEN
  267. jnb platform_panic
  268. ;; Save the name
  269. mov esi, edx
  270. mov edi, [symbol_num]
  271. shl edi, MAX_SYMBOL_NAME_LEN_LOG
  272. add edi, [symbol_names_ptr]
  273. call strcpy2
  274. ;; Save the location for the new symbol
  275. mov eax, [symbol_num]
  276. shl eax, 2
  277. add eax, [symbol_locs_ptr]
  278. pop DWORD [eax]
  279. ;; Save the arity for the new symbol
  280. mov eax, [symbol_num]
  281. shl eax, 2
  282. add eax, [symbol_arities_ptr]
  283. pop DWORD [eax]
  284. ;; Increment and store the new symbol number
  285. inc DWORD [symbol_num]
  286. pop edi
  287. pop esi
  288. ret
  289. ;; Input in EAX (name), ECX (loc) and EDX (arity)
  290. ;; Destroys: EAX, ECX, EDX
  291. add_symbol_wrapper:
  292. ;; Branch to appropriate stage
  293. cmp DWORD [stage], 0
  294. jne add_symbol_wrapper_stage1
  295. ;; Stage 0: call actual add_symbol
  296. call add_symbol
  297. jmp add_symbol_wrapper_ret
  298. add_symbol_wrapper_stage1:
  299. ;; Save parameters
  300. push edx
  301. push ecx
  302. ;; Call find_symbol
  303. mov edx, eax
  304. call find_symbol
  305. ;; Check the symbol was found
  306. cmp eax, 0
  307. je platform_panic
  308. ;; Check the location matches
  309. pop eax
  310. cmp ecx, eax
  311. jne platform_panic
  312. ;; Check the arity matches
  313. pop eax
  314. cmp edx, eax
  315. jne platform_panic
  316. add_symbol_wrapper_ret:
  317. ret
  318. ;; Input in EAX (symbol name), EDX (arity)
  319. add_symbol_placeholder:
  320. ;; Call find_symbol
  321. push eax
  322. push edx
  323. mov edx, eax
  324. call find_symbol
  325. ;; Check that the symbol exists if we are not in stage 0
  326. cmp DWORD [stage], 0
  327. je add_symbol_placeholder_stage0
  328. cmp eax, 0
  329. je platform_panic
  330. add_symbol_placeholder_stage0:
  331. ;; If the symbol was not found...
  332. cmp eax, 0
  333. jne add_symbol_placeholder_found
  334. ;; ...add it, with a fake location
  335. pop edx
  336. pop eax
  337. mov ecx, -1
  338. call add_symbol
  339. jmp add_symbol_placeholder_end
  340. add_symbol_placeholder_found:
  341. ;; If it was found, check that arity matches
  342. pop eax
  343. cmp edx, eax
  344. jne platform_panic
  345. add esp, 4
  346. add_symbol_placeholder_end:
  347. ret
  348. ;; Input in EAX (name), ECX (loc) and EDX (arity)
  349. ;; Destroys: EAX, ECX, EDX
  350. fix_symbol_placeholder:
  351. ;; Call find_symbol
  352. push eax
  353. push ecx
  354. push edx
  355. mov edx, eax
  356. call find_symbol
  357. ;; Check that the symbol exists if we are not in stage 0
  358. cmp DWORD [stage], 0
  359. je fix_symbol_placeholder_stage0
  360. cmp eax, 0
  361. je platform_panic
  362. fix_symbol_placeholder_stage0:
  363. ;; If the symbol was not found...
  364. cmp eax, 0
  365. jne fix_symbol_placeholder_found
  366. ;; ..add it
  367. pop edx
  368. pop ecx
  369. pop eax
  370. call add_symbol
  371. jmp add_symbol_placeholder_end
  372. fix_symbol_placeholder_found:
  373. ;; If it was found, check that arity matches
  374. pop eax
  375. cmp eax, edx
  376. jne platform_panic
  377. ;; And check that loc either matches...
  378. pop eax
  379. cmp eax, ecx
  380. pop edx
  381. je fix_symbol_placeholder_end
  382. ;; ...or is -1 at stage 0...
  383. cmp ecx, -1
  384. jne platform_panic
  385. cmp DWORD [stage], 0
  386. jne platform_panic
  387. ;; ...in which case update it
  388. push eax
  389. call get_symbol_idx
  390. cmp ecx, [symbol_num]
  391. je platform_panic
  392. mov eax, [symbol_locs_ptr]
  393. pop edx
  394. mov [eax+4*ecx], edx
  395. fix_symbol_placeholder_end:
  396. ret
  397. ;; String pointers are in ESI and EDI
  398. ;; Destroys: ESI, EDI
  399. ;; Returns: EAX
  400. strcmp2_loop:
  401. cmp al, 0
  402. je ret_zero
  403. inc esi
  404. inc edi
  405. strcmp2:
  406. mov al, [esi]
  407. cmp al, [edi]
  408. je strcmp2_loop
  409. jmp ret_one
  410. ;; String pointer in ESI
  411. ;; Destroys: ESI
  412. ;; Returns: EAX
  413. strlen2:
  414. mov eax, 0
  415. jmp strlen2_inside
  416. strlen2_loop:
  417. inc esi
  418. inc eax
  419. strlen2_inside:
  420. cmp BYTE [esi], 0
  421. jne strlen2_loop
  422. ret
  423. ;; Source in ESI, destination in EDI
  424. ;; Destroys: ESI, EDI, EAX
  425. strcpy2_loop:
  426. inc esi
  427. inc edi
  428. strcpy2:
  429. mov al, [esi]
  430. mov [edi], al
  431. cmp al, 0
  432. jne strcpy2_loop
  433. ret
  434. ;; Wrapper over strcmp2
  435. strcmp:
  436. push esi
  437. push edi
  438. mov esi, [esp+12]
  439. mov edi, [esp+16]
  440. call strcmp2
  441. pop edi
  442. pop esi
  443. ret
  444. ;; Wrapper over strlen2
  445. strlen:
  446. push esi
  447. mov esi, [esp+8]
  448. call strlen2
  449. pop esi
  450. ret
  451. ;; Wrapper over strcpy2
  452. strcpy:
  453. push esi
  454. push edi
  455. mov esi, [esp+16]
  456. mov edi, [esp+12]
  457. call strcpy2
  458. pop edi
  459. pop esi
  460. ret
  461. ;; Common return cases
  462. ret_zero:
  463. xor eax, eax
  464. ret_simple:
  465. ret
  466. ret_one:
  467. xor eax, eax
  468. inc eax
  469. ret