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

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