Brainfuck compiler for linux x86_64 written in nasm x86_64
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.

bfc.asm 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. ; bfc : a brainfuck compiler & interpreter
  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. ; A brainfuck compiler & interpreter :
  18. ; Build : nasm -felf64 bfc.asm && ld -s -melf_x86_64 bfc.o -o bfc
  19. ;
  20. ; ./bfc [-h] [-e [-o a.out]] FILE.bf
  21. ; Options :
  22. ; -h print usage and exit
  23. ; -e tell bfc to produce a elf file
  24. ; -o with -e indicate the file to create
  25. ; FILE.bf the brainfuck source file to compile
  26. [bits 64]
  27. %use smartalign
  28. ALIGNMODE k8
  29. %define lbl_incresize 0x2e
  30. %define lbl_decresize 0x50
  31. %define MAP_INC_SIZE 0x1000
  32. %define MAP_INC_MASK 0x0FFF
  33. %define BFMEM_INIT_SZ MAP_INC_SIZE
  34. section .data
  35. bf_start_head:
  36. push 0x00400085
  37. ;dw 0x6885004000
  38. bf_start_head_sz: equ $ - bf_start_head
  39. bf_start:
  40. jmp .start
  41. .mremap: ; rbx is resize size
  42. cmp rbx, MAP_INC_SIZE
  43. jg .remap_cont
  44. xor rbx, rbx
  45. .remap_cont:
  46. xor rbx, MAP_INC_MASK
  47. add rbx, MAP_INC_SIZE
  48. add r14, rbx
  49. mov rax, 0x19 ; mremap
  50. mov rdi, r15 ; addr
  51. mov rsi, r14 ; oldlen
  52. jc .erremap ; overflow, too much mem !!!!
  53. mov rdx, r14 ; newlen
  54. xor r10, r10 ; maymove
  55. xor r11, r11
  56. syscall
  57. cmp rax, 0
  58. jle .erremap
  59. mov r15, rax
  60. ret
  61. .erremap:
  62. mov rax, 0x3c
  63. mov rdi, 0x2
  64. syscall
  65. align 8
  66. .lbl_incresize: equ $ - bf_start
  67. .incresize: ; rbx is resize size
  68. call .mremap
  69. ret
  70. align 8
  71. .lbl_decresize: equ $ - bf_start
  72. .decresize: ; rbx is decrement
  73. push rsi
  74. push r14
  75. call .incresize
  76. pop rcx ; old size
  77. mov rdi, rsi
  78. inc rdi
  79. .decresize_cpy:
  80. movsb
  81. loop .decresize_cpy
  82. mov byte [r15], 0
  83. pop rsi
  84. ret
  85. .errmap:
  86. mov rax, 0x3c
  87. mov rdi, 0x1
  88. syscall
  89. .start:
  90. ;map init
  91. mov rax, 0x9 ;mmap
  92. xor rdi, rdi
  93. mov rsi, BFMEM_INIT_SZ ;len
  94. mov r14, rsi
  95. mov rdx, (0x1|0x2) ;PROT_READ | PROT_WRITE
  96. mov r10, (0x2 | 0x20) ;flags MAP_PRIVATE | MAP_ANONYMOUS
  97. mov r8, -1 ;fd
  98. xor r9, r9
  99. syscall
  100. cmp rax, 0
  101. jle .errmap
  102. mov r15, rax
  103. mov rsi, r15
  104. add rsi, (BFMEM_INIT_SZ / 2) ; BF ptr
  105. align 8
  106. bf_start_sz: equ $ - bf_start
  107. ; In piece of code call jump is achieved by adding
  108. ; an offset to the JIT map base addr
  109. ; this base address has to be on top of the stack
  110. ; when executing this small piece of code
  111. ;
  112. ; the first instruction has to be a mov of a byte
  113. ; in a register. This operation will be updated to
  114. ; "pass" a parameter
  115. bf_decptr:
  116. mov rbx, strict qword 0x1
  117. push rbx
  118. cmp rsi, rbx
  119. jge .end
  120. mov rax, [rsp+8]
  121. add rax, bf_start.lbl_decresize
  122. call rax
  123. .end:
  124. pop rbx
  125. sub rsi, rbx
  126. bf_decptr_sz: equ $ - bf_decptr
  127. bf_incptr:
  128. mov rbx, strict qword 0x1
  129. push rbx
  130. mov rax, rsi
  131. sub rax, r15
  132. cmp rax, r14
  133. jl .end
  134. mov rax, [rsp+8]
  135. add rax, bf_start.lbl_incresize
  136. call rax
  137. .end:
  138. pop rbx
  139. add rsi, rbx
  140. bf_incptr_sz: equ $ - bf_incptr
  141. bf_incval:
  142. mov rbx, strict qword 0x1
  143. xor rax, rax
  144. mov al,[rsi]
  145. add rax, rbx
  146. mov [rsi], al
  147. bf_incval_sz: equ $ - bf_incval
  148. bf_decval:
  149. mov rbx, strict qword 0x1
  150. xor rax, rax
  151. mov al, [rsi]
  152. sub rax, rbx
  153. mov [rsi], al
  154. bf_decval_sz: equ $ - bf_decval
  155. bf_readval:
  156. mov rdx, strict qword 0x1
  157. push rsi
  158. xor rax, rax ; read
  159. xor rdi, rdi ; stdin
  160. syscall
  161. test rax, rax
  162. jnz .end
  163. mov byte [rsi], 0
  164. .end:
  165. pop rsi
  166. bf_readval_sz: equ $ - bf_readval
  167. bf_writeval:
  168. mov rdx, strict qword 0x1
  169. push rsi
  170. xor rax, rax ; write
  171. inc rax
  172. mov rdi, rax ; stdout
  173. syscall
  174. pop rsi
  175. bf_writeval_sz: equ $ - bf_writeval
  176. bf_loopstart:
  177. mov rbx, strict qword 0x1
  178. add rbx, [rsp]
  179. xor rdx, rdx
  180. mov dl, [rsi]
  181. cmp dl, 0
  182. jnz .end
  183. jmp rbx
  184. .end:
  185. bf_loopstart_sz: equ $ - bf_loopstart
  186. bf_loopend:
  187. mov rbx, strict qword 0x1
  188. add rbx, [rsp]
  189. xor rdx, rdx
  190. mov dl, [rsi]
  191. cmp dl, 0
  192. jz .end
  193. jmp rbx
  194. .end:
  195. bf_loopend_sz: equ $ - bf_loopend
  196. bf_exit:
  197. mov rax, 0x3c
  198. xor rdi, rdi
  199. syscall
  200. bf_exit_sz: equ $ - bf_exit
  201. elf_head: dw 0x457f, 0x464c, 0x0102, 0x0001,
  202. times 4 dw 0x0
  203. ; 0x10
  204. dw 0x0002, 0x003e, 0x0001, 0x0000
  205. dw 0x080, 0x040, 0x0, 0x0
  206. ; 0x20
  207. dw 0x0040
  208. times 3 dw 0x0
  209. elf_section_head_offset : times 8 db 0xFF ; 0x28
  210. ; 0x30
  211. dw 0x0, 0x0, 0x40, 0x38, 0x1, 0x40, 0x3, 0x2
  212. ; 0x40 section header
  213. dw 0x1, 0x0, 0x5 ; load in memory with RX perm
  214. times 5 dw 0x0
  215. ; 0x50
  216. dw 0x0, 0x40, 0, 0, 0, 0x40, 0, 0 ; load at 0x40000
  217. ; 0x60
  218. elf_prog_sz: times 16 db 0xFF ; 0x60 & 0x 68
  219. ; 0x70
  220. dw 0x0, 0x20
  221. times 6 dw 0x0
  222. elf_head_sz: equ $ - elf_head
  223. elf_shstrtab: db ".shstrtab", 0x0, ".text", 0x0
  224. align 8
  225. elf_shstrtab_sz: equ $ - elf_shstrtab
  226. elf_section_headers: times 8 dq 0x0 ; head0
  227. ; head 1
  228. dw 0xb, 0, 0x1, 0, 0x6, 0, 0, 0
  229. dw 0x80, 0x40, 0, 0, 0x80, 0, 0, 0
  230. elf_section_text_sz: times 8 db 0xFF
  231. dq 0x0
  232. dw 0x10
  233. times 7 dw 0x0
  234. ; head2
  235. dw 0x1, 0, 0x3 , 0, 0, 0, 0, 0
  236. dq 0x0
  237. elf_section_strtab_off: times 8 db 0xFF
  238. dw 0x11
  239. times 7 dw 0x0
  240. dw 0x1
  241. times 7 dw 0x0
  242. elf_section_headers_sz: equ $ - elf_section_headers
  243. default_output: db "a.out", 0x0
  244. miss_open: db "Missing opening '[' matching closing ']'"
  245. miss_open_sz: equ $ - miss_open
  246. chr_list : db ": ", 0xA, 0x0
  247. read_error: db "Error reading file "
  248. read_error_sz: equ $ - read_error
  249. usage_err: db "Usage : [-e [-o a.out]] FILE.BF"
  250. usage_err_sz: equ $ - usage_err
  251. open_err: db "Error opening file", 0xa
  252. open_err_sz: equ $ - open_err
  253. section .text
  254. global _start
  255. _start:
  256. ; using heap to store arguments
  257. %define bf_source [r13]
  258. %define elf_file [r13+0x8]
  259. %define elf_out [r13+0x11]
  260. %define heap_size 0x12
  261. mov rax, 0xc
  262. xor rdi, rdi
  263. syscall
  264. mov rdi, rax
  265. mov r13, rax ; heap start
  266. add rdi, heap_size
  267. mov rax, 0xc
  268. syscall
  269. ;argument parsing
  270. mov rcx, [rsp] ; argc
  271. cmp rcx, 2
  272. jl .badarg
  273. je .init_1arg
  274. cmp rcx, 5
  275. jg .badarg
  276. mov rsi, rsp
  277. add rsi, 8 ; argv[0]
  278. dec rcx
  279. .argloop:
  280. add rsi, 8
  281. mov rdi, [rsi]
  282. mov al, [rdi]
  283. cmp al, 0x2d ; '-'
  284. jne .filearg
  285. mov al, [rdi+2]
  286. test al, al
  287. jnz .filearg
  288. ; arg is '-X' testing X
  289. mov al, [rdi+1]
  290. cmp al, 0x68 ; '-h'
  291. je .badarg
  292. cmp al, 0x65 ; '-e'
  293. je .elfout_arg
  294. cmp al, 0x6f ; '-o'
  295. jne .badarg
  296. ; -o storing file
  297. test rcx, rcx
  298. jz .badarg ; no more args
  299. dec rcx
  300. add rsi, 8
  301. mov rdi, [rsi]
  302. mov elf_file, rdi
  303. loop .argloop
  304. jmp .init
  305. .elfout_arg:
  306. mov al, 0x1
  307. mov elf_out, al
  308. mov rax, elf_file
  309. test rax, rax
  310. jz .default_out
  311. .elfout_arg_end:
  312. loop .argloop
  313. jmp .init
  314. .default_out:
  315. mov rax, default_output
  316. mov elf_file, rax
  317. jmp .elfout_arg_end
  318. .filearg:
  319. mov rax, bf_source
  320. cmp rax, 0
  321. .br3:
  322. jnz .badarg ; file allready given
  323. mov bf_source, rdi
  324. loop .argloop
  325. jmp .init
  326. .init_1arg:
  327. mov rax, [rsp+16]
  328. mov bf_source, rax
  329. .init:
  330. ; code map init
  331. ; rsi map size
  332. mov rsi, 0x10
  333. call initmap
  334. mov rax, 0x2 ; open
  335. mov rdi, bf_source ; from heap
  336. test rdi, rdi
  337. jz .badarg
  338. xor rsi, rsi ; O_RDONLY
  339. xor rdx, rdx ; no mode
  340. syscall
  341. cmp rax, 0
  342. jl .err_open
  343. push rax ; fd
  344. push r13 ; heap
  345. call compile_bf
  346. pop r13 ; heap
  347. pop rdi ; fd
  348. sub rax, r15
  349. push rax ; map len
  350. mov rax, 0x3 ; close
  351. syscall
  352. mov al, elf_out
  353. test al, al
  354. jnz .write_elf
  355. .code_jmp:
  356. ; restore heap
  357. mov rax, 0xc
  358. mov rdi, r13
  359. syscall
  360. ; set code map perm
  361. mov rax, 0xA ; mprotect
  362. mov rdi, r15
  363. mov rsi, r14
  364. mov rdx, 0x4 | 0x1 ; PROT_EXEC | PROT_READ
  365. syscall
  366. push r15
  367. jmp r15 ; end... jumping in bf code map
  368. .write_elf: ; writing elf file
  369. mov rax, [rsp] ; map len
  370. add rax, bf_start_head_sz
  371. mov [elf_section_text_sz], rax
  372. add rax, elf_head_sz ; elf head + map_ptr
  373. mov [elf_head + 0x60], rax
  374. mov [elf_head + 0x68], rax
  375. mov [elf_section_strtab_off], rax
  376. add rax, elf_shstrtab_sz ; section head offset
  377. xor r14, r14 ; store align padding for section header
  378. xor rbx, rbx
  379. mov bl, al
  380. and bl, 0x0F
  381. test bl, bl
  382. jz .aligned_section
  383. mov r14, 0x10
  384. sub r14, rbx
  385. and al, 0xF0
  386. add rax, 0x10
  387. .aligned_section:
  388. mov [elf_head + 0x28], rax
  389. mov rax, 0x2
  390. mov rdi, elf_file
  391. mov rsi, 0x40 | 0x200 | 0x1 ; O_CREAT | O_TRUNC | O_WRONLY
  392. mov rdx, 755o ; perm
  393. syscall
  394. cmp rax, 0
  395. jl .err_open
  396. push rax ; fd
  397. mov rax, 1
  398. mov rdi, [rsp]
  399. mov rsi, elf_head
  400. mov rdx, elf_head_sz
  401. syscall
  402. mov rax, 1
  403. mov rdi, [rsp]
  404. mov rsi, bf_start_head
  405. mov rdx, bf_start_head_sz
  406. syscall
  407. mov rax, 1
  408. mov rdi, [rsp]
  409. mov rsi, r15 ; map_addr
  410. mov rdx, [rsp+8] ; map len
  411. syscall
  412. mov rax, 1
  413. mov rdi, [rsp]
  414. mov rsi, elf_shstrtab
  415. mov rdx, elf_shstrtab_sz
  416. syscall
  417. .padloop:
  418. test r14, r14
  419. jz .end_padloop
  420. mov rax, 1
  421. mov rdi, [rsp]
  422. mov rsi, elf_section_headers ; 0x0
  423. mov rdx, 1
  424. syscall
  425. dec r14
  426. jmp .padloop
  427. .end_padloop:
  428. mov rax, 1
  429. mov rdi, [rsp]
  430. mov rsi, elf_section_headers
  431. mov rdx, elf_section_headers_sz
  432. syscall
  433. pop rdi ; fd
  434. mov rax, 0x3 ; close
  435. syscall
  436. pop rax ; map_len
  437. mov rax, 0x3c ; exit
  438. xor rdi, rdi
  439. syscall
  440. .err_open:
  441. mov rax, 1 ; write
  442. mov rdi, 2 ; stderr
  443. mov rsi, open_err
  444. mov rdx, open_err_sz
  445. syscall
  446. .badarg:
  447. mov rax, 1 ;write
  448. mov rdi, 2 ; stderr
  449. mov rsi, usage_err
  450. mov rdx, 8 ; "Usage : "
  451. syscall
  452. mov rsi, [rsp+8] ; argv[0]
  453. xor rdx, rdx
  454. xor rcx, rcx
  455. .argv0len:
  456. inc rsi
  457. inc rdx
  458. mov cl, [rsi]
  459. test cl, cl
  460. jnz .argv0len
  461. mov rax, 1
  462. mov rdi, 2
  463. mov rsi, [rsp+8] ; argv[0]
  464. syscall
  465. mov rax, 1 ;write
  466. mov rdi, 2 ; stderr
  467. mov rsi, usage_err + 7
  468. mov rdx, usage_err_sz - 7 ; usage opts
  469. syscall
  470. mov rax, 1
  471. mov rdi, 2
  472. mov rsi, chr_list + 2 ; \n
  473. mov rdx, 1
  474. syscall
  475. mov rax, 0x3c ; exit
  476. mov rdi, 1
  477. syscall
  478. %undef heap_size
  479. %undef elf_file
  480. %undef bf_source
  481. ; Init a writable memory map
  482. ; len in rsi
  483. ; ret : r14 map size
  484. ; r15 map addr
  485. initmap:
  486. mov r14, rsi
  487. mov rax, 0x9 ;mmap
  488. xor rdi, rdi ;addr
  489. ; rsi is len
  490. mov rdx, (0x1|0x2) ;PROT_READ | PROT_WRITE
  491. mov r10, (0x2 | 0x20) ;flags MAP_PRIVATE | MAP_ANONYMOUS
  492. mov r8, -1 ;fd
  493. xor r9, r9
  494. syscall
  495. cmp rax, 0
  496. jle .err
  497. mov r15, rax
  498. ret
  499. .err:
  500. mov rax, 0x3c
  501. mov rdi, 0x2
  502. syscall
  503. ; resize the memory map
  504. ; addr in r15 (0 if init)
  505. ; len in r14
  506. ; inc size in bytes in r10
  507. mremap:
  508. mov rax, 0x19 ;mremap
  509. mov rdi, r15 ;addr
  510. mov rsi, r14 ;oldlen
  511. mov rdx, rsi
  512. add rdx, MAP_INC_SIZE ; newlen
  513. xor r10, r10 ; MAYMOVE
  514. xor r11, r11
  515. syscall
  516. cmp rax, 0
  517. jle .err
  518. mov r15, rax
  519. add r14, MAP_INC_SIZE
  520. ret
  521. .err:
  522. mov rax, 0x3c
  523. mov rdi, 0x3
  524. syscall
  525. ; JIT brainfuck compiler. Read bf code from fd and write
  526. ; machine code in a dedicated anon map with PROT_READ | PROT_EXEC
  527. ; Using heap to read file
  528. ; args :
  529. ; rax source fd
  530. ; r14 map size
  531. ; r15 map addr
  532. ; ret :
  533. ; rax map ptr
  534. ; r15 map addr
  535. ; r14 map size
  536. compile_bf:
  537. ; Allocating growing heap to store various datas
  538. ; heap start will be stored in r13
  539. %define fd [r13]
  540. %define map_ptr [r13+0x8]
  541. %define base_rsp [r13+0x10]
  542. %define chr_repeat [r13+0x18]
  543. %define line_count [r13+0x20]
  544. %define chr_count [r13+0x28]
  545. %define chr_buff_off 0x30
  546. %define chr_buff [r13+chr_buff_off]
  547. %define prev_chr_off 0x31
  548. %define prev_chr [r13+prev_chr_off]
  549. %define heap_size 0x32
  550. push rax ; source fd
  551. mov rax, 0xc ; brk
  552. xor rdi, rdi
  553. syscall
  554. push rax ; heap start
  555. mov rdi, rax
  556. add rdi, heap_size ; new heap addr
  557. mov rax, 0xc ; brk
  558. syscall
  559. pop rdi ; heap start
  560. mov r13, rdi
  561. pop rax ; source fd
  562. mov fd, rax
  563. ; init heap
  564. mov byte prev_chr, 0
  565. mov qword chr_count, 0
  566. mov qword line_count, 0
  567. mov qword chr_repeat, 1
  568. mov base_rsp, rsp ; save rsp in heap
  569. ; copy code map header
  570. mov rdi, r15
  571. mov rsi, bf_start
  572. mov rdx, bf_start_sz
  573. call code_cpy
  574. mov map_ptr, rax ; new map ptr
  575. ; read first char in prev_chr
  576. xor rax, rax ;read
  577. mov rdi, fd ; fd
  578. mov rsi, r13
  579. add rsi, prev_chr_off ; chr_prev
  580. mov rdx, 1 ; read 1 byte
  581. syscall
  582. cmp rax, 0
  583. jle .read_error
  584. .readloop:
  585. xor rax, rax ;read
  586. mov rdi, fd ; fd
  587. mov rsi, r13
  588. add rsi, chr_buff_off ; buff byte
  589. mov rdx, 1 ; read 1 byte
  590. syscall
  591. cmp rax, 0
  592. je .endread
  593. jl .read_error ; error
  594. mov rax, chr_count ; chr counter
  595. inc rax
  596. mov chr_count, rax
  597. mov al, chr_buff
  598. ; arg for loop is not a repeat counter
  599. cmp al, 0x5b ; '['
  600. je .cmpchar
  601. cmp al, 0x5d ; '['
  602. je .cmpchar
  603. cmp al, prev_chr
  604. je .incnum ; same instruction, incrementing counter
  605. .cmpchar:
  606. mov rdi, map_ptr ; prepare to copy in code map
  607. ; compare previous char and store current in prev
  608. ; note : chr_repeat has to be reset by .nxtinstr
  609. ; after jump
  610. xchg prev_chr, al
  611. cmp al, 0x3c ; '<'
  612. je .lptr
  613. cmp al, 0x3e ; '>'
  614. je .rptr
  615. cmp al, 0x2b ; '+'
  616. je .incval
  617. cmp al, 0x2d ; '-'
  618. je .decval
  619. cmp al, 0x2e ; '.'
  620. je .wrval
  621. cmp al, 0x2c ; ','
  622. je .rdval
  623. cmp al, 0x5b ; '['
  624. je .loopstart
  625. cmp al, 0x5d ; ']'
  626. je .loopend
  627. cmp al, 0x0a ; '\n'
  628. je .line
  629. ; chr is not an instruction, printing them
  630. ; on stderr
  631. mov chr_buff, al
  632. mov rcx, chr_repeat
  633. .errchr:
  634. push rcx
  635. mov rax, 1 ; write
  636. mov rdi, 2 ; stderr
  637. mov rsi, r13
  638. add rsi, chr_buff_off ; heap buff
  639. mov rdx, rax ; sz 1
  640. syscall
  641. pop rcx
  642. loop .errchr
  643. jmp .nxtinstr
  644. .line: ; increment line counter in heap
  645. mov rax, line_count
  646. add rax, chr_repeat
  647. mov line_count, rax
  648. mov rcx, chr_repeat
  649. jmp .errchr ; print the newline
  650. ; following ref copy assume rdi to be map_ptr
  651. .incval:
  652. mov rsi, bf_incval
  653. mov rdx, bf_incval_sz
  654. push rdx
  655. jmp .callcpy
  656. .decval:
  657. mov rsi, bf_decval
  658. mov rdx, bf_decval_sz
  659. push rdx
  660. jmp .callcpy
  661. .lptr:
  662. mov rsi, bf_decptr
  663. mov rdx, bf_decptr_sz
  664. push rdx
  665. jmp .callcpy
  666. .rptr:
  667. mov rsi, bf_incptr
  668. mov rdx, bf_incptr_sz
  669. push rdx
  670. jmp .callcpy
  671. .wrval:
  672. mov rsi, bf_writeval
  673. mov rdx, bf_writeval_sz
  674. push rdx
  675. jmp .callcpy
  676. .rdval:
  677. mov rsi, bf_readval
  678. mov rdx, bf_readval_sz
  679. push rdx
  680. jmp .callcpy
  681. .loopstart:
  682. mov rbx, map_ptr
  683. sub rbx, r15
  684. push rbx ; loop offset from map start
  685. ;push qword map_ptr ; ret addr
  686. mov rsi, bf_loopstart
  687. mov rdx, bf_loopstart_sz
  688. push rdx
  689. jmp .callcpy
  690. .loopend:
  691. cmp rsp, base_rsp
  692. je .loop_err_miss_open
  693. mov rsi, bf_loopend
  694. mov rdx, bf_loopend_sz
  695. push rdx
  696. call code_cpy
  697. mov map_ptr, rax ; rax is map_ptr
  698. pop rdx
  699. sub rax, rdx
  700. add rax, 2 ;arg addr in code map
  701. pop rbx ; loop_start code offset
  702. mov [rax], rbx ; loop end jump to start
  703. mov rax, map_ptr
  704. sub rax, r15 ; loop end offset in map
  705. add rbx, r15 ; loop start addr
  706. mov [rbx+2], rax ; start jump to end
  707. jmp .nxtinstr
  708. .callcpy:
  709. call code_cpy
  710. mov map_ptr, rax
  711. ; set the 1st instr rgs in the mapping
  712. ; and reinit chr_repeat
  713. pop rdx
  714. sub rax, rdx
  715. add rax, 2 ; arg addr in code map
  716. mov rbx, chr_repeat
  717. mov [rax], rbx
  718. .nxtinstr:
  719. ; reinit chr_repeat
  720. mov qword chr_repeat, 1
  721. jmp .readloop
  722. .incnum:
  723. ; same instruction found incrementing
  724. ; chr_repeat
  725. mov rbx, chr_repeat
  726. inc rbx
  727. jc .incoverflow
  728. mov chr_repeat, rbx
  729. jmp .readloop
  730. .incoverflow:
  731. dec rbx
  732. mov chr_repeat, rbx
  733. jmp .cmpchar
  734. jmp .readloop
  735. .loop_err_miss_open:
  736. ; miss_open_err
  737. mov rax, 1
  738. mov rdi, 2 ; stderr
  739. mov rsi, miss_open
  740. mov rdx, miss_open_sz
  741. syscall
  742. jmp .exit_error
  743. .read_error:
  744. xor rax, rax
  745. inc rax ; write
  746. mov rsi, 2 ; stderr
  747. mov rdi, read_error
  748. mov rdx, read_error_sz
  749. syscall
  750. jmp .exit_error
  751. .exit_error:
  752. mov rax, 1
  753. mov rdi, 2
  754. mov rsi, chr_list + 2
  755. mov rdx, 1
  756. syscall
  757. mov rax, 0x3c
  758. mov rdi, 0x11
  759. syscall
  760. .endread: ; EOF reached
  761. ; fake \0 read to process prev_chr
  762. mov byte chr_buff, 0
  763. mov bl, prev_chr
  764. test bl, bl
  765. jnz .cmpchar
  766. ; prevchar is 0 copying exit in code map
  767. .end_compile:
  768. mov rdi, map_ptr
  769. mov rsi, bf_exit
  770. mov rdx, bf_exit_sz
  771. call code_cpy
  772. mov map_ptr, rax
  773. ; restoring stack
  774. mov rsp, base_rsp
  775. push qword map_ptr
  776. ; restore heap
  777. mov rax, 0xc ; brk
  778. mov rdi, r13
  779. syscall
  780. pop rax ; return map_ptr
  781. ret
  782. %undef fd
  783. %undef map_ptr
  784. %undef base_rsp
  785. %undef chr_buff
  786. %undef prev_chr
  787. %undef heap_size
  788. ; Copy bf code from data to map
  789. ; Use :
  790. ; r15 map start
  791. ; r14 map size
  792. ; rdi map ptr
  793. ; rsi code ptr
  794. ; rdx code size in bytes
  795. ; ret :
  796. ; rax : new map ptr
  797. code_cpy:
  798. push rdx
  799. mov rax, rdi
  800. sub rax, r15 ; used len in map
  801. push rax
  802. mov rcx, rdx
  803. cmp rax, r14 ; rax is future len (after copy)
  804. jle .copy
  805. ; resize
  806. push rsi ; save code_ptr
  807. call mremap
  808. pop rsi ; new code_ptr
  809. .copy:
  810. mov rdi, r15
  811. pop rax
  812. add rdi, rax ; new map ptr
  813. pop rcx ; size in words to write
  814. cld ; clear DF
  815. .copyloop:
  816. movsb
  817. loop .copyloop
  818. mov rax, rdi
  819. .ret:
  820. ret