650Vue Part 5: Registers, Memory, and Vuex
From this point forward, I'll be talking about 650Vue from a technical perspective, but I won't go into every aspect of 650Vue in extreme detail; I'm not here to teach Vue, nor am I here to explain 6502 architecture and assembly programming. If you'd like to learn more about any of the topics that I gloss over, there are excellent resources online:
The actual code that makes up 650Vue went through a number of changes as I experimented with various approaches, tried several things (many of which did not work), committed and backed out numerous changes. What you see on these pages will be an idealized description of 650Vue's development; if you look at the project's commit history in GitHub, you'll observe that my development process can be quite messy.
The architecture of the 6502 is simple. If we want to model the state of the 6502, we only need to keep track of six registers (labelled in red in Figure 1), occupying 7 bytes worth of data. The registers called AC, XR, YR, SP, SR all store one byte or 8 bits. PC requires 16 bits, made up of two 8-bit segments called the low and high bytes).
These are the 6502's registers:
- AC (accumulator): the accumulator is the 6502's "workhorse" register, and plays a central role in any non-trivial machine language program. The accumulator is where the results of arithmetic operations get stored, although the 6502 has limited arithmetic abilities—it can only add, subtract, and perform bitwise OR and AND operations on values between 0 and 255.
- XR and YR (X- and Y-registers): the X- and Y- registers are index registers, used for counting, keeping track of loops, and as offsets for indirect memory access. XR and YR are roughly interchangeable, although XR can be used in a few contexts where YR cannot.
- SP (stack pointer): the stack is a fixed 256-byte stretch of memory used as temporary storage. You push values onto the stack to store them and pull them back later when you need them. The stack pointer keeps track of where the next push should go or the next pull should come from.
- SR (status register): the status register is a collection of single-bit flags, each of which can be 1 or 0. You can fit 8 bitwise flags into a single byte, but the 6502 only uses 7.
- PC (program counter): the program counter tells the 6502 where to find its next instruction in memory. This register is 16 bits wide, meaning it can hold values from 0 to 65,535, representing 64K of memory.
I want to define a bunch of variables to keep track of those registers, although in Vue.js, I could get all fancy and say I want to persist the application state. Vue's standard tool for state management is called Vuex. For now, I just need to set up a store to hold my registers; I'll be doing more with these values later. In Vuex, I define my store as in Figure 2:
The simple store outlined in Figure 2 contains almost everything we need to simulate our computer:
five 8-bit registers, one 16-bit program counter, and a big array with 64k cells to simulate RAM. I've
bundled the registers into a single object called
cpu. I'll add two additional variables
to the store in future updates, but what you see above is pretty much it.
I initialize the registers with random values because if I understand the documentation correctly, the 6502's registers are supposed to be in an unspecified state until a hardware reset is applied. Random numbers may not be authentic, but they are at least interesting to look at. I fill the RAM array with 65,536 zeros to represent empty memory.
In the next section, I will connect the Vuex store to some front end components, so that we can look at the registers in our web browser.