[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: EPZ directive



Guillaume Tello <houten.van@wanadoo.fr> wrote:

> hello,
> 
> i'm trying to learn 6502 asm. here is a part I don't understand:
> 
> B    EPZ $6    ; low part of adr
> BH    EPZ $7    ; high part of adr

The "EPZ" directive is only used by some assemblers (I have vague
recollection of using it in LISA, but it might have been something
else).

It is roughly equivalent to an EQU directive, equating a symbolic name
to a value, but it tells the assembler that the symbolic name must be
located on page zero, and use of that symbol will enforce zero-page
addressing rather than absolute addressing.

For example, if you had

ABSSYM EQU $0006
ZPSYM  EPZ $06

then

LDA ABSSYM would use absolute addressing (AD 06 00)
LDA ZPSYM would use zero page addressing (A5 06)

(Freaky - I still remember those opcodes. I haven't used them directly
for about 20 years.)

These particular instructions have the same effect but the first one
requires an extra byte and will take an extra cycle to execute. Some
addressing modes require the use of a zero page symbol, e.g. indirect
pre-indexed with X or indirect post-indexed with Y.  In these cases, the
symbol would have to be defined with EPZ to avoid an error.

Anyway...

> ...
>     LDA (B,X)
> 
> looking at the first two lines, I can think that the adr is $706.
> but the assembly code for LDA (B,X) is A1 06 meaning that only low part of
> the adress is used, pointing to page zero.

Nope.  There is a two byte variable called "B" at locations $06 (low
order byte) and $07 (high order byte). The "BH" symbol is used to
directly access the high order byte of "B".

The instruction "LDA (B,X)" will be converted to "LDA ($06,X)" once
assembled. This instruction does the following:

1. Take the contents of the X register.

2. Add 6 to it (wrapping around from zero again if the result of the
addition exceeds 255).

3. Uses the result as the address in zero page from which it fetches two
bytes (low order byte first).

4. The two fetched bytes are interpreted as an address, and the
accumulator is loaded from that address.

If the X register is set to zero, then the LDA (B,X) instruction will be
using the contents of B and BH (locations $06 and $07) as a pointer to
another memory location and will be loading the accumulator from that
location.

If the X register might be a non-zero value at the point this
instruction is executed, then B should be regarded as the start location
of a table consisting of multiple two-byte pointers to separate memory
locations, and X is an offset into the table of pointers (which should
be an even number).

e.g. if X contained 8 then the contents of locations B+8 and B+9 ($0E
and $0F) would be fetched as a pointer to another memory location, and
the accumulator would be loaded from that location.

I hope that makes it somewhat clearer.

This code is using the "pre-indexed indirect" addressing mode. It is
probably the least frequently used addressing mode, and is definitely
one of the harder ones to understand for a newcomer to assembly
language. It is often difficult to use to its full potential because
zero page is a valuable resource and there sometimes isn't room to store
a whole table of pointers there.

The corresponding "post-indexed indirect" addressing mode (which uses Y)
is much more common, and is much easier to understand.

Given the same definitions as above:

LDA (B),Y

This will be converted to "LDA ($06),Y" by the assembler. This does the
following:

1. Fetch the contents of locations $06 and $07, treating them as a
16-bit value (low order byte first).

2. Add the contents of the Y register to the fetched value (with carry
into the high order byte).

3. Use the result as the address of a memory location from which the
accumulator is loaded.

This is a simple case of storing the base address of a data structure
(which can be anywhere in memory) in a pair of zero page locations, and
then using the Y register as an index into that data structure.

-- 
David Empson
dempson@actrix.gen.nz