Bryan Parkoff 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