From ddd0c278932f20dfdcbc617a149539e4bc8daa47 Mon Sep 17 00:00:00 2001 From: zxq5 Date: Mon, 23 Jun 2025 00:31:09 +0100 Subject: [PATCH] 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. --- assembler/src/assembler/expand.rs | 2 +- assembler/src/assembler/model.rs | 4 +- emulator/src/emulator/system/memory.rs | 3 + emulator/src/emulator/system/processor/mod.rs | 8 +- resources/dsa/bf.dsa | 170 ++++++++++++------ resources/dsb/bf.dsb | Bin 0 -> 4 bytes 6 files changed, 125 insertions(+), 62 deletions(-) create mode 100644 resources/dsb/bf.dsb diff --git a/assembler/src/assembler/expand.rs b/assembler/src/assembler/expand.rs index dbe81da..993a6ad 100644 --- a/assembler/src/assembler/expand.rs +++ b/assembler/src/assembler/expand.rs @@ -183,7 +183,7 @@ fn expand_stx(current: Node, nodes: &mut Vec) -> Result<(), AssembleError> let base = expect_type!(current.arg(0).unwrap(), Register)?; let dest = expect_type!(current.arg(1).unwrap(), Symbol)?; let offset = expect_type!(current.arg(2).unwrap(), Immediate)?; - let temp = Token::Register(Register::Rgf); + let temp = Token::Register(Register::Acc); nodes.extend(vec![ node!(current.label(), Opcode::Lli, dest, temp), diff --git a/assembler/src/assembler/model.rs b/assembler/src/assembler/model.rs index 28c37a2..d9c041c 100644 --- a/assembler/src/assembler/model.rs +++ b/assembler/src/assembler/model.rs @@ -326,8 +326,8 @@ impl FromStr for Opcode { "include" => Ok(Self::Include), "call" => Ok(Self::Call), "return" => Ok(Self::Return), - "pusha" => Ok(Self::Push), - "popa" => Ok(Self::Pop), + "pusha" => Ok(Self::Pusha), + "popa" => Ok(Self::Popa), _ => Err(OpcodeFromStrError::InvalidRegister("unknown opcode")), } } diff --git a/emulator/src/emulator/system/memory.rs b/emulator/src/emulator/system/memory.rs index aa655e7..32f2b48 100644 --- a/emulator/src/emulator/system/memory.rs +++ b/emulator/src/emulator/system/memory.rs @@ -72,6 +72,9 @@ impl MemoryUnit for MainStore { fn read_word(&mut self, addr: u32) -> u32 { let (block_addr, offset) = Self::segment_addr(addr); + + println!("reading word from {block_addr:x?} + {offset}"); + let block = self.mut_block(block_addr); let mut bytes = [0; 4]; bytes[0] = block.data[offset as usize]; diff --git a/emulator/src/emulator/system/processor/mod.rs b/emulator/src/emulator/system/processor/mod.rs index ecdbf54..c5f7fde 100644 --- a/emulator/src/emulator/system/processor/mod.rs +++ b/emulator/src/emulator/system/processor/mod.rs @@ -21,6 +21,10 @@ pub struct Processor { pub dustbin: u32, } +fn log(message: &str) { + println!("\x1b[32mINFO:\x1b[0m {message}"); +} + #[allow(clippy::needless_pass_by_ref_mut)] impl Processor { #[must_use] @@ -62,12 +66,10 @@ impl Processor { // Decode and execute the instruction. let instruction = Instruction::decode(val)?; - println!("Executing instruction: {instruction}"); + log(&instruction.to_string()); instruction.execute(self); - println!("ok!"); - Ok((addr, instruction)) } diff --git a/resources/dsa/bf.dsa b/resources/dsa/bf.dsa index a58c24a..801a0b7 100644 --- a/resources/dsa/bf.dsa +++ b/resources/dsa/bf.dsa @@ -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 diff --git a/resources/dsb/bf.dsb b/resources/dsb/bf.dsb new file mode 100644 index 0000000000000000000000000000000000000000..2b831a14e46872a7943b9adcac710ba835e160b8 GIT binary patch literal 4 LcmXpjXJ7#U0!09_ literal 0 HcmV?d00001