Day 25 - Other Instructions
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:
1) The carry (C) flag before the instruction is saved (how?, dunno, just is).
2) The byte (A or Memory) is shifted one in the specific direction (L=Left,R=Right).
3) The bit shifted out is put into the C flag.
4) 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...)
1) A-"the byte being compared" is done and saved (how/where?, dunno)
2) If the result (the saved thing) is zero, Z flag is set.
3) The N flag is set to bit 7 of the result.
4) 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
Intro - Day 26