Linux x86_64 implementation of libglitch : https://github.com/erlehmann/libglitch.git
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

yaglitch.asm 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. ; yaglitch : Yet Another Glitch
  2. ; Copyright (C) 2018 Weber Yann
  3. ;
  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. ; any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;
  17. [bits 64]
  18. %include "sdl.asm"
  19. %include "utils.asm"
  20. %define STACK_SZ 256
  21. %define MAX_FILE_SZ (16 * 17) ; 16 lines of 16 chars + newline chr
  22. %define NL "!"
  23. section .data
  24. op_ptrs: ; pointers on OP functions
  25. dq OP.t ; a
  26. dq OP.put ; b
  27. dq OP.drop ; c
  28. dq OP.mul ; d
  29. dq OP.div ; e
  30. dq OP.add ; f
  31. dq OP.sub ; g
  32. dq OP.mod ; h
  33. dq 0 ; i : syntax error
  34. dq OP.lshift ; j
  35. dq OP.rshift ; k
  36. dq OP.and ; l
  37. dq OP.or ; m
  38. dq OP.xor ; n
  39. dq OP.not ; o
  40. dq OP.dup ; p
  41. dq OP.pick ; q
  42. dq OP.swap ; r
  43. dq OP.lt ; s
  44. dq OP.gt ; t
  45. dq OP.eq ; u
  46. audiospec_wanted: ; SDL_audio configuration
  47. dd 8000 ; freq
  48. dw AUDIO_U8 ; format
  49. db 1 ; channels
  50. db 0 ; silence
  51. dw 1024 ; samples
  52. dd 0 ; size
  53. dw 0 ; allign
  54. dq audio_cllbck
  55. dq 0 ; userdata
  56. ; text messages
  57. def_str usage, "Usage : "
  58. def_str opts, {" FILE.glitch",0xA}
  59. def_str openerr, {'Error opening file : "', 0xA}
  60. def_str syntax_error, {"Syntax error", 0xA}
  61. def_str bigline_error, {"Line with more than 16 tokens !", 0xA}
  62. def_str nl_error, {"Character \n is not the last one", 0xA}
  63. def_str badop_error, {"Bad OP", 0xA}
  64. section .bss
  65. ; glitch name (1st line) : len 16 + \0
  66. glitch_name: resb 17
  67. ; program internal repr for stack machine
  68. ; each token uses 2 words : 1st for the callback address 2nd for
  69. ; optional value
  70. glitch_pgm: resq 16 * 16 * 2
  71. ; stack machine ring buffer
  72. stack_buff: resd STACK_SZ
  73. ; top of stack pointer
  74. tosp: resq 1
  75. ; stack machine rgister
  76. t: resd 1
  77. ; audiospec returned from SDL
  78. audiospec_recv: resb 32
  79. ; Event receveid from SDL
  80. %ifdef SDL1
  81. event: resb 24
  82. %endif
  83. %ifdef SDL2
  84. event: resb 56
  85. evt_cnt: resb 1
  86. %endif
  87. section .text
  88. global _start
  89. _start:
  90. ; checking args
  91. mov rcx, [rsp]
  92. cmp rcx, 2
  93. jne exit.badarg
  94. mov rax, 0x2 ; sys_open
  95. mov rdi, [rsp+16] ; argv[1]
  96. xor rsi, rsi ; no flags
  97. xor rdx, rdx ; O_RDONLY
  98. syscall
  99. cmp rax, 0
  100. jl exit.err_open
  101. push rax ; source fd
  102. mov rax, 0xc ; brk
  103. xor rdi, rdi
  104. syscall
  105. push rax ; heap start
  106. mov rdi, rax
  107. add rdi, MAX_FILE_SZ ; new heap end
  108. mov rax, 0xc ; brk
  109. syscall
  110. pop rsi ; heap start
  111. mov r14, rsi
  112. xor rax, rax ; sys_read
  113. mov rdi, [rsp] ; source_fd
  114. mov rdx, MAX_FILE_SZ
  115. syscall
  116. cmp rax, 0
  117. jl exit.err_open
  118. mov r15, rax
  119. mov rax, 0x3 ; sys_close
  120. pop rdi ; source_fd
  121. syscall
  122. mov rbx, r15 ;read size
  123. mov rdi, r14 ; heap start
  124. add rdi, rbx ; heap end
  125. mov r15, rdi
  126. mov rax, 0xc ; brk
  127. syscall ; shrink heap to read size
  128. ; init program space
  129. mov rdi, glitch_pgm
  130. xor rax, rax
  131. stosq
  132. stosq
  133. mov rsi, r14
  134. push rsi
  135. xor r13, r13
  136. xor rbx, rbx
  137. parse:
  138. ; go trhough file , with rsi current ptr, r15 file stop
  139. ; r13 will contain updated lineno and rbx chr in current line
  140. ; rdi store the destination pointer
  141. ; parse glitch name
  142. mov rcx, 16
  143. mov rdi, glitch_name
  144. .name_loop:
  145. inc rbx
  146. lodsb
  147. test al, al ; EOF
  148. jz .no_nl
  149. cmp al, 0xA
  150. je .trailing_nl
  151. cmp al, "!" ; EOL
  152. je .name_end
  153. cmp al, "_"
  154. je .chrname
  155. cmp al, "0"
  156. jl exit.syntax_error
  157. cmp al, "9"
  158. jle .chrname
  159. cmp al, "a"
  160. jl exit.syntax_error
  161. cmp al, "z"
  162. jg exit.syntax_error
  163. .chrname:
  164. stosb
  165. loop .name_loop
  166. jmp exit.bigline
  167. .name_end:
  168. inc r13 ; lineno
  169. xor rbx, rbx
  170. xor al, al
  171. stosb
  172. ; parsing tokens
  173. xor edx, edx ; 32bits numeric token value
  174. xor eax, eax
  175. xor r10, r10 ; numeric token flag (1 mean in numeric token)
  176. xor r11, r11 ; numeric token len
  177. mov rcx, r15
  178. sub rcx, r14
  179. mov rdi, glitch_pgm
  180. .parse_loop:
  181. inc rbx
  182. lodsb
  183. test al, al
  184. jz .no_nl
  185. cmp al, 0xA
  186. je .trailing_nl
  187. cmp al, "!" ; EOL
  188. je .next_line
  189. cmp al, "." ; token separator
  190. je .next_token
  191. cmp al, "0"
  192. jl exit.syntax_error
  193. cmp al, "9"
  194. jle .dec_token
  195. cmp al, "A"
  196. jl exit.syntax_error
  197. cmp al, "F"
  198. jle .hex_token
  199. jmp .op_match ; allowing loop near jump
  200. .end_op:
  201. stosq
  202. xor rax, rax
  203. stosq
  204. loop .parse_loop
  205. .hex_token:
  206. sub al, "A" - 10
  207. jmp .numeric_token
  208. .dec_token:
  209. sub al, "0"
  210. .numeric_token:
  211. cmp r11, 8
  212. je exit.syntax_error ; Numeric constant OF
  213. inc r11
  214. mov r10, 1
  215. shl edx, 4
  216. add edx, eax
  217. loop .parse_loop
  218. .next_token:
  219. test r10, r10 ; check for numeric constant
  220. jnz .add_numeric
  221. loop .parse_loop
  222. .next_line:
  223. inc r13
  224. xor rbx, rbx
  225. .loop_parse_loop:
  226. loop .parse_loop
  227. .add_numeric:
  228. mov rax, OP.numeric
  229. stosq
  230. xor rax, rax
  231. xor r11, r11
  232. xor r10, r10
  233. xchg rax, rdx
  234. shl rax, 32
  235. stosq
  236. xor rax, rax
  237. jmp .loop_parse_loop
  238. .trailing_nl:
  239. ; check that NL is the last chr, else syntax error
  240. cmp rsi, r15
  241. jne exit.nl_not_last
  242. jmp .parse_end
  243. .op_match:
  244. ; allow loop .parse_loop near jump
  245. cmp al, "a"
  246. jl exit.syntax_error
  247. cmp al, "u"
  248. jg exit.syntax_error
  249. ; OP shortand matching
  250. ; checking for previous numeric token to write
  251. test r10, r10
  252. jz .match_op
  253. push rax
  254. ; add previous numeric token
  255. mov rax, OP.numeric
  256. stosq
  257. xor rax, rax
  258. xor r11, r11 ; numeric token length raz
  259. xor r10, r10 ; numeric token flag raz
  260. xchg rax, rdx
  261. shl rax, 32 ; shl to allow reading as dword ?
  262. stosq
  263. pop rax
  264. .match_op:
  265. sub al, "a"
  266. shl rax, 3 ; mul by 8 (size of ptr)
  267. add rax, op_ptrs
  268. mov rax, [rax]
  269. test rax, rax
  270. jz exit.bad_op
  271. jmp .end_op
  272. .no_nl: ; TODO : print warning
  273. ; no NL at EOF
  274. .parse_end:
  275. ; clean heap
  276. mov rax, 0xc
  277. pop rdi
  278. syscall
  279. ; print glitch name
  280. mov rax, "Playing "
  281. push rax
  282. mov rax, 1
  283. mov rdi, 1
  284. mov rsi, rsp
  285. mov rdx, 8
  286. syscall
  287. pop rax
  288. mov rdi, glitch_name
  289. call strlen
  290. mov rdx, rax
  291. mov rax, 1
  292. mov rdi, 1
  293. mov rsi, glitch_name
  294. syscall
  295. mov rax, `\n`
  296. push rax
  297. mov rax, 1
  298. mov rdi, 1
  299. mov rsi, rsp
  300. mov rdx, 1
  301. syscall
  302. pop rax
  303. ; init stack machine runtime
  304. stack_init:
  305. mov rcx, STACK_SZ
  306. mov rdi, stack_buff
  307. xor rax, rax
  308. mov [t], eax
  309. .loop_buff_init:
  310. stosd
  311. loop .loop_buff_init
  312. mov eax, (STACK_SZ - 1) * 4
  313. mov [tosp], eax
  314. sdl_init:
  315. mov rdi, 0x0000FFFF
  316. call SDL_Init
  317. mov rdi, audiospec_wanted
  318. mov rsi, audiospec_recv
  319. call SDL_OpenAudio
  320. dbginit:
  321. ; 256*256 window
  322. ;mov rdi, 256
  323. ;mov rsi, 255
  324. ;mov rdx, 32
  325. ;;mov rcx, SDL_SWSURFACE
  326. ;xor rcx, rcx
  327. ;call SDL_SetVideoMode
  328. audio_start:
  329. ;start audio
  330. xor rdi, rdi
  331. call SDL_PauseAudio
  332. loop_event:
  333. xor rdi, rdi
  334. mov [event], rdi
  335. mov rdi, event
  336. call SDL_WaitEvent
  337. cmp rax, 0
  338. je sdl_error ; error fetching event...
  339. xor rdi, rdi
  340. %ifdef SDL1
  341. mov dil, [event] ; 8bit evt
  342. cmp dil, SDL_QUIT
  343. je exit
  344. %endif
  345. %ifdef SDL2
  346. mov edi, [event]
  347. cmp edi, SDL_QUIT
  348. je exit
  349. %endif
  350. evt:
  351. jmp loop_event
  352. sdl_error:
  353. ; display error & exit
  354. call SDL_GetError
  355. push rax
  356. call strlen
  357. mov rdx, rsi ; msglen
  358. pop rdi ; msg
  359. mov rax, 1 ; write
  360. mov rdi, 2 ; stderr
  361. syscall
  362. mov rdi, 0xF
  363. jmp exit.exit_err
  364. exit_fatal:
  365. mov rdi, 42
  366. jmp exit.exit_err
  367. exit:
  368. call SDL_Quit
  369. xor rdi, rdi
  370. mov rax, 0x3c
  371. syscall
  372. .err_open:
  373. mov rax, 1
  374. mov rdi, 2
  375. mov rsi, openerr
  376. mov rdx, openerr_len - 1
  377. syscall
  378. mov rdi, [rsp+16]
  379. push rdi
  380. call strlen
  381. mov rdx, rax
  382. mov rax, 1
  383. mov rdi, 2
  384. pop rsi
  385. syscall
  386. mov rax, 1
  387. mov rdi, 2
  388. mov rsi, openerr + openerr_len - 2
  389. mov rdx, 2
  390. syscall
  391. .badarg:
  392. mov rax, 1
  393. mov rdi, 2
  394. mov rsi, usage
  395. mov rdx, usage_len
  396. syscall
  397. mov rdi, [rsp+8]
  398. call strlen
  399. mov rdx, rax
  400. mov rax, 1
  401. mov rdi, 2
  402. mov rsi, [rsp+8]
  403. syscall
  404. mov rax, 1
  405. mov rdi, 2
  406. mov rsi, opts
  407. mov rdx, opts_len
  408. syscall
  409. mov rdi, 1
  410. .exit_err: ; with rdi error code
  411. mov rax, 0x3c ; exit
  412. syscall
  413. ; expect : r13 lineno, rbx chr num in line
  414. ; TODO: real error message
  415. .nl_not_last:
  416. mov rsi, nl_error
  417. mov rsi, nl_error_len
  418. push qword 3
  419. jmp exit.parse_error
  420. .syntax_error:
  421. mov rsi, syntax_error
  422. mov rdx, syntax_error_len
  423. push qword 2
  424. jmp exit.parse_error
  425. .bigline:
  426. mov rsi, bigline_error
  427. mov rdx, bigline_error_len
  428. push qword 2
  429. jmp exit.parse_error
  430. .bad_op:
  431. mov rsi, badop_error
  432. mov rdx, badop_error_len
  433. push qword 2
  434. jmp exit.parse_error
  435. .parse_error:
  436. ; print error lineno & chrno
  437. push rsi ; source ptr
  438. push rdx
  439. push rbx ; chrno in line
  440. sub r14, rsi ; chr count
  441. push 14
  442. mov rdi, "chr:0x"
  443. mov rsi, 6
  444. call short_err
  445. pop rdi ; chr count
  446. mov rsi, 2
  447. call print_hnum
  448. mov rdi, ",line:0x"
  449. mov rsi, 8
  450. call short_err
  451. mov rdi, r13
  452. mov rsi, 2
  453. call print_hnum
  454. mov rdi, ",col:0x"
  455. mov rsi, 7
  456. call short_err
  457. pop rdi
  458. mov rsi, 2
  459. call print_hnum
  460. mov rdi, ` :\t`
  461. mov rsi, 3
  462. call short_err
  463. pop rdx
  464. pop rsi
  465. mov rax, 1
  466. mov rdi, 2
  467. syscall
  468. pop rdi
  469. jmp exit.exit_err
  470. short_err:
  471. ; rdi is the message (less than 8 chr)
  472. ; rsi is message len
  473. push rdi
  474. mov rdx, rsi
  475. mov rsi, rsp
  476. mov rax, 1
  477. mov rdi, 1
  478. syscall
  479. pop rdi
  480. ret
  481. strlen:
  482. ; rdi containing str pointer
  483. ; rax will contain strlen and rdi is unchanged
  484. mov rsi, rdi
  485. xor rdx, rdx
  486. pushf
  487. cld
  488. .loop:
  489. inc rdx
  490. lodsb
  491. mov cl, al
  492. test al, al
  493. jnz .loop
  494. dec rdx
  495. mov rax, rdx
  496. popf
  497. ret
  498. print_hnum:
  499. ; rdi : number to print
  500. ; rsi : output fd
  501. pushf
  502. mov rax, rdi
  503. xor rcx, rcx
  504. push rcx ; using stack as buffer
  505. std
  506. lea rdi, [rsp + 8]
  507. .loop:
  508. test rax, rax
  509. jz .endloop
  510. inc rcx
  511. inc rcx
  512. push rax
  513. and al, 0x0F
  514. call .al2digit
  515. stosb
  516. mov rax, [rsp]
  517. shr al, 4
  518. call .al2digit
  519. stosb
  520. pop rax
  521. shr rax, 8
  522. jmp .loop
  523. .endloop:
  524. mov rax, 1
  525. xchg rdi, rsi
  526. inc rsi
  527. ;mov rdi, rsi
  528. ;mov rsi, rsp
  529. mov rdx, rcx
  530. syscall
  531. pop rax
  532. popf
  533. ret
  534. .al2digit:
  535. cmp al, 9
  536. jg .hex
  537. add al, "0"
  538. ret
  539. .hex:
  540. add al, "A" - 10
  541. ret
  542. ; simplest/shortes audio_callback : copy byte returned by run_glitch in *stream
  543. audio_cllbck:
  544. ; rdi -> *userdata
  545. ; rsi -> *stream
  546. ; rdx -> stream_len
  547. push rbx ; stores rbx
  548. mov rcx, rdx
  549. mov rdi, rsi
  550. .loop:
  551. push rcx
  552. push rdi
  553. call run_glitch
  554. pop rdi
  555. stosb
  556. pop rcx
  557. inc dword [t]
  558. loop .loop
  559. pop rbx ; rbx restore
  560. ret
  561. run_glitch:
  562. ; Run the glitch_pgm
  563. ; return TOSP value in eax
  564. mov rsi, glitch_pgm
  565. .loop:
  566. lodsq
  567. test rax, rax
  568. jz .end_glitch
  569. push rax
  570. lodsq
  571. mov rdi, rax
  572. pop rax
  573. push rsi
  574. call rax
  575. pop rsi
  576. jmp .loop
  577. .end_glitch:
  578. xor rbx, rbx
  579. mov ebx, [tosp]
  580. lea rdi, [stack_buff + rbx]
  581. mov eax, [rdi]
  582. ; DEBUG (can be use to output data to stdout)
  583. ;push rax
  584. ;xor rdi, rdi
  585. ;mov rdi, rax
  586. ;mov rsi, 1
  587. ;call print_hnum
  588. ;mov rax, " "
  589. ;push rax
  590. ;mov rax, 1
  591. ;mov rdi, 1
  592. ;mov rsi, rsp
  593. ;mov rdx, 1
  594. ;syscall
  595. ;pop rax
  596. ;pop rax
  597. ; /DEBUG
  598. ret
  599. OP:
  600. .numeric:
  601. ; rdi contain the number
  602. shr rdi, 32
  603. ._push:
  604. ; push rdi (edi) on stack_buff
  605. mov eax, edi
  606. xor rbx, rbx
  607. mov ebx, [tosp]
  608. add ebx, 4
  609. cmp ebx, STACK_SZ * 4
  610. jl .go_push
  611. mov ebx, 0
  612. .go_push:
  613. mov [tosp], ebx
  614. lea rdi, [stack_buff+rbx]
  615. stosd
  616. ret
  617. .drop: ; drop just calls pop
  618. ._pop:
  619. ; pop eax from stack_buff
  620. xor rbx, rbx
  621. mov ebx, [tosp]
  622. lea rsi, [stack_buff+rbx]
  623. xor rax, rax
  624. lodsd
  625. test ebx, ebx
  626. jz .pop_no_dec
  627. sub ebx, 4
  628. jmp .pop_end
  629. .pop_no_dec:
  630. mov ebx, (STACK_SZ-1) * 4
  631. .pop_end:
  632. mov [tosp], ebx
  633. ret
  634. .t: ; push t on the stack
  635. mov edi, [t]
  636. call ._push
  637. ret
  638. .put:
  639. pushf
  640. cld
  641. xor rbx, rbx
  642. xor rax, rax
  643. mov ebx, [tosp]
  644. lea rsi, [stack_buff+rbx]
  645. lodsd
  646. and eax, 0xFF
  647. inc eax
  648. mov edx, eax
  649. lodsd
  650. neg rdx
  651. lea rdi, [stack_buff + rdx]
  652. stosq
  653. call OP._pop
  654. popf
  655. ret
  656. .mul:
  657. call .prep_2arg
  658. mul ebx
  659. mov edi, eax
  660. call OP._push
  661. ret
  662. .div:
  663. call .prep_2arg
  664. test ebx, ebx
  665. jz .nodiv
  666. xor rdx, rdx
  667. div ebx
  668. jmp .divend
  669. .nodiv:
  670. xor eax, eax
  671. .divend:
  672. mov edi, eax
  673. call OP._push
  674. ret
  675. .add:
  676. call .prep_2arg
  677. add eax, ebx
  678. mov edi, eax
  679. call OP._push
  680. ret
  681. .sub:
  682. call .prep_2arg
  683. sub eax, ebx
  684. mov edi, eax
  685. call OP._push
  686. ret
  687. .mod:
  688. call .prep_2arg
  689. test rbx, rbx
  690. jz .nomod
  691. xor edx, edx
  692. div ebx
  693. jmp .endmod
  694. .nomod:
  695. xor edx, edx
  696. .endmod:
  697. mov edi, edx
  698. call OP._push
  699. ret
  700. .lshift:
  701. call OP._pop
  702. push rax
  703. call OP._pop
  704. pop rcx
  705. shl eax, cl
  706. mov edi, eax
  707. call OP._push
  708. ret
  709. .rshift:
  710. call OP._pop
  711. push rax
  712. call OP._pop
  713. pop rcx
  714. shr eax, cl
  715. mov edi, eax
  716. call OP._push
  717. ret
  718. .and:
  719. call .prep_2arg
  720. and eax, ebx
  721. mov edi, eax
  722. call OP._push
  723. ret
  724. .or:
  725. call .prep_2arg
  726. or eax, ebx
  727. mov edi, eax
  728. call OP._push
  729. ret
  730. .xor:
  731. call .prep_2arg
  732. xor eax, ebx
  733. mov edi, eax
  734. call OP._push
  735. ret
  736. .not:
  737. call OP._pop
  738. not eax
  739. mov edi, eax
  740. call OP._push
  741. ret
  742. .dup:
  743. call OP._pop
  744. push rax
  745. mov edi, eax
  746. call OP._push
  747. pop rdi
  748. call OP._push
  749. ret
  750. .pick:
  751. call OP._pop
  752. inc eax
  753. and eax, 0xFF
  754. mov ebx, 4
  755. mov ecx, [tosp]
  756. mul ebx ; mul by data size
  757. cmp eax, [tosp]
  758. jg .pick_loop
  759. sub ecx, eax
  760. jmp .pick_lea
  761. .pick_loop: ; eax > tosp
  762. sub eax, ecx
  763. mov ecx, (STACK_SZ - 1) * 4
  764. sub ecx, eax
  765. .pick_lea:
  766. lea rsi, [stack_buff+ecx]
  767. lodsd
  768. push rax
  769. call OP._pop
  770. pop rdi
  771. call OP._push
  772. ret
  773. .swap:
  774. call OP._pop
  775. push rax
  776. call OP._pop
  777. xchg rax, [rsp]
  778. mov edi, eax
  779. call OP._push
  780. pop rdi
  781. call OP._push
  782. ret
  783. .lt:
  784. call .prep_2arg
  785. xor rdi, rdi
  786. cmp eax, ebx
  787. jge .lt_false
  788. not rdi
  789. .lt_false:
  790. call OP._push
  791. ret
  792. .gt:
  793. call .prep_2arg
  794. xor rdi, rdi
  795. cmp eax, ebx
  796. jle .gt_false
  797. not rdi
  798. .gt_false:
  799. call OP._push
  800. ret
  801. .eq:
  802. call .prep_2arg
  803. xor rdi, rdi
  804. cmp eax, ebx
  805. jne .eq_false
  806. not rdi
  807. .eq_false:
  808. call OP._push
  809. ret
  810. .prep_2arg:
  811. ; utils that pop both arguments V1 in eax, V2 in ebx
  812. call OP._pop
  813. push rax
  814. call OP._pop
  815. pop rbx
  816. ret