Implement interpreter
This commit is contained in:
202
jitfuck.asm
Normal file
202
jitfuck.asm
Normal file
@@ -0,0 +1,202 @@
|
||||
format ELF64 executable
|
||||
|
||||
RIGHT = 3Eh
|
||||
LEFT = 3Ch
|
||||
PLUS = 2Bh
|
||||
MINUS = 2Dh
|
||||
DOT = 2Eh
|
||||
COMMA = 2Ch
|
||||
LBRAC = 5Bh
|
||||
RBRAC = 5Dh
|
||||
|
||||
CHUNK_MAX = 20h
|
||||
CHUNK_SIZE = (CHUNK_MAX * 2)
|
||||
CHUNK_MASK = (CHUNK_SIZE - 1)
|
||||
|
||||
MAX_CHUNKS = 20h
|
||||
TRANSLATION_MAX = 40h
|
||||
|
||||
MEM = 100h
|
||||
|
||||
entry $
|
||||
xor r12,r12 ; Initialize chunk start
|
||||
.next_chunk:
|
||||
xor r13,r13 ; Initialize chunk offset
|
||||
.skip:
|
||||
call key
|
||||
.next_run:
|
||||
cmp rax,0
|
||||
je interpret ; EOF -> finished loading chunks
|
||||
|
||||
;; Dispatch on command
|
||||
cmp rax,RIGHT
|
||||
je .run_init
|
||||
cmp rax,LEFT
|
||||
je .run_init
|
||||
cmp rax,PLUS
|
||||
je .run_init
|
||||
cmp rax,MINUS
|
||||
je .run_init
|
||||
cmp rax,DOT
|
||||
je .run_init
|
||||
cmp rax,COMMA
|
||||
je .run_init
|
||||
cmp rax,LBRAC
|
||||
je .lbrac
|
||||
cmp rax,RBRAC
|
||||
je .rbrac
|
||||
jmp .skip ; Skip non-command characters
|
||||
|
||||
.run_init:
|
||||
mov r14,rax ; Save rax as run command
|
||||
mov r15,1 ; Initialize run count to 1
|
||||
.run:
|
||||
call key
|
||||
cmp rax,r14
|
||||
jne .run_write ; Write run if different command
|
||||
inc r15 ; Increment run count
|
||||
jmp .run
|
||||
|
||||
.run_write:
|
||||
mov rbx,r12
|
||||
add rbx,r13
|
||||
mov byte [chunks+rbx],r14b ; Write command
|
||||
mov byte [chunks+rbx+1],r15b ; Write run count
|
||||
add r13,2 ; Increment chunk offset
|
||||
jmp .next_run
|
||||
|
||||
.lbrac:
|
||||
mov rbx,r12
|
||||
add rbx,CHUNK_SIZE
|
||||
push rbx ; Push start of next chunk
|
||||
mov rax,r12
|
||||
add rax,r13
|
||||
mov byte [chunks+rax],LBRAC ; Write command
|
||||
mov byte [chunks+rax+1],0 ; Zero run count field
|
||||
lea rbx,[chunks+rax+2]
|
||||
push rbx ; Push address of dest field
|
||||
jmp .end_chunk
|
||||
|
||||
.rbrac:
|
||||
pop rax ; Pop address of lbrac's dest field
|
||||
mov rbx,r12
|
||||
add rbx,CHUNK_SIZE
|
||||
mov word [rax],bx ; Write start of next chunk to lbrac's dest field
|
||||
mov rax,r12
|
||||
add rax,r13
|
||||
mov byte [chunks+rax],RBRAC ; Write command
|
||||
mov byte [chunks+rax+1],0 ; Zero run count field
|
||||
pop rbx ; Pop start of chunk after lbrac
|
||||
mov word [chunks+rax+2],bx ; Write to dest field
|
||||
jmp .end_chunk
|
||||
|
||||
.end_chunk:
|
||||
mov word [chunks+rax+4],0 ; Write chunk terminator
|
||||
add r12,CHUNK_SIZE ; Bump chunk start to next chunk
|
||||
jmp .next_chunk
|
||||
|
||||
interpret:
|
||||
xor r12,r12 ; Initialize code offset
|
||||
mov r13,mem ; Initialize head
|
||||
.opcode_dispatch:
|
||||
mov word ax,[chunks+r12]
|
||||
movzx ebx,ah
|
||||
cmp al,RIGHT
|
||||
je .right
|
||||
cmp al,LEFT
|
||||
je .left
|
||||
cmp al,PLUS
|
||||
je .plus
|
||||
cmp al,MINUS
|
||||
je .minus
|
||||
cmp al,DOT
|
||||
je .dot
|
||||
cmp al,COMMA
|
||||
je .comma
|
||||
cmp al,LBRAC
|
||||
je .lbrac
|
||||
cmp al,RBRAC
|
||||
je .rbrac
|
||||
jmp exit
|
||||
|
||||
.right:
|
||||
add r13,rbx
|
||||
jmp .next
|
||||
|
||||
.left:
|
||||
sub r13,rbx
|
||||
jmp .next
|
||||
|
||||
.plus:
|
||||
add byte [r13],bl
|
||||
jmp .next
|
||||
|
||||
.minus:
|
||||
sub byte [r13],bl
|
||||
jmp .next
|
||||
|
||||
.dot:
|
||||
mov r14,rbx
|
||||
.dot_loop:
|
||||
cmp r14,0
|
||||
je .next
|
||||
call emit
|
||||
dec r14
|
||||
jmp .dot_loop
|
||||
|
||||
.comma: ; TODO
|
||||
int3
|
||||
jmp .next
|
||||
|
||||
.lbrac:
|
||||
cmp byte [r13],0
|
||||
jne .next_chunk
|
||||
mov word r12w,[chunks+r12+2]
|
||||
jmp .opcode_dispatch
|
||||
|
||||
.rbrac:
|
||||
cmp byte [r13],0
|
||||
je .next_chunk
|
||||
mov word r12w,[chunks+r12+2]
|
||||
jmp .opcode_dispatch
|
||||
|
||||
.next:
|
||||
add r12,2
|
||||
jmp .opcode_dispatch
|
||||
|
||||
.next_chunk:
|
||||
and r12,(not CHUNK_MASK)
|
||||
add r12,CHUNK_SIZE
|
||||
jmp .opcode_dispatch
|
||||
|
||||
exit:
|
||||
mov rdi,0
|
||||
mov rax,60
|
||||
syscall
|
||||
|
||||
key:
|
||||
mov rdi,0
|
||||
mov rsi,.ch
|
||||
mov rdx,1
|
||||
mov rax,0
|
||||
syscall
|
||||
|
||||
cmp rax,0
|
||||
je .eof
|
||||
mov byte al,[.ch]
|
||||
ret
|
||||
.eof:
|
||||
ret
|
||||
.ch: rb 1
|
||||
|
||||
emit:
|
||||
mov rdi,1
|
||||
mov rsi,r13
|
||||
mov rdx,1
|
||||
mov rax,1
|
||||
syscall
|
||||
ret
|
||||
|
||||
chunks: rw (CHUNK_MAX * MAX_CHUNKS)
|
||||
translations: rb (TRANSLATION_MAX * MAX_CHUNKS)
|
||||
mem: db MEM dup 0
|
||||
Reference in New Issue
Block a user