Examining Memory

Today is kind of a big update, and not all the source code will be presented in-line here in the blog post. As always, you can look at the current source Here at GitHub.

Good news, everyone! After quite a lot of hacking, I can examine memory with my monitor. It’s a very primitive feature, right now: I can only examine one byte at a time, so I can’t dump memory regions yet. But hey, it’s a good start. Let’s dive into the code.

Here’s the entry point, where the CPU jumps after being reset:

The code starts by making sure interrupts are disabled, then clears the Decimal Mode flag and sets the stack pointer to $01FF (it could be anywhere when the processor starts up!). Following that is the IO initialization routine, which is probably pretty familiar by now. We just set up the ACIA for 9600 baud 8-N-1 communication.

Then things start to get more interesting:

Here, we’re clearing the entire contents of Page 2 ($0200 to $02FF) in order to use it for scratch space. I’m using page 2 to store whatever the user types on the command line, which I’m referring to as IBUF (the Input Buffer). I’ve named this entry point HRESET, in case I want to be able to jump to it directly in a future version of the monitor.

Next, we welcome the user and start looping on input, parsing one line at a time.

There’s kind of a lot going on in this code, so let’s take it a little bit at a time.

At the very start, we print out a message (using our STR macro) that welcomes the user. Then, we print a “*” prompt, do some housekeeping, and finally wait for input. It looks like this when it’s running:

Running

EVLOOP is the main Eval Loop that takes a line of input and handles it. The NXTCHR block is the meat of this code. Every time a key is pressed, the character is appended to the IBUF input buffer, located at $0200. We’re using the Y register as a pointer into the buffer.

If the user ever presses the backspace key, there’s a separate routine that handles that. It decrements the Y pointer and echoes the backspace character to the terminal.

And when the user presses ENTER (which generates a Carriage Return/Line Feed combo), we jump immediately to the PARSE parsing code to handle the command.

And this is where I totally cheat:

This is a lot to take in, I know. But basically, it parses the command into two parts: A one-letter command, and a one- to four-letter operand.

The idea is that a user should be able to enter a command like this:

and be able to see the contents of memory address (“examine”) $01FF. I’m cheating because I totally ignore the value of the first letter, the “E” — right now, ONLY the examine command is implemented, you could use any letter in place of E. Ssshhhhh, don’t tell anyone. I’ll fix that later. Really.

But the rest of the code is not cheating. It works by using two pointers, Y and X, to walk the input buffer until the operand is found. When it is, Y will point at the start of the operand. Then we increment the second pointer, X, until it’s pointing at the end of the operand. At that point, we start taking the operand backward, one character at a time, and convert it from hex to binary. The value is stored in page zero in locations OP1H (high byte) and OP1L (low byte). If the input is malformed or isn’t hexadecimal, we abort by printing “?” to the console and then jumping back to the EVLOOP entry point.

When the operand has been decoded, we call another routine, PRADDR, to print the address, followed by a colon and space. Then, finally, we use PRBYT to print the contents of the memory at the desired address. Whew, that’s a lot of code. I haven’t shown the implementation of PRADDR or PRBYT here, but the source, as always, is up on GitHub. Feel free to dig through it if that’s your thing.

When running, it looks like this:

In Use

That’s plenty for one day. I hope to refactor this code a little and clean it up tomorrow, so I can start adding more commands.

One thought on “Examining Memory”

Comments are closed.