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 13KB

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