C Pointers in HC11
Pointers in the C programming language, or references in the Java language, are variables that "point" to a data variable -- they are not data themselves (though they are variables!). How would you create a pointer variable on the HC11?. Well, the only addressing mode that allows an instruction to access changing memory locations is the Indexed addressing mode. We've used it up til now to access arrays -- the changing address just stepped through (or accessed) the different elements in an array.
We can use indexed addressing mode to create pointers. Consider the following C code:
int i;
int *pi;
i = 4;
pi = &i;
*pi = i + 3;
Let's translate this into HC11 assembly language. First, the data declarations:
ORG $0000
i RMB 1
pi RMB 2
The variable i is just one byte because the HC11 uses 1-byte integers (mostly). But why is pi two bytes? Well, pi must "point" to some data location, and thus it must hold an address. On the HC11, addresses are 16 bits, or 2 bytes. Now let's add some code, for all but the last C statement:
ORG $0000
i RMB 1
pi RMB 2
ORG $F800
start LDAA #4
STAA i
LDX #i
STX pi
So, what is going on here? Well, the first two instructions are easy. They load the A register with a constant 4, and store it into the variable i (what is the addressing mode?). The next instruction looks odd, but it is correct. It loads the value of the label i -- not the value of the variable i -- into the X register. Think of this instruction as the "&" operator -- in fact, when C programmers speak, they say "address of" to denote the "&" operator. Remember, all labels are address values, so the X register now has the address $0000 in it. We store this address into the variable pi with the next instruction. The variable "pi", which holds an address, is now "pointing to" the variable i! This is exactly how a pointer variable operates. When it comes down to the machine instruction level, a pointer (or reference) variables is really a variable that holds the address of another variable.
So how do we write machine code to do the last statement. Well, we show it here, added onto the previous code, so what is shown below is the whole program:
ORG $0000
i RMB 1
pi RMB 2
ORG $F800
start LDAA #4
STAA i
LDX #i
STX pi
* everything below here is for the last statement,
* and it does not assume the values are already in registers
LDAA i
ADDA #3
LDX pi
STAA 0,X
Alright, so the last four instructions implement the last C statement. And notice that we did not assume that register X had the value of pi or register A had the value of i (even though they do). The four instructions implement the last statement "from scratch", so that you can see what is going on.
The first of the four instructions simply loads the value of variable i
into A. It uses direct addressing to do this. The second instruction
adds the constant 3 to that value in A. The third instruction loads the
value of the variable pi into X (it uses direct addressing to do this).
Think of this third instruction as the "*" operator. Finally, the
value in register A is stored into the location that pi points to --
that is, the variable i.