[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: LDA OpCode Question
- Subject: Re: LDA OpCode Question
- From: dempson@actrix.gen.nz (David Empson)
- Date: Tue, 16 Jul 2002 02:14:10 +1200
- Newsgroups: comp.sys.apple2
- References: <1poY8.107750$iX5.5032987@bin3.nnrp.aus1.giganews.com>
- User-agent: MacSOUP/2.5b1 (Mac OS X version 10.1.5)
- Xref: archiver1.google.com comp.sys.apple2:21304
Bryan Parkoff <BParkoff@satx.rr.com> wrote:
> LDA OpCode Question
>
> I tried to tell 65816 that 65816 can read data from bank $01 by using
> local address instead of long address. For example below:
>
> 00/2000: JSR $FC58
> 00/2002: JSL $012000
> 00/2007: RTS
The above code is risky. You cannot safely execute code outside of bank
0 if the 65816 is in emulation mode, unless you disable interrupts for
the entire duration of executing code outside bank 0.
If an interrupt occurs while in emulation mode, the program bank
register will not be saved, and the code will resume executing in the
wrong bank after the interrupt is complete.
Add an SEI before the JSL $012000, and a CLI after it (or better still:
PHP and SEI first, then PLP afterwards).
> 01/2000: LDX #00
> 01/2002: LDA 2100,X
This LDA instruction is using absolute addressing mode, which accesses
the current data bank. As you haven't set the data bank explicitly, it
is almost certainly 0, so this instruction will be loading the
accumulator from $002100+X.
If you want to access data in another bank using absolute addressing,
you have to set the data bank register. I'd suggest doing PHB first to
save the current data bank, then PHK PLB to set the data bank to match
the code bank, and end with a PLB before returning.
Better still, avoid executing code in bank 1 at all, and just use
absolute long indexed addressing for this instruction as well, or leave
the code in bank 0 and set the data bank register to point to bank 1.
> 01/2005: STA 002100,X
> 01/2009: INX
> 01/200A: CPX #10
> 01/200C: BEQ 2010
> 01/200E: BRA 2002
These two branch instructions could be reduced to a single BCC 2002.
> 01/2010: RTL
> 01/2100:"Bryan Parkoff..."
> It does not work because LDA 2100,X is the local address in bank $01.
No, it doesn't work because the data bank register contains zero, so you
are reading the bytes from bank 0 (and promptly writing them back to the
same location).
> It forces me to use LDA 012100,X instead of LDA 2100,X that is the long
> address in bank $01. Look like below.
>
> 01/2000: LDX #00
> 01/2002: LDA 012100,X
> 01/2006: STA 002100,X
> 01/200A: INX
> 01/200B: CPX #10
> 01/200D: BEQ 2011
> 01/200F: BRA 2002
> 01/2011: RTL
Yes, that will work, because you are specifying the bank explicitly.
> Do you notice that BEQ and BRA are local addresses in bank $01?
Branch addresses are always relative to the program counter within the
current program bank. You cannot cross a bank boundary with any kind of
branch, nor an absolute JMP or JSR, nor an RTS - only JML, JSL, RTL and
interrupt/RTI can change the code execution bank.
> Does 65816's rule always state that all long address LDA/STA must be
> used in bank $01 to $FF except local address LDA/STA must be in bank $00.
No, absolute addressing uses the data bank register (B) to determine
which bank is to be accessed. It typically set using a PLB instruction
(pull B from stack), and can be saved using PHB (push B to stack).
If you are using absolute indexed mode with a large enough base address
plus index (e.g. LDA FFFF,X with X equal to 01 or higher) it is possible
to index past the end of the bank - assuming X was 01, this instruction
would access location 0 in the bank after the one which is referenced by
the data bank register.
> If this rule is true that bank $00 is always default for LDA $12, LDA $1234,
> etc.
LDA $12 is a different situation again. That is direct page addressing,
which uses the D register as a base address, and it can only access
locations in bank 0. (The data bank register is ignored, and indexing
will wrap around within bank 0.)
--
David Empson
dempson@actrix.gen.nz