asmg.asm 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955
  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. WRITE_LABEL_BUF_LEN equ 128
  15. STACK_VARS_LEN equ 1024
  16. ;; STACK_VARS_SIZE = STACK_VARS_LEN * MAX_SYMBOL_NAME_LEN
  17. STACK_VARS_SIZE equ 131072
  18. TEMP_VAR:
  19. db '__temp'
  20. db 0
  21. push_esp_pos:
  22. db 0xff
  23. db 0xb4
  24. db 0x24
  25. lea_eax_esp_pos:
  26. db 0x8d
  27. db 0x84
  28. db 0x24
  29. push_peax:
  30. db 0xff
  31. db 0x30
  32. add_esp:
  33. db 0x81
  34. db 0xc4
  35. pop_ebp_ret:
  36. db 0x5d
  37. db 0xc3
  38. pop_eax_cmp_eax_0_je_rel:
  39. db 0x58
  40. db 0x83
  41. db 0xf8
  42. db 0x00
  43. db 0x0f
  44. db 0x84
  45. sub_esp_4:
  46. db 0x83
  47. db 0xec
  48. db 0x04
  49. push_ebp_mov_ebp_esp:
  50. db 0x55
  51. db 0x89
  52. db 0xe5
  53. pop_eax_call_eax:
  54. db 0x58
  55. db 0xff
  56. db 0xd0
  57. str_cu_open:
  58. db '{'
  59. db 0
  60. str_cu_closed:
  61. db '}'
  62. db 0
  63. str_semicolon:
  64. db SEMICOLON
  65. db 0
  66. str_ret:
  67. db 'ret'
  68. db 0
  69. str_if:
  70. db 'if'
  71. db 0
  72. str_while:
  73. db 'while'
  74. db 0
  75. str_else:
  76. db 'else'
  77. db 0
  78. str_ifun:
  79. db 'ifun'
  80. db 0
  81. str_fun:
  82. db 'fun'
  83. db 0
  84. str_const:
  85. db 'const'
  86. db 0
  87. label_num:
  88. resd 1
  89. stack_vars_ptr:
  90. resd 1
  91. block_depth:
  92. resd 1
  93. stack_depth:
  94. resd 1
  95. temp_depth:
  96. resd 1
  97. token_given_back:
  98. resd 1
  99. token_len:
  100. resd 1
  101. token_buf_ptr:
  102. resd 1
  103. buf2_ptr:
  104. resd 1
  105. read_fd:
  106. resd 1
  107. write_label_buf:
  108. resb WRITE_LABEL_BUF_LEN
  109. global get_label_num
  110. get_label_num:
  111. mov eax, label_num
  112. ret
  113. global get_stack_vars
  114. get_stack_vars:
  115. mov eax, stack_vars_ptr
  116. mov eax, [eax]
  117. ret
  118. global get_block_depth
  119. get_block_depth:
  120. mov eax, block_depth
  121. ret
  122. global get_stack_depth
  123. get_stack_depth:
  124. mov eax, stack_depth
  125. ret
  126. global get_temp_depth
  127. get_temp_depth:
  128. mov eax, temp_depth
  129. ret
  130. global get_token_given_back
  131. get_token_given_back:
  132. mov eax, token_given_back
  133. ret
  134. global get_token_len
  135. get_token_len:
  136. mov eax, token_len
  137. ret
  138. global get_token_buf
  139. get_token_buf:
  140. mov eax, token_buf_ptr
  141. mov eax, [eax]
  142. ret
  143. global get_buf2
  144. get_buf2:
  145. mov eax, buf2_ptr
  146. mov eax, [eax]
  147. ret
  148. global get_read_fd
  149. get_read_fd:
  150. mov eax, read_fd
  151. ret
  152. global gen_label
  153. gen_label:
  154. ;; Increment by 1 gen_label and return its original value
  155. mov ecx, label_num
  156. mov eax, [ecx]
  157. mov edx, eax
  158. add edx, 1
  159. mov [ecx], edx
  160. ret
  161. global write_label
  162. write_label:
  163. ;; Call itoa
  164. mov eax, [esp+4]
  165. push eax
  166. call itoa
  167. add esp, 4
  168. mov edx, eax
  169. ;; Print the initial dot
  170. mov eax, write_label_buf
  171. mov BYTE [eax], DOT
  172. ;; Copy from itoa to our buffer
  173. add eax, 1
  174. push edx
  175. push eax
  176. call strcpy
  177. add esp, 8
  178. mov eax, write_label_buf
  179. ret
  180. global get_symbol
  181. get_symbol:
  182. ;; If stage is not 1 and no arity is requested, just return 0
  183. mov eax, stage
  184. cmp DWORD [eax], 1
  185. je get_symbol_find
  186. cmp DWORD [esp+8], 0
  187. jne get_symbol_find
  188. mov eax, 0
  189. ret
  190. get_symbol_find:
  191. ;; Call find_symbol
  192. mov ecx, [esp+8]
  193. mov eax, [esp+4]
  194. push 0
  195. mov edx, esp
  196. push ecx
  197. push edx
  198. push eax
  199. call find_symbol
  200. add esp, 12
  201. ;; Check for validity
  202. cmp eax, 0
  203. je platform_panic
  204. ;; Return the location
  205. pop eax
  206. ret
  207. global is_whitespace
  208. is_whitespace:
  209. ;; Return true only if the argument is a tab, a space or a newline
  210. mov ecx, [esp+4]
  211. cmp cl, SPACE
  212. je is_whitespace_ret_true
  213. cmp cl, TAB
  214. je is_whitespace_ret_true
  215. cmp cl, NEWLINE
  216. je is_whitespace_ret_true
  217. mov eax, 0
  218. ret
  219. is_whitespace_ret_true:
  220. mov eax, 1
  221. ret
  222. global push_var
  223. push_var:
  224. ;; Check the var name length
  225. mov eax, [esp+4]
  226. push eax
  227. call strlen
  228. add esp, 4
  229. cmp eax, 0
  230. jna platform_panic
  231. cmp eax, MAX_SYMBOL_NAME_LEN
  232. jnb platform_panic
  233. ;; Check we are not overflowing the stack
  234. mov eax, stack_depth
  235. mov eax, [eax]
  236. cmp eax, STACK_VARS_LEN
  237. jnb platform_panic
  238. ;; Copy the variable name in the stack
  239. mov edx, MAX_SYMBOL_NAME_LEN
  240. mul edx
  241. mov ecx, stack_vars_ptr
  242. add eax, [ecx]
  243. mov edx, eax
  244. mov eax, [esp+4]
  245. push eax
  246. push edx
  247. call strcpy
  248. add esp, 8
  249. ;; Increment the stack depth
  250. mov eax, stack_depth
  251. add DWORD [eax], 1
  252. ;; If this is a temp var, increment also temp_depth
  253. cmp DWORD [esp+8], 0
  254. je push_var_non_temp
  255. mov eax, temp_depth
  256. add DWORD [eax], 1
  257. ret
  258. ;; If this is not a temp var, check temp_depth is zero
  259. push_var_non_temp:
  260. mov eax, temp_depth
  261. cmp DWORD [eax], 0
  262. jne platform_panic
  263. ret
  264. global pop_var
  265. pop_var:
  266. ;; Check stack depth is positive and decrement it
  267. mov eax, stack_depth
  268. cmp DWORD [eax], 0
  269. jna platform_panic
  270. sub DWORD [eax], 1
  271. ;; If this is a temp var...
  272. cmp DWORD [esp+4], 0
  273. jne pop_var_temp
  274. ret
  275. ;; ...check and decrement temp_depth
  276. pop_var_temp:
  277. mov eax, temp_depth
  278. cmp DWORD [eax], 0
  279. jna platform_panic
  280. sub DWORD [eax], 1
  281. ret
  282. global pop_temps
  283. pop_temps:
  284. ;; Check for termination
  285. mov eax, temp_depth
  286. cmp DWORD [eax], 0
  287. jna pop_temps_ret
  288. ;; Call pop_var
  289. push 1
  290. call pop_var
  291. add esp, 4
  292. jmp pop_temps
  293. pop_temps_ret:
  294. ret
  295. global find_in_stack
  296. find_in_stack:
  297. push ebp
  298. mov ebp, esp
  299. push ebx
  300. mov ebx, 0
  301. find_in_stack_loop:
  302. ;; Check for termination
  303. mov edx, stack_depth
  304. cmp ebx, [edx]
  305. mov eax, 1
  306. je find_in_stack_not_found
  307. ;; Compute the pointer to be checked
  308. mov eax, [edx]
  309. sub eax, 1
  310. sub eax, ebx
  311. mov edx, MAX_SYMBOL_NAME_LEN
  312. mul edx
  313. mov ecx, stack_vars_ptr
  314. add eax, [ecx]
  315. ;; Call strcmp and return if it matches
  316. push eax
  317. push DWORD [ebp+8]
  318. call strcmp
  319. add esp, 8
  320. cmp eax, 0
  321. je find_in_stack_found
  322. ;; Increment index and restart
  323. add ebx, 1
  324. jmp find_in_stack_loop
  325. find_in_stack_not_found:
  326. mov eax, 0xffffffff
  327. jmp find_in_stack_end
  328. find_in_stack_found:
  329. mov eax, ebx
  330. jmp find_in_stack_end
  331. find_in_stack_end:
  332. pop ebx
  333. pop ebp
  334. ret
  335. global get_token
  336. get_token:
  337. ;; If last token was given back, just return it
  338. mov eax, token_given_back
  339. cmp DWORD [eax], 0
  340. je get_token_read
  341. mov DWORD [eax], 0
  342. mov eax, token_buf_ptr
  343. mov eax, [eax]
  344. ret
  345. get_token_read:
  346. push ebx
  347. ;; Reset length and state
  348. mov eax, token_len
  349. mov DWORD [eax], 0
  350. mov ecx, 0
  351. get_token_loop:
  352. ;; Call platform_read_char
  353. push ecx
  354. mov ecx, read_fd
  355. push DWORD [ecx]
  356. call platform_read_char
  357. add esp, 4
  358. ;; Break if -1 was returned
  359. pop ecx
  360. cmp eax, 0xffffffff
  361. je get_token_end
  362. push ecx
  363. ;; Call is_whitespace
  364. push eax
  365. push eax
  366. call is_whitespace
  367. add esp, 4
  368. ;; Store is_whitespace in eax, save_char in dh, read char in dl and
  369. ;; state in ecx
  370. pop edx
  371. mov dh, 0
  372. pop ecx
  373. ;; Branch depending on the state
  374. cmp ecx, 0
  375. je get_token_state0
  376. cmp ecx, 1
  377. je get_token_state1
  378. cmp ecx, 2
  379. je get_token_state2
  380. cmp ecx, 3
  381. je get_token_state3
  382. cmp ecx, 4
  383. je get_token_state4
  384. cmp ecx, 5
  385. je get_token_state5
  386. call platform_panic
  387. ;; Normal program code
  388. get_token_state0:
  389. cmp eax, 0
  390. jne get_token_state0_whitespace
  391. cmp dl, POUND
  392. je get_token_state0_pound
  393. mov dh, 1
  394. cmp dl, QUOTE
  395. je get_token_state0_quote
  396. cmp dl, APEX
  397. je get_token_state0_apex
  398. jmp get_token_loop_end
  399. get_token_state0_whitespace:
  400. mov eax, token_len
  401. cmp DWORD [eax], 0
  402. ja get_token_end
  403. jmp get_token_loop_end
  404. get_token_state0_pound:
  405. mov ecx, 1
  406. jmp get_token_loop_end
  407. get_token_state0_quote:
  408. mov ecx, 2
  409. jmp get_token_loop_end
  410. get_token_state0_apex:
  411. mov ecx, 4
  412. jmp get_token_loop_end
  413. ;; Comments
  414. get_token_state1:
  415. cmp dl, NEWLINE
  416. jne get_token_loop_end
  417. mov ecx, 0
  418. mov eax, token_len
  419. cmp DWORD [eax], 0
  420. ja get_token_end
  421. jmp get_token_loop_end
  422. ;; String
  423. get_token_state2:
  424. mov dh, 1
  425. cmp dl, QUOTE
  426. je get_token_state2_quote
  427. cmp dl, BACKSLASH
  428. je get_token_state2_backslash
  429. jmp get_token_loop_end
  430. get_token_state2_quote:
  431. mov ecx, 0
  432. jmp get_token_loop_end
  433. get_token_state2_backslash:
  434. mov ecx, 3
  435. jmp get_token_loop_end
  436. ;; Escape character in a string
  437. get_token_state3:
  438. mov ecx, 2
  439. mov dh, 1
  440. jmp get_token_loop_end
  441. ;; Character
  442. get_token_state4:
  443. mov dh, 1
  444. cmp dl, APEX
  445. je get_token_state4_quote
  446. cmp dl, BACKSLASH
  447. je get_token_state4_backslash
  448. jmp get_token_loop_end
  449. get_token_state4_quote:
  450. mov ecx, 0
  451. jmp get_token_loop_end
  452. get_token_state4_backslash:
  453. mov ecx, 5
  454. jmp get_token_loop_end
  455. ;; Escape character in a character
  456. get_token_state5:
  457. mov ecx, 4
  458. mov dh, 1
  459. jmp get_token_loop_end
  460. get_token_loop_end:
  461. ;; If save_char is true, save the char and increment length
  462. cmp dh, 0
  463. je get_token_loop
  464. mov ebx, token_len
  465. mov ebx, [ebx]
  466. mov eax, token_buf_ptr
  467. mov eax, [eax]
  468. add eax, ebx
  469. mov [eax], dl
  470. add ebx, 1
  471. mov eax, token_len
  472. mov [eax], ebx
  473. jmp get_token_loop
  474. get_token_end:
  475. ;; Write the terminator and return
  476. mov eax, token_buf_ptr
  477. mov eax, [eax]
  478. mov ecx, token_len
  479. mov ecx, [ecx]
  480. add ecx, eax
  481. mov BYTE [ecx], 0
  482. ;; ;; Log token
  483. ;; push eax
  484. ;; push eax
  485. ;; push 1
  486. ;; call platform_log
  487. ;; add esp, 8
  488. ;; push 32
  489. ;; push 1
  490. ;; call platform_write_char
  491. ;; add esp, 8
  492. ;; pop eax
  493. pop ebx
  494. ret
  495. global give_back_token
  496. give_back_token:
  497. ;; Check another token was not already given back
  498. mov eax, token_given_back
  499. cmp DWORD [eax], 0
  500. jne platform_panic
  501. ;; Mark the current one as given back
  502. mov DWORD [eax], 1
  503. ret
  504. global escaped
  505. escaped:
  506. mov edx, [esp+4]
  507. mov eax, 0
  508. mov al, NEWLINE
  509. cmp dl, LITTLEN
  510. je escaped_ret
  511. mov al, TAB
  512. cmp dl, LITTLET
  513. je escaped_ret
  514. mov al, FEED
  515. cmp dl, LITTLEF
  516. je escaped_ret
  517. mov al, RETURN
  518. cmp dl, LITTLER
  519. je escaped_ret
  520. mov al, VERTTAB
  521. cmp dl, LITTLEV
  522. je escaped_ret
  523. mov al, 0
  524. cmp dl, ZERO
  525. je escaped_ret
  526. mov al, BACKSLASH
  527. cmp dl, BACKSLASH
  528. je escaped_ret
  529. mov al, APEX
  530. cmp dl, APEX
  531. je escaped_ret
  532. mov al, QUOTE
  533. cmp dl, QUOTE
  534. je escaped_ret
  535. mov eax, 0
  536. escaped_ret:
  537. ret
  538. global emit_escaped_string
  539. emit_escaped_string:
  540. ;; Check the string beings with a quote
  541. mov eax, [esp+4]
  542. cmp BYTE [eax], QUOTE
  543. jne platform_panic
  544. add eax, 1
  545. emit_escaped_string_loop:
  546. ;; Check we did not find the terminator (without a closing quote)
  547. cmp BYTE [eax], 0
  548. je platform_panic
  549. ;; If we found a quote, jump to end
  550. cmp BYTE [eax], QUOTE
  551. je emit_escaped_string_end
  552. ;; If we found a backslash, jump to the following character and
  553. ;; escape it
  554. mov edx, 0
  555. mov dl, [eax]
  556. cmp dl, BACKSLASH
  557. jne emit_escaped_string_emit
  558. add eax, 1
  559. mov dl, [eax]
  560. push eax
  561. push edx
  562. call escaped
  563. add esp, 4
  564. mov edx, eax
  565. pop eax
  566. emit_escaped_string_emit:
  567. ;; Call emit
  568. push eax
  569. push edx
  570. call emit
  571. add esp, 4
  572. ;; Increment the pointer
  573. pop eax
  574. add eax, 1
  575. jmp emit_escaped_string_loop
  576. emit_escaped_string_end:
  577. ;; Check a terminator follows and then return
  578. cmp BYTE [eax+1], 0
  579. jne platform_panic
  580. ret
  581. global decode_number_or_char
  582. decode_number_or_char:
  583. ;; The first argument does not begin with an apex, call
  584. ;; decode_number
  585. mov eax, [esp+4]
  586. cmp BYTE [eax], APEX
  587. je decode_number_or_char_char
  588. mov ecx, [esp+8]
  589. push ecx
  590. push eax
  591. call decode_number
  592. add esp, 8
  593. ret
  594. decode_number_or_char_char:
  595. ;; If second char is not a backslash, just return it
  596. cmp BYTE [eax+1], BACKSLASH
  597. je decode_number_or_char_backslash
  598. mov ecx, [esp+8]
  599. mov edx, 0
  600. mov dl, [eax+1]
  601. mov [ecx], edx
  602. ;; Check that the input string finishes here
  603. cmp BYTE [eax+2], APEX
  604. jne platform_panic
  605. cmp BYTE [eax+3], 0
  606. jne platform_panic
  607. mov eax, 1
  608. ret
  609. decode_number_or_char_backslash:
  610. ;; Call escaped
  611. push eax
  612. mov edx, 0
  613. mov dl, BYTE [eax+2]
  614. push edx
  615. call escaped
  616. add esp, 4
  617. ;; Return what escaped returned
  618. mov edx, eax
  619. pop eax
  620. mov ecx, [esp+8]
  621. mov [ecx], edx
  622. ;; Check that the input string finishes here
  623. cmp BYTE [eax+3], APEX
  624. jne platform_panic
  625. cmp BYTE [eax+4], 0
  626. jne platform_panic
  627. mov eax, 1
  628. ret
  629. global compute_rel
  630. compute_rel:
  631. ;; Subtract current_loc and than 4
  632. mov eax, [esp+4]
  633. mov ecx, current_loc
  634. sub eax, [ecx]
  635. sub eax, 4
  636. ret
  637. global push_expr
  638. push_expr:
  639. push ebp
  640. mov ebp, esp
  641. push ebx
  642. push esi
  643. ;; Try to interpret argument as number
  644. push 0
  645. mov edx, esp
  646. push edx
  647. push DWORD [ebp+8]
  648. call decode_number_or_char
  649. add esp, 8
  650. pop ebx
  651. cmp eax, 0
  652. je push_expr_stack
  653. ;; It is a number, check that we do not want the address
  654. cmp DWORD [ebp+12], 0
  655. jne platform_panic
  656. ;; Emit the code
  657. push 1
  658. push TEMP_VAR
  659. call push_var
  660. add esp, 8
  661. push 0x68
  662. call emit
  663. add esp, 4
  664. push ebx
  665. call emit32
  666. add esp, 4
  667. jmp push_expr_ret
  668. push_expr_stack:
  669. ;; Call find_in_stack
  670. push DWORD [ebp+8]
  671. call find_in_stack
  672. add esp, 4
  673. cmp eax, 0xffffffff
  674. je push_expr_symbol
  675. ;; Multiply the position by 4
  676. mov edx, 4
  677. mul edx
  678. mov ebx, eax
  679. ;; It is on the stack: check if we want the address or not
  680. cmp DWORD [ebp+12], 0
  681. jne push_expr_stack_addr
  682. ;; We want the value, emit the code
  683. push 1
  684. push TEMP_VAR
  685. call push_var
  686. add esp, 8
  687. push 3
  688. push push_esp_pos
  689. call emit_str
  690. add esp, 8
  691. push ebx
  692. call emit32
  693. add esp, 4
  694. jmp push_expr_ret
  695. push_expr_stack_addr:
  696. ;; We want the address, emit the code
  697. push 1
  698. push TEMP_VAR
  699. call push_var
  700. add esp, 8
  701. push 3
  702. push lea_eax_esp_pos
  703. call emit_str
  704. add esp, 8
  705. push ebx
  706. call emit32
  707. add esp, 4
  708. push 0x50
  709. call emit
  710. add esp, 4
  711. jmp push_expr_ret
  712. push_expr_symbol:
  713. ;; Get symbol data
  714. push 0
  715. mov edx, esp
  716. push edx
  717. push DWORD [ebp+8]
  718. call get_symbol
  719. add esp, 8
  720. mov ebx, eax
  721. pop edx
  722. ;; If arity is -2, check we do not want the address
  723. cmp edx, 0xfffffffe
  724. jne push_expr_after_assert
  725. cmp DWORD [ebp+12], 0
  726. jne platform_panic
  727. push_expr_after_assert:
  728. ;; Check if we want the address or arity is -2
  729. cmp edx, 0xfffffffe
  730. je push_expr_addr
  731. cmp DWORD [ebp+12], 0
  732. jne push_expr_addr
  733. ;; Check if arity is -1
  734. cmp edx, 0xffffffff
  735. je push_expr_val
  736. mov esi, edx
  737. ;; This is a real function call, emit the code (part 1)
  738. push 0xe8
  739. call emit
  740. add esp, 4
  741. push ebx
  742. call compute_rel
  743. add esp, 4
  744. push eax
  745. call emit32
  746. add esp, 4
  747. push 2
  748. push add_esp
  749. call emit_str
  750. add esp, 8
  751. ;; Multiply the arity by 4 and continue emitting code
  752. mov eax, esi
  753. mov edx, 4
  754. mul edx
  755. push eax
  756. call emit32
  757. add esp, 4
  758. push 0x50
  759. call emit
  760. add esp, 4
  761. ;; Update stack variables
  762. push_expr_symbol_loop:
  763. ;; Check for termination
  764. cmp esi, 0
  765. je push_expr_symbol_loop_end
  766. ;; Call pop_var
  767. push 1
  768. call pop_var
  769. add esp, 4
  770. ;; Decrement arity and reloop
  771. sub esi, 1
  772. jmp push_expr_symbol_loop
  773. push_expr_symbol_loop_end:
  774. push 1
  775. push TEMP_VAR
  776. call push_var
  777. add esp, 8
  778. jmp push_expr_ret
  779. push_expr_addr:
  780. ;; We want the address, emit the code
  781. push 1
  782. push TEMP_VAR
  783. call push_var
  784. add esp, 8
  785. push 0x68
  786. call emit
  787. add esp, 4
  788. push ebx
  789. call emit32
  790. add esp, 4
  791. jmp push_expr_ret
  792. push_expr_val:
  793. ;; We want the value, emit the code
  794. push 1
  795. push TEMP_VAR
  796. call push_var
  797. add esp, 8
  798. push 0xb8
  799. call emit
  800. add esp, 4
  801. push ebx
  802. call emit32
  803. add esp, 4
  804. push 2
  805. push push_peax
  806. call emit_str
  807. add esp, 8
  808. jmp push_expr_ret
  809. push_expr_ret:
  810. pop esi
  811. pop ebx
  812. pop ebp
  813. ret
  814. global push_expr_until_brace
  815. push_expr_until_brace:
  816. push ebx
  817. push esi
  818. push edi
  819. push_expr_until_brace_loop:
  820. ;; Get a token
  821. call get_token
  822. mov ebx, eax
  823. ;; If it is an open brace, exit loop
  824. push eax
  825. push str_cu_open
  826. call strcmp
  827. add esp, 8
  828. cmp eax, 0
  829. je push_expr_until_brace_end
  830. ;; If not, branch depending on whether it is a string or not
  831. cmp BYTE [ebx], QUOTE
  832. je push_expr_until_brace_string
  833. jmp push_expr_until_brace_push
  834. push_expr_until_brace_string:
  835. ;; Generate a jump (in esi) and a string (in edi) label
  836. call gen_label
  837. mov esi, eax
  838. call gen_label
  839. mov edi, eax
  840. ;; Emit code to jump to the jump label
  841. push 0xe9
  842. call emit
  843. add esp, 4
  844. push 0
  845. push esi
  846. call write_label
  847. add esp, 4
  848. push eax
  849. call get_symbol
  850. add esp, 8
  851. push eax
  852. call compute_rel
  853. add esp, 4
  854. push eax
  855. call emit32
  856. add esp, 4
  857. ;; Add a symbol for the string label
  858. push 0xffffffff
  859. mov eax, current_loc
  860. push DWORD [eax]
  861. push edi
  862. call write_label
  863. add esp, 4
  864. push eax
  865. call add_symbol_wrapper
  866. add esp, 12
  867. ;; Emit escaped string and a terminator
  868. push ebx
  869. call emit_escaped_string
  870. add esp, 4
  871. push 0
  872. call emit
  873. add esp, 4
  874. ;; Add a symbol for the jump label
  875. push 0xffffffff
  876. mov eax, current_loc
  877. push DWORD [eax]
  878. push esi
  879. call write_label
  880. add esp, 4
  881. push eax
  882. call add_symbol_wrapper
  883. add esp, 12
  884. ;; Emit code to push the string label
  885. push 1
  886. push TEMP_VAR
  887. call push_var
  888. add esp, 8
  889. push 0x68
  890. call emit
  891. add esp, 4
  892. push 0
  893. push edi
  894. call write_label
  895. add esp, 4
  896. push eax
  897. call get_symbol
  898. add esp, 8
  899. push eax
  900. call emit32
  901. add esp, 4
  902. jmp push_expr_until_brace_loop
  903. push_expr_until_brace_push:
  904. ;; Check if we want the address
  905. mov esi, 0
  906. cmp BYTE [ebx], AT_SIGN
  907. jne push_expr_until_brace_push_after_if
  908. mov esi, 1
  909. add ebx, 1
  910. push_expr_until_brace_push_after_if:
  911. ;; Call push_expr
  912. push esi
  913. push ebx
  914. call push_expr
  915. add esp, 8
  916. jmp push_expr_until_brace_loop
  917. push_expr_until_brace_end:
  918. ;; Given the token back
  919. call give_back_token
  920. ;; Check that temp depth is positive
  921. mov eax, temp_depth
  922. cmp DWORD [eax], 0
  923. jna platform_panic
  924. pop edi
  925. pop esi
  926. pop ebx
  927. ret
  928. global parse_block
  929. parse_block:
  930. push ebp
  931. mov ebp, esp
  932. sub esp, 4
  933. push ebx
  934. push esi
  935. push edi
  936. ;; Increment block depth
  937. mov eax, block_depth
  938. add DWORD [eax], 1
  939. ;; Save stack depth
  940. mov eax, stack_depth
  941. mov eax, [eax]
  942. mov [ebp+0xfffffffc], eax
  943. ;; Expect and discard an open curly brace token
  944. call get_token
  945. push eax
  946. push str_cu_open
  947. call strcmp
  948. add esp, 8
  949. cmp eax, 0
  950. jne platform_panic
  951. ;; Main parsing loop
  952. parse_block_loop:
  953. ;; Receive a token and save it in ebx
  954. call get_token
  955. mov ebx, eax
  956. ;; Ensure it is not empty (meaning EOF)
  957. cmp BYTE [ebx], 0
  958. je platform_panic
  959. ;; If it is a closed curly brace, then break
  960. push ebx
  961. push str_cu_closed
  962. call strcmp
  963. add esp, 8
  964. cmp eax, 0
  965. je parse_block_break
  966. ;; Jump to the appropriate handler
  967. push ebx
  968. push str_semicolon
  969. call strcmp
  970. add esp, 8
  971. cmp eax, 0
  972. je parse_block_semicolon
  973. push ebx
  974. push str_ret
  975. call strcmp
  976. add esp, 8
  977. cmp eax, 0
  978. je parse_block_ret
  979. push ebx
  980. push str_if
  981. call strcmp
  982. add esp, 8
  983. cmp eax, 0
  984. je parse_block_if
  985. push ebx
  986. push str_while
  987. call strcmp
  988. add esp, 8
  989. cmp eax, 0
  990. je parse_block_while
  991. cmp BYTE [ebx], DOLLAR
  992. je parse_block_alloc
  993. cmp BYTE [ebx], BACKSLASH
  994. je parse_block_call
  995. cmp BYTE [ebx], QUOTE
  996. je parse_block_string
  997. jmp parse_block_push
  998. parse_block_semicolon:
  999. ;; Emit code to rewind temp stack
  1000. push 2
  1001. push add_esp
  1002. call emit_str
  1003. add esp, 8
  1004. mov eax, temp_depth
  1005. mov eax, [eax]
  1006. mov edx, 4
  1007. mul edx
  1008. push eax
  1009. call emit32
  1010. add esp, 4
  1011. call pop_temps
  1012. jmp parse_block_loop
  1013. parse_block_ret:
  1014. ;; If there are temp vars, emit code to pop one
  1015. mov eax, temp_depth
  1016. cmp DWORD [eax], 0
  1017. jna parse_block_ret_emit
  1018. push 0x58
  1019. call emit
  1020. add esp, 4
  1021. push 1
  1022. call pop_var
  1023. add esp, 4
  1024. parse_block_ret_emit:
  1025. ;; Emit code to unwind stack end return
  1026. push 2
  1027. push add_esp
  1028. call emit_str
  1029. add esp, 8
  1030. mov eax, stack_depth
  1031. mov eax, [eax]
  1032. mov edx, 4
  1033. mul edx
  1034. push eax
  1035. call emit32
  1036. add esp, 4
  1037. push 2
  1038. push pop_ebp_ret
  1039. call emit_str
  1040. add esp, 8
  1041. jmp parse_block_loop
  1042. parse_block_if:
  1043. ;; Call push_expr_until_brace
  1044. call push_expr_until_brace
  1045. ;; Generate the else label
  1046. call gen_label
  1047. mov ebx, eax
  1048. ;; Emit code to pop and possibly jump to else label
  1049. push 1
  1050. call pop_var
  1051. add esp, 4
  1052. push 6
  1053. push pop_eax_cmp_eax_0_je_rel
  1054. call emit_str
  1055. add esp, 8
  1056. push 0
  1057. push ebx
  1058. call write_label
  1059. add esp, 4
  1060. push eax
  1061. call get_symbol
  1062. add esp, 8
  1063. push eax
  1064. call compute_rel
  1065. add esp, 4
  1066. push eax
  1067. call emit32
  1068. add esp, 4
  1069. ;; Recursively parse the inner block
  1070. call parse_block
  1071. ;; Get another token and check if it is an else
  1072. call get_token
  1073. push eax
  1074. push str_else
  1075. call strcmp
  1076. add esp, 8
  1077. cmp eax, 0
  1078. je parse_block_else
  1079. ;; Not an else: add a symbol for the else label
  1080. push 0xffffffff
  1081. mov eax, current_loc
  1082. push DWORD [eax]
  1083. push ebx
  1084. call write_label
  1085. add esp, 4
  1086. push eax
  1087. call add_symbol_wrapper
  1088. add esp, 12
  1089. ;; Give the token back
  1090. call give_back_token
  1091. jmp parse_block_loop
  1092. parse_block_else:
  1093. ;; There is an else: generate the fi label (load in edi)
  1094. call gen_label
  1095. mov edi, eax
  1096. ;; Emit code to jump to fi
  1097. push 0xe9
  1098. call emit
  1099. add esp, 4
  1100. push 0
  1101. push edi
  1102. call write_label
  1103. add esp, 4
  1104. push eax
  1105. call get_symbol
  1106. add esp, 8
  1107. push eax
  1108. call compute_rel
  1109. add esp, 4
  1110. push eax
  1111. call emit32
  1112. add esp, 4
  1113. ;; Add the symbol for the else label
  1114. push 0xffffffff
  1115. mov eax, current_loc
  1116. push DWORD [eax]
  1117. push ebx
  1118. call write_label
  1119. add esp, 4
  1120. push eax
  1121. call add_symbol_wrapper
  1122. add esp, 12
  1123. ;; Recursively parse the inner block
  1124. call parse_block
  1125. ;; Add the symbol for the fi label
  1126. push 0xffffffff
  1127. mov eax, current_loc
  1128. push DWORD [eax]
  1129. push edi
  1130. call write_label
  1131. add esp, 4
  1132. push eax
  1133. call add_symbol_wrapper
  1134. add esp, 12
  1135. jmp parse_block_loop
  1136. parse_block_while:
  1137. ;; Generate the restart label (in esi) and the end label (in edi)
  1138. call gen_label
  1139. mov esi, eax
  1140. call gen_label
  1141. mov edi, eax
  1142. ;; Add a symbol for the restart label
  1143. push 0xffffffff
  1144. mov eax, current_loc
  1145. push DWORD [eax]
  1146. push esi
  1147. call write_label
  1148. add esp, 4
  1149. push eax
  1150. call add_symbol_wrapper
  1151. add esp, 12
  1152. ;; Call push_expr_until_brace
  1153. call push_expr_until_brace
  1154. ;; Emit code to pop and possibly jump to end label
  1155. push 1
  1156. call pop_var
  1157. add esp, 4
  1158. push 6
  1159. push pop_eax_cmp_eax_0_je_rel
  1160. call emit_str
  1161. add esp, 8
  1162. push 0
  1163. push edi
  1164. call write_label
  1165. add esp, 4
  1166. push eax
  1167. call get_symbol
  1168. add esp, 8
  1169. push eax
  1170. call compute_rel
  1171. add esp, 4
  1172. push eax
  1173. call emit32
  1174. add esp, 4
  1175. ;; Recursively parse the inner block
  1176. call parse_block
  1177. ;; Emit code to restart the loop
  1178. push 0xe9
  1179. call emit
  1180. add esp, 4
  1181. push 0
  1182. push esi
  1183. call write_label
  1184. add esp, 4
  1185. push eax
  1186. call get_symbol
  1187. add esp, 8
  1188. push eax
  1189. call compute_rel
  1190. add esp, 4
  1191. push eax
  1192. call emit32
  1193. add esp, 4
  1194. ;; Add a symbol for the end label
  1195. push 0xffffffff
  1196. mov eax, current_loc
  1197. push DWORD [eax]
  1198. push edi
  1199. call write_label
  1200. add esp, 4
  1201. push eax
  1202. call add_symbol_wrapper
  1203. add esp, 12
  1204. jmp parse_block_loop
  1205. parse_block_alloc:
  1206. ;; Skip to following char and check it is not a terminator
  1207. add ebx, 1
  1208. cmp BYTE [ebx], 0
  1209. je platform_panic
  1210. ;; Call push_var
  1211. push 0
  1212. push ebx
  1213. call push_var
  1214. add esp, 8
  1215. ;; Emit code
  1216. push 3
  1217. push sub_esp_4
  1218. call emit_str
  1219. add esp, 8
  1220. jmp parse_block_loop
  1221. parse_block_call:
  1222. ;; Skip to following char and check it is not a terminator
  1223. add ebx, 1
  1224. cmp BYTE [ebx], 0
  1225. je platform_panic
  1226. ;; Call decode_number_or_symbol
  1227. push ebx
  1228. call decode_number_or_symbol
  1229. add esp, 4
  1230. mov ebx, eax
  1231. ;; Call pop_var
  1232. push 1
  1233. call pop_var
  1234. add esp, 4
  1235. ;; Emit code to do the indirect call
  1236. push 3
  1237. push pop_eax_call_eax
  1238. call emit_str
  1239. add esp, 8
  1240. ;; Emit code for stack cleanup
  1241. push 2
  1242. push add_esp
  1243. call emit_str
  1244. add esp, 8
  1245. mov eax, 4
  1246. mul ebx
  1247. push eax
  1248. call emit32
  1249. add esp, 4
  1250. ;; Pop an appropriate number of temp vars
  1251. parse_block_call_loop:
  1252. ;; Check for termination
  1253. cmp ebx, 0
  1254. je parse_block_call_end
  1255. ;; Pop a var
  1256. push 1
  1257. call pop_var
  1258. add esp, 4
  1259. ;; Decrement counter and reloop
  1260. sub ebx, 1
  1261. jmp parse_block_call_loop
  1262. parse_block_call_end:
  1263. ;; Emit code to push the return value
  1264. push 1
  1265. push TEMP_VAR
  1266. call push_var
  1267. add esp, 8
  1268. push 0x50
  1269. call emit
  1270. add esp, 4
  1271. jmp parse_block_loop
  1272. parse_block_string:
  1273. ;; Generate a jump (in esi) and a string (in edi) label
  1274. call gen_label
  1275. mov esi, eax
  1276. call gen_label
  1277. mov edi, eax
  1278. ;; Emit code to jump to the jump label
  1279. push 0xe9
  1280. call emit
  1281. add esp, 4
  1282. push 0
  1283. push esi
  1284. call write_label
  1285. add esp, 4
  1286. push eax
  1287. call get_symbol
  1288. add esp, 8
  1289. push eax
  1290. call compute_rel
  1291. add esp, 4
  1292. push eax
  1293. call emit32
  1294. add esp, 4
  1295. ;; Add a symbol for the string label
  1296. push 0xffffffff
  1297. mov eax, current_loc
  1298. push DWORD [eax]
  1299. push edi
  1300. call write_label
  1301. add esp, 4
  1302. push eax
  1303. call add_symbol_wrapper
  1304. add esp, 12
  1305. ;; Emit escaped string and a terminator
  1306. push ebx
  1307. call emit_escaped_string
  1308. add esp, 4
  1309. push 0
  1310. call emit
  1311. add esp, 4
  1312. ;; Add a symbol for the jump label
  1313. push 0xffffffff
  1314. mov eax, current_loc
  1315. push DWORD [eax]
  1316. push esi
  1317. call write_label
  1318. add esp, 4
  1319. push eax
  1320. call add_symbol_wrapper
  1321. add esp, 12
  1322. ;; Emit code to push the string label
  1323. push 1
  1324. push TEMP_VAR
  1325. call push_var
  1326. add esp, 8
  1327. push 0x68
  1328. call emit
  1329. add esp, 4
  1330. push 0
  1331. push edi
  1332. call write_label
  1333. add esp, 4
  1334. push eax
  1335. call get_symbol
  1336. add esp, 8
  1337. push eax
  1338. call emit32
  1339. add esp, 4
  1340. jmp parse_block_loop
  1341. parse_block_push:
  1342. ;; Check if we want the address
  1343. mov esi, 0
  1344. cmp BYTE [ebx], AT_SIGN
  1345. jne parse_block_push_after_if
  1346. mov esi, 1
  1347. add ebx, 1
  1348. parse_block_push_after_if:
  1349. ;; Call push_expr
  1350. push esi
  1351. push ebx
  1352. call push_expr
  1353. add esp, 8
  1354. jmp parse_block_loop
  1355. parse_block_break:
  1356. ;; Emit stack unwinding code
  1357. push 2
  1358. push add_esp
  1359. call emit_str
  1360. add esp, 8
  1361. ;; Sanity check: stack depth must not have increased
  1362. mov eax, stack_depth
  1363. mov eax, [eax]
  1364. mov esi, [ebp+0xfffffffc]
  1365. cmp eax, esi
  1366. jnge platform_panic
  1367. ;; Emit stack depth different, multiplied by 4
  1368. sub eax, esi
  1369. mov edx, 4
  1370. mul edx
  1371. push eax
  1372. call emit32
  1373. add esp, 4
  1374. ;; Reset stack depth to saved value and decrease block depth
  1375. mov eax, stack_depth
  1376. mov [eax], esi
  1377. mov eax, block_depth
  1378. sub DWORD [eax], 1
  1379. pop edi
  1380. pop esi
  1381. pop ebx
  1382. add esp, 4
  1383. pop ebp
  1384. ret
  1385. global decode_number_or_symbol
  1386. decode_number_or_symbol:
  1387. ;; Call decode_number_or_char
  1388. mov eax, [esp+4]
  1389. push 0
  1390. mov edx, esp
  1391. push edx
  1392. push eax
  1393. call decode_number_or_char
  1394. add esp, 8
  1395. pop edx
  1396. ;; If it returned true, return
  1397. cmp eax, 0
  1398. je decode_number_or_symbol_symbol
  1399. mov eax, edx
  1400. ret
  1401. decode_number_or_symbol_symbol:
  1402. ;; Call get_symbol and return
  1403. mov eax, [esp+4]
  1404. push 0
  1405. mov edx, esp
  1406. push edx
  1407. push eax
  1408. call get_symbol
  1409. add esp, 8
  1410. add esp, 4
  1411. ret
  1412. global parse
  1413. parse:
  1414. push ebp
  1415. mov ebp, esp
  1416. push ebx
  1417. ;; Main loop
  1418. parse_loop:
  1419. ;; Get a token and break if it is empty
  1420. call get_token
  1421. mov ebx, eax
  1422. cmp BYTE [ebx], 0
  1423. je parse_ret
  1424. ;; Jump to the appropriate handler
  1425. push ebx
  1426. push str_fun
  1427. call strcmp
  1428. add esp, 8
  1429. cmp eax, 0
  1430. je parse_fun
  1431. push ebx
  1432. push str_ifun
  1433. call strcmp
  1434. add esp, 8
  1435. cmp eax, 0
  1436. je parse_ifun
  1437. push ebx
  1438. push str_const
  1439. call strcmp
  1440. add esp, 8
  1441. cmp eax, 0
  1442. je parse_const
  1443. cmp BYTE [ebx], DOLLAR
  1444. je parse_var
  1445. cmp BYTE [ebx], PERCENT
  1446. je parse_array
  1447. call platform_panic
  1448. parse_fun:
  1449. ;; Get a token and copy it in buf2 (pointed by ebx)
  1450. mov eax, buf2_ptr
  1451. mov ebx, [eax]
  1452. call get_token
  1453. push eax
  1454. push ebx
  1455. call strcpy
  1456. add esp, 8
  1457. ;; Get another token and convert it to an integer
  1458. call get_token
  1459. push eax
  1460. call atoi
  1461. add esp, 4
  1462. ;; Add a symbol for the function
  1463. push eax
  1464. mov eax, current_loc
  1465. push DWORD [eax]
  1466. push ebx
  1467. call fix_symbol_placeholder
  1468. add esp, 12
  1469. ;; Emit the prologue
  1470. push 3
  1471. push push_ebp_mov_ebp_esp
  1472. call emit_str
  1473. add esp, 8
  1474. ;; Parse the block
  1475. call parse_block
  1476. ;; Emit the epilogue
  1477. push 2
  1478. push pop_ebp_ret
  1479. call emit_str
  1480. add esp, 8
  1481. jmp parse_loop
  1482. parse_ifun:
  1483. ;; Get a token and copy it in buf2 (pointed by ebx)
  1484. mov eax, buf2_ptr
  1485. mov ebx, [eax]
  1486. call get_token
  1487. push eax
  1488. push ebx
  1489. call strcpy
  1490. add esp, 8
  1491. ;; Get another token and convert it to an integer
  1492. call get_token
  1493. push eax
  1494. call atoi
  1495. add esp, 4
  1496. ;; Add a symbol placeholder for the function
  1497. push eax
  1498. push ebx
  1499. call add_symbol_placeholder
  1500. add esp, 8
  1501. jmp parse_loop
  1502. parse_const:
  1503. ;; Get a token and copy it in buf2 (pointed by ebx)
  1504. mov eax, buf2_ptr
  1505. mov ebx, [eax]
  1506. call get_token
  1507. push eax
  1508. push ebx
  1509. call strcpy
  1510. add esp, 8
  1511. ;; Get another token and interpret it as a number or symbol
  1512. call get_token
  1513. push eax
  1514. call decode_number_or_symbol
  1515. add esp, 4
  1516. ;; Add a symbol
  1517. push 0xfffffffe
  1518. push eax
  1519. push ebx
  1520. call add_symbol_wrapper
  1521. add esp, 12
  1522. jmp parse_loop
  1523. parse_var:
  1524. ;; Increment the pointer and check the string continues
  1525. add ebx, 1
  1526. cmp BYTE [ebx], 0
  1527. je platform_panic
  1528. ;; Add a symbol
  1529. push 0xffffffff
  1530. mov eax, current_loc
  1531. push DWORD [eax]
  1532. push ebx
  1533. call add_symbol_wrapper
  1534. add esp, 12
  1535. ;; Emit a zero to allocate space for the variable
  1536. push 0
  1537. call emit32
  1538. add esp, 4
  1539. jmp parse_loop
  1540. parse_array:
  1541. ;; Increment the pointer and check the string continues
  1542. add ebx, 1
  1543. cmp BYTE [ebx], 0
  1544. je platform_panic
  1545. ;; Add a symbol
  1546. push 0xfffffffe
  1547. mov eax, current_loc
  1548. push DWORD [eax]
  1549. push ebx
  1550. call add_symbol_wrapper
  1551. add esp, 12
  1552. ;; Get another token and interpret it as a number or symbol
  1553. call get_token
  1554. push eax
  1555. call decode_number_or_symbol
  1556. add esp, 4
  1557. mov ebx, eax
  1558. ;; Emit that number of zero bytes to allocate the array
  1559. parse_array_loop:
  1560. ;; Check for termination
  1561. cmp ebx, 0
  1562. je parse_loop
  1563. ;; Decrement counter
  1564. sub ebx, 1
  1565. ;; Emit a zero byte
  1566. push 0
  1567. call emit
  1568. add esp, 4
  1569. jmp parse_array_loop
  1570. parse_ret:
  1571. pop ebx
  1572. pop ebp
  1573. ret
  1574. global init_g_compiler
  1575. init_g_compiler:
  1576. ;; Allocate stack variables list
  1577. push STACK_VARS_SIZE
  1578. call platform_allocate
  1579. add esp, 4
  1580. mov ecx, stack_vars_ptr
  1581. mov [ecx], eax
  1582. ;; Allocate the token buffer
  1583. push MAX_SYMBOL_NAME_LEN
  1584. call platform_allocate
  1585. add esp, 4
  1586. mov ecx, token_buf_ptr
  1587. mov [ecx], eax
  1588. ;; Allocate buf2
  1589. push MAX_SYMBOL_NAME_LEN
  1590. call platform_allocate
  1591. add esp, 4
  1592. mov ecx, buf2_ptr
  1593. mov [ecx], eax
  1594. ;; Set token_given_back to false
  1595. mov eax, token_given_back
  1596. mov DWORD [eax], 0
  1597. ret
  1598. global compile
  1599. compile:
  1600. ;; Set emit_fd and read_fd
  1601. mov eax, emit_fd
  1602. mov ecx, [esp+8]
  1603. mov [eax], ecx
  1604. mov eax, read_fd
  1605. mov ecx, [esp+4]
  1606. mov [eax], ecx
  1607. ;; Reset depths
  1608. mov eax, block_depth
  1609. mov DWORD [eax], 0
  1610. mov eax, stack_depth
  1611. mov DWORD [eax], 0
  1612. mov eax, temp_depth
  1613. mov DWORD [eax], 0
  1614. ;; Reset stage
  1615. mov eax, stage
  1616. mov DWORD [eax], 0
  1617. compile_stage_loop:
  1618. ;; Check for termination
  1619. mov eax, stage
  1620. cmp DWORD [eax], 2
  1621. je compile_end
  1622. ;; Call platform_reset_file
  1623. mov eax, [esp+4]
  1624. push eax
  1625. call platform_reset_file
  1626. add esp, 4
  1627. ;; Reset label_num and current_loc
  1628. mov eax, label_num
  1629. mov DWORD [eax], 0
  1630. mov eax, current_loc
  1631. mov ecx, [esp+12]
  1632. mov [eax], ecx
  1633. ;; If the preable was requested, emit it
  1634. cmp DWORD [esp+16], 0
  1635. je compile_parse
  1636. compile_parse:
  1637. ;; Call parse
  1638. call parse
  1639. ;; Check that depths were reset to zero
  1640. mov eax, block_depth
  1641. cmp DWORD [eax], 0
  1642. jne platform_panic
  1643. mov eax, stack_depth
  1644. cmp DWORD [eax], 0
  1645. jne platform_panic
  1646. mov eax, temp_depth
  1647. cmp DWORD [eax], 0
  1648. jne platform_panic
  1649. ;; Increment stage
  1650. mov eax, stage
  1651. add DWORD [eax], 1
  1652. jmp compile_stage_loop
  1653. compile_end:
  1654. ret