What happens with variables whose locations are determined at run-time? There are three categories of variables like this:
How do you use indexed addressing? First, concepts relating the ideas to a high-level langauge.
Something that makes this more convenient is the fcb
assembler directive. You can define symbols for all the offsets and
for the size of the object, and refer to the symbols later.
Let's look at a quick example of doing index addressing. We are just going to sum the values in a small table. First let's look at what the C pseudocode code loop would look like:
i = tablelen-1;
while (i != 0) {
sum += table[i];
i--;
}
And now the assembly code (we'll assume the table we are summing is in EEPROM so we don't have to worry about initializing it):
RAM equ $0010
EEPROM equ $f800
CONSTS equ $f900
TABLES equ $fa00
RESET equ $fffe
org RAM
cnt rmb 1
sum rmb 1
org CONSTS
tabst fdb TABLES
tablen fcb 6
org TABLES
table fcb 1, 2, 3, 4, 5, 6
org EEPROM
start ldx tabst * Load start of table
ldaa 0, X
staa sum * add value from table to sum
ldaa tablen
deca
staa cnt * save counter
loop beq done * while (cnt != 0) {
inx
ldaa sum
ldab 0,x
aba * sum = sum + table[x]
staa sum
ldaa cnt
deca
staa cnt * cnt--;
bra loop * }
done
mloop bra mloop
org RESET
fdb start
Now let's improve the code to make it more efficient and closer to the actual algorithm that we started with:
RAM equ $0010
EEPROM equ $f800
CONSTS equ $f900
TABLES equ $fa00
RESET equ $fffe
TABLELN equ 5
org RAM
sum rmb 1
org CONSTS
tablen fcb TABLELN+1
org TABLES
table fcb 1, 2, 3, 4, 5, 6
org EEPROM
start clr sum
ldx #table
ldaa tablen
loop beq done * While (a != 0) {
ldab TABLELN,x
addb sum
stab sum * sum += table[a-1]
dex
deca * a--;
bra loop * }
done
mloop bra mloop
org RESET
fdb start
$ff
, see
later.
,x
or
offset,y
to use indexed addressing.
You say
ldx #label
ldy #label
to load a known address to the index register (as usual, you need to
be careful about addressing modes).
The index registers are capable of very little arithmetic. You can
increment them, you can decrement them, you can add the B accumulator
to either one, you can load them, you can store them, you can exchange
them with D, you can transfer them back and forth to the stack pointer.
That's pretty much it.
y
index register also gives us an opportunity
to learn about a standard hack that manufacturers apply to their
instruction sets to expand them beyond the limitations of their
original design: a prefix byte.
Early members of the Motorola 6800 family only had a single index
register: the x
register. When they wanted to add a
second index register, they had a problem: their were too many
instructions using indexed addressing to just add that many new op
codes to the instruction set. This left them with two choices: they
could either cripple the new y
index register, leaving it
capable of doing less than the x
index register, or they
could put a prefix byte into the instruction set. A prefix
byte is a byte that ``adjusts'' what the instruction does....
One very important use of indexed addressing on the HC11 is the case
where you want to use the various bit-twiddling instructions (like
bset
, brset
, and their friends) to examine
or control devices. Unfortunately, the devices are in a block
starting at $1000
, and those instructions don't support
extended addressing. So, you can set one of the index registers to
point to $1000
, and use a one-byte offset to specify the
particular device control register.
Here's another example of hand-compiling a program for the HC11 to sum the absolute values of the elements of a buffer. I'm going to use a buffer instead of an array here, because it translates more directly to assembly code.
sum = 0;
pnt = bufstrt;
while (pnt != bufend) {
if (*pnt < 0)
sum = sum - *pnt;
else
sum = sum + *pnt;
pnt++;
}
And now the assembly code (we'll assume the array we are summing is in EEPROM so we don't have to worry about initializing it):
RAM equ $0010
EEPROM equ $f800
RESET eqy $fffe
org RAM
sum rmb 1
org EEPROM
bufstrt fcb 5, -2, 7, -3, 6, 5
bufend
start clra * initialize sum
ldx #bufstrt * pnt = bufstrt
loop cpx #bufend
beq done * while (pnt != bufend ) {
ldab 0,x
bge noneg * if (*pnt < 0) then
sba * sum = sum - *pnt;
bra eloop
noneg aba * else sum = sum + *pnt;
eloop inx * pnt++;
bra loop * }
done staa sum * store sum
mloop bra mloop
org RESET
fdb start