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

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