Browse Source

Initial commit

Yann Weber 5 years ago
commit
a93885868c
3 changed files with 945 additions and 0 deletions
  1. 20
    0
      Makefile
  2. 19
    0
      README.txt
  3. 906
    0
      bfc.asm

+ 20
- 0
Makefile View File

@@ -0,0 +1,20 @@
1
+NASM=nasm
2
+ASFLAGS=-felf64
3
+LDFLAGS=-s -melf_x86_64
4
+
5
+# To build with debugging symbols
6
+#ASFLAGS=-felf64 -g -F dwarf -l bf.lst
7
+#LDFLAGS=-g -melf_x86_64
8
+
9
+all: bfc
10
+
11
+bfc: bfc.o
12
+	ld $(LDFLAGS) bfc.o -o bfc
13
+
14
+bfc.o: bfc.asm
15
+	$(NASM) $(ASFLAGS) bfc.asm
16
+
17
+.PHONY: clean
18
+
19
+clean:
20
+	-rm -fv bfc bfc.o bfc.lst

+ 19
- 0
README.txt View File

@@ -0,0 +1,19 @@
1
+BFC : a BrainFuck Compiler & interpreter
2
+----------------------------------------
3
+
4
+Build :
5
+-------
6
+	make
7
+or :
8
+	nasm -felf64 bfc.asm && ld -s -melf_x86_64 bfc.o -o bfc
9
+
10
+Usage :
11
+-------
12
+	./bfc [-h] [-e [-o a.out]] FILE.bf
13
+
14
+Options :
15
+---------
16
+ 	-h print usage and exit
17
+	-e tell bfc to produce a elf file
18
+	-o with -e indicate the file to create
19
+	FILE.bf the brainfuck source file to compile

+ 906
- 0
bfc.asm View File

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

Loading…
Cancel
Save