So You Want to Build a Language VM - Interlude 02

Adds in strings to our VM

Hello!

Welcome to the 2nd interlude where we go back and tidy up a bit! Before doing this, you should have finished tutorial #12. == True should be False One bug I found while writing article #13 is that when calling execute_instruction() on the VM, it executes one loop. I’ve been using this version of the VM to execute one iteration at a time, so it went unnoticed.

The Fix

Head over to src/vm.rs and find the execute_instruction() function:

pub fn run(&mut self) {
    let mut is_done = false;
    while !is_done {
        is_done = self.execute_instruction();
    }
}

fn execute_instruction(&mut self) -> bool {
    if self.pc >= self.program.len() {
        // This was false
        return true;
    }
    match self.decode_opcode() {
        Opcode::HLT => {
            println!("HLT encountered");
            // This was false
            return true;
        }
        Opcode::IGL => {
            println!("Illegal instruction encountered");
            // This was false
            return true;
        }
     // The rest of the opcodes are fine
     <snip>

    }
    // This was true
    false
}

We flipped the four boolean values in the snippet above to their opposite.

Whoops.

Anywho, that was an easy fix.

Instruction Padding

This bug was that some instructions which did not use the full 32 bits were not padded to 32 bits. Because our VM relies on each instruction being 32-bits, we need to pad any that are smaller.

The Fix

In src/repl/mod.rs, in the function to_bytes for AssemblerInstruction, place this:

while results.len() < 4 {
    results.push(0);
}
just after this block:
for operand in &[&self.operand1, &self.operand2, &self.operand3] {
    if let Some(token) = operand {
        AssemblerInstruction::extract_operand(token, &mut results, symbols)
    }
}

Some Convenience Opcodes

I’ve added in two new opcodes:

  • INC: Increments the value in the register provided as an operand by 1

  • DEC: Decrements the value in the register provided as an operand by 1

I’ll leave the implementation to you, or you can look in the code on GitLab. These instructions are useful for loops in assembly.

End

That’s for all this interlude!


If you need some assistance with any of the topics in the tutorials, or just devops and application development in general, we offer consulting services. Check it out over here or click Services along the top.