Other Instructions
Before we go
These are the remaining instructions on the 6502 that I haven't mentioned
yet or explained in detail.
Addressing Modes
I ought to go over the addressing modes, so we are clear on how those work...
- Implied
- The address mode is implied (like NOP, there isn't an address mode or
asl (asl a, sometimes) where A is used without it being mentioned in the
instruction.
- Immediate
- Example: lda #$3. Loads A with 3. Simple. You should know immediate mode...
- ZP
- Things like "lda $88" are zero page, called zero page because the
addresses are $0000-$00FF (the high byte is the page). It is faster
(slightly) and uses less PRG space (1 byte for ZP addresses) to use Zero
Page instead of the Absolute address (which would add another zero
byte.)
- Absolute
- Example: lda $0332. Use absolute addressing when reading memory that isn't in page zero.
- ZP Indexed
- Things like "lda $10,X" or "lda $B,Y" are indexed, meaning that A is
loaded with the byte at the address (Must be a zero page address (1 byte))
+ either X or Y, so if you do "lda $10,X" when X is 5, A will be loaded
with the byte at zero page address $15. Note that if you do "lda $FF,Y" (Y
or X doesn't matter, except that fewer instructions can use Y as an index),
when Y is 5, you don't get the byte from $0104, you get it from $04 (zero
page indexed wraps).
- Absolute Indexed
- Pretty much the same as ZP Indexed, except there's no wrapping and the
address can be 2 bytes (i.e. a full absolute address). Not sure what
exactly happens if you have an index and an address of $FFFF. Would be neat
if doing lda $FFFF,X with X swapping in another bank of RAM from
$0200-$07FF. EMS on the NES!!!
- Pre Indirect
- Example: lda ($10,X). A 1-byte ZP address is given. X is added to the
ZP Address (wrapping applies). The final ZP address is used to get an
absolute address from memory. That absolute address is then used to load a
byte into A.
- Post Indirect
- Example: lda ($10),Y. A 1-byte ZP address is given. The final ZP
address is used to get an absolute address from memory. Y is added to the
absolute address. That absolute address is then used to load a byte into
A.
- Indirect
- This addressing mode is unique to the JMP instruction. Example JMP
(label2). It's just like the indexed (Pre/Post) indirect modes, except that
there's no index, and the ZP address from the indexed indirect modes is now
an Absolute Address.
The BIT Instruction
The BIT instruction can be very useful. It does a sort of comparison...
The BIT instruction has only 2 addressing modes ZP, and Absolute.
BIT takes a byte from Memory, ANDs it with A. (note that neither A or Memory
will change). It then Sets the Z flag if the result is zero. Sets the V flag to
bit 6 of the result and the N flag to bit 7 of the result.
This instruction is commonly used to check for vblank as it uses less cycles and doesn't change A:
;--CODE--;
waitforVBLANK:
bit $2002 ; note that neither $2002 or A are written to. But N flag will
; be set if bit 7 of $2002
; is set. (bit 7 of $2002, remember that it tells if we are in VBlank).
bpl waitforVBLANK ; will branch if N flag is 0. If N flag is 1, we are
;in VBlank and are done waiting.
;--CODE END--;
The ASL/LSR Instructions
These instructions are simple shifting instructions. They will either shift
the A register or a Memory location. Note that they always shift one, and that
the bit shifted off is put into the C register. The new bit on the opposite
end will be a zero. Simple as that. (think the <<1 or >>1 in C/C++). Very
useful.
The ROL/ROR Instructions
These are just like ASL/LSR, except that it follows a slightly different steps:
- The carry (C) flag before the instruction is saved (how?, dunno, just
is).
- The byte (A or Memory) is shifted one in the specific direction
(L=Left,R=Right).
- The bit shifted out is put into the C flag.
- The old (saved) C flag is the bit that gets put onto the opposite side
of the bit that got shifted out.
Not sure why you'd use ROL/ROR, probably useful for some math routines.
How the compare really works
Here are the steps on how CMP/CPY/CPX really work (I will assume CMP, so I don't have to go A/X/Y every time...):
- A-"the byte being compared" is done and saved (how/where?, dunno)
- If the result (the saved thing) is zero, Z flag is set.
- The N flag is set to bit 7 of the result.
- The C flag is set if the result would have ended up being greater than $100 (note
that the result actually wraps to a byte).
So basically, A-byte, and then C if result >= $100 (yes, >=). N = result bit
7, and Z if result is zero.
This Day In Review
Can't think of anything else about the base instruction set of the 6502 that
I haven't mentioned yet, if there is, please tell me.
Have fun (as usual)!,
-GbaGuy