Movement Instructions I

We begin our tour de force of the implementation of the actual assembly language instructions in our fictitious machine with the instructions used for moving data around in the machine.

We start with LDA, which according to its description in emulate.h, is supposed to load the accumulator with a value from memory. The value to be loaded is specified by giving its address in memory as an operand to the LDA instruction. As a side effect of executing this instruction, we also want the flags in our machine to be updated, based on what that data was, i.e. whether it was zero or positive or not.

Just looking at the implementation, you might think that something is missing. Since we just refer to MEM. But this is not a mistake. The definition of MEM is actually given somewhere else. Look at the top of the file, and you will see a line which reads:

#define MEM fetch(fetch(MC->IP+1))

Welcome to the world of the C preprocessor! This part of your C compiler is responsible for dealing with lines like this one. The purpose of the #define preprocessor directive, is to allow the construction of macros.

In this instance, before a single line of C code is compiled, the C preprocessor goes through and replaces every instance of the word MEM, with what follows-na it in the #define.

Let's look at what MEM stands for, then. It calls the function fetch, which as we know, retrieves 16 bits of data from memory at the address specified. But which address do we tell it to use? Well, that again is fetched from memory, since the address we want to use will be specified as an operand to the current instruction of the assembly language program being executed; and that program, is itself stored in our machine's memory. Thus we need to dip into the memory which holds our assembly language code, and pull out the data from that operand.

But now, where are we going to get the address of the piece of our program code which contains this operand? Fortunately, that is easy. It will be the very next memory location after the current instruction, since it is an operand for that instruction. Therefore it will be the memory location immediately after the one pointed to by the instruction pointer.

Sound confusing? Well, C can get like that. We want something, which is pointed to by something, which is pointed to by something else, etc. This is a particularly bad case, because we are mixing two languages and two machines.

But, to recap. The operand to the LDA instruction is stored at the (fictitious) memory address immediately following the LDA instruction itself. We fetch that operand by using fetch() with the instruction pointer plus one, as the memory location. Now that operand itself consists of a memory location - the location of the data we (or the assembly language programmer) actuallys want to load into the accumulator. So we then use fetch again, to get the data at that specified location.

Since other instructions will want to do precisely the same data fetch, we write the whole thing up as a macro, and simply call it MEM, using a #define. Clear as mud?

Returning now to our implementation of the LDA instruction, we can clearly see where the data is coming from, and it should be apparent where it is going. It simply gets put into the accumulator, which is just a field inside our machine structure.