found a cause of a memory bug in emulator - fix is TODO (#6) - continued working on brainf interpreter. we really need better debugging tools tbh.

This commit is contained in:
2025-06-23 00:31:09 +01:00
parent b8091222a4
commit ddd0c27893
6 changed files with 125 additions and 62 deletions
+114 -56
View File
@@ -1,10 +1,12 @@
// a simple brainf##k interpreter, because I already wrote a compiler lol.
// a simple brainf##k interpreter,
// because I already wrote a compiler lol.
include print "./lib/print.dsa"
// "print hello world"
db program: "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+."
db error: "Invalid Instruction!"
dw stack: 0x10000
dw input: 0x30000
@@ -21,25 +23,32 @@ start:
// rg0 is our instruction pointer
// rg1 is our data pointer
// acc is the value at the data pointer
// rg2 is the value at the data pointer
// rg3 stores the current instruction
// rg4 is the expression nesting level.
lui rg8, 43 // + = 43 increment
lui rg9, 45 // - = 45 decrement
lui rga, 62 // > = 62 increment pointer
lui rgb, 60 // < = 60 decrement pointer
lui rgc, 46 // . = 46 output
lui rgd, 44 // , = 44 input
lui rge, 91 // [ = 91 loop start
lui rgf, 93 // ] = 93 loop end
lli 43, rg8 // + = 43 increment
lli 45, rg9 // - = 45 decrement
lli 62, rga // > = 62 increment pointer
lli 60, rgb // < = 60 decrement pointer
lli 46, rgc // . = 46 output
lli 44, rgd // , = 44 input
lli 91, rge // [ = 91 loop start
lli 93, rgf // ] = 93 loop end
loop:
loop_start:
// load the current instruction into rg3
ldb rg0, rg3
inc rg0
// pusha 2
// push rg3
// call print::print_byte
// pop zero
// popa 2
// switch on the instruction
// all cases will return to either loop_start or loop_end
cmp rg3, rg8
jeq increment
cmp rg3, rg9
@@ -56,93 +65,142 @@ loop:
jeq expr_start
cmp rg3, rgf
jeq expr_end
cmp rg3, zero
jeq end
// if we get here, we don't know what the instruction is
lwi error, rg0
push rg0
call print::print
pop zero
end:
lwi error, rg2
pusha 2
push rg2
call print::print
pop zero
popa 2
hlt
loop_end:
inc rg0
jmp loop_start
// ------------------------------------------
// increment the current cell
increment:
inc acc
jmp loop
inc rg2
jmp loop_end
// ------------------------------------------
// decrement the current cell
decrement:
dec acc
jmp loop
dec rg2
jmp loop_end
// ------------------------------------------
// increment the pointer
inc_ptr:
stw acc, rg1
stw rg2, rg1
addi rg1, 4
ldw rg1, acc
jmp loop
ldw rg1, rg2
jmp loop_end
// ------------------------------------------
// decrement the pointer
dec_ptr:
stw rg1, acc
stw rg1, rg2
subi rg1, 4
ldw rg1, acc
jmp loop
ldw rg1, rg2
jmp loop_end
// ------------------------------------------
// print the byte in the current cell
output:
push acc
pusha 2
push rg2
call print::print_byte
pop zero
jmp loop
popa 2
jmp loop_end
// ------------------------------------------
// read a byte into the current cell
input:
ldw input, acc
jmp loop
ldw input, rg2
jmp loop_end
// ------------------------------------------
// handle an open bracket instruction
expr_start:
cmp acc, zero
jeq _traverse_right
inc rg4
jmp loop
cmp rg2, zero
jne loop_end
expr_end:
cmp acc, zero
jne _traverse_left
dec rg4
jmp loop
_traverse_right_start:
// push a register that definitely has a nonzero value
// when we pop this value from the stack
// we know we've finished traversing.
push rg8
traverse_right_start:
// we need to traverse to the right until we find the closing bracket.
// for each open bracket, we push to the stack
// for each close bracket, we pop from the stack
_traverse_right_loop:
_traverse_right:
inc rg0
ldb rg0, rg3
cmp rg3, rge
jeq _open
jeq open_right
cmp rg3, rgf
jeq _close
jeq close_right
cmp rg3, zero
jeq end
jmp _traverse_right
_open:
push rg4
inc rg4
open_right:
// push zero to the stack
push zero
jmp _traverse_right
_close:
pop rg5
cmp rg4,
jmp _traverse_right
close_right:
// check if we've reached the bottom of the stack
pop rg4
cmp rg4, zero
jeq _traverse_right
// go to next instruction after closing bracket
inc rg0
jmp loop_start
// ------------------------------------------
// handle the close bracket instruction
expr_end:
cmp rg2, zero
jeq loop_end
_traverse_left_start:
push rg8
_traverse_left:
dec rg0
ldb rg0, rg3
cmp rg3, rge
jeq open_left
cmp rg3, rgf
jeq close_left
cmp rg3, zero
jeq end
jmp _traverse_left
open_left:
// check if we've reached the bottom of the stack
pop rg4
cmp rg4, zero
jeq _traverse_left
// go to next instruction after open bracket
inc rg0
jmp loop_start
close_left:
// push zero to the stack
push zero
jmp _traverse_left
Binary file not shown.