Needle in the (hay)Stack


Our capstone project continues to hum along thanks to my amazing team. We finished our first half of the project (building out i8080 emulator opcodes) ahead of schedule and only had debugging left to progress onto our second half (building out the virtual machine with graphics & sound). The checkpoint between these two main phases of the project was running our emulator and getting to an infinite loop around 50,000 instructions later. We didn’t quite make it that far, however, after all our opcodes should have been implemented. We had testing for each of these, and they all passed, so it was very difficult to figure out where we were going wrong.

Unfortunately, the only real way to debug at this stage was to step through the program and look at register/state/flag data at each step and compare to a known-working emulator (https://bluishcoder.co.nz/js8080/ was the one I used). This was about as tedious as it sounds, but it was really the only way. As I stepped through the program instruction-by-instruction, I really gained an appreciation for the amount of work modern languages are doing under the hood. Loading an image into the memory, for example, is done byte-by-byte with a couple of nested loops. This leads to thousands-upon-thousands of lines of output for very basic instructions that we generally might take for granted. After stepping through a few hundred of these, I realized our first mistake: we were incrementing the value of the l register with the previous value of the e register. This was clearly a copy-paste error and an easy one to make, given the single-letter difference.

That fix got us quite a bit farther through the emulation, but we still weren’t making it to the infinite loop. After blasting through many thousands of lines of cpu state output, I was able to find the other bug: in instructions 0x32 and 0x3a, we were pulling data from the program counter pointer instead of the stack pointer. Again, this was a difference of a couple letters, so it was very hard to see unless you knew what you were looking for. After changing these opcodes to work as intended, we made it to the infinite loop! Checkpoint achieved!

Next on our docket is to create a GUI, I/O via Keyboard, and Sound of a machine using only Rust, SDL2, and the command line. We’re dangerously close to the finish line, and learning a ton every step of the way!

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *