When the 6502 refers to addressing modes, it really means "What is the source of the data used in this instruction?" The 6502's data book divides the addressing modes into 2 groups, indexed and non-indexed. That seems to be a logical way to discuss them, so I'll stick with that.
Most of the addressing modes are used to access memory, but 3 do not.
These instructions have register A (the accumulator) as the target. Examples are
LSR A and
These instructions have their data defined as the next byte after the opcode.
ORA #$B2 will perform a logical (also called bitwise) of the value B2 with the accumulator. Remember that in assembly when you see a # sign, it indicates an immediate value. If $B2 was written without a #, it would indicate an address or offset.
In an implied instruction, the data and/or destination is mandatory for the instruction. For example, the
CLC instruction is implied, it is going to clear the processor's Carry flag.
Relative addressing on the 6502 is only used for branch operations. The byte after the opcode is the branch offset. If the branch is taken, the new address will the the current PC plus the offset. The offset is a signed byte, so it can jump a maximum of 127 bytes forward, or 128 bytes backward. (For more info about signed numbers, check here.)
Absolute addressing specifies the memory location explicitly in the two bytes following the opcode. So
JMP $4032 will set the PC to $4032. The hex for this is
4C 32 40. The 6502 is a little endian machine, so any 16 bit (2 byte) value is stored with the LSB first. All instructions that use absolute addressing are 3 bytes.
Zero-Page is an addressing mode that is only capable of addressing the first 256 bytes of the CPU's memory map. You can think of it as absolute addressing for the first 256 bytes. The instruction
LDA $35 will put the value stored in memory location $35 into A. The advantage of zero-page are two - the instruction takes one less byte to specify, and it executes in less CPU cycles. Most programs are written to store the most frequently used variables in the first 256 memory locations so they can take advantage of zero page addressing.
The JMP instruction is the only instruction that uses this addressing mode. It is a 3 byte instruction - the 2nd and 3rd bytes are an absolute address. The set the PC to the address stored at that address. So maybe this would be clearer.
Memory: 1000 52 3a 04 d3 93 00 3f 93 84 Instruction: JMP ($1000)
When this instruction is executed, the PC will be set to $3a52, which is the address stored at address $1000.
The 6502 has the ability to do indexed addressing, where the X or Y register is used as an extra offset to the address being accessed.
This addressing mode makes the target address by adding the contents of the X or Y register to an absolute address. For example, this 6502 code can be used to fill 10 bytes with $FF starting at address $1009, counting down to address $1000.
LDA #$FF LDY #$09 loop: STA $1000,Y ; absolute indexed addressing DEY BPL loop
This works just like absolute indexed, but the target address is limited to the first 0xFF bytes.
The target address will wrap around and will always be in the zero page. If the instruction is
LDA $C0,X, and X is $60, then the target address will be $20. $C0+$60 = $120, but the carry is discarded in the calculation of the target address.
This mode is only used with the X register. Consider a situation where the instruction is
LDA ($20,X), X contains $04, and memory at $24 contains
0024: 74 20, First, X is added to $20 to get $24. The target address will be fetched from $24 resulting in a target address of $2074. Register A will be loaded with the contents of memory at $2074.
If X + the immediate byte will wrap around to a zero-page address. So you could code that like
targetAddress = (X + opcode) & 0xFF .
Indexed Indirect instructions are 2 bytes - the second byte is the zero-page address - $20 in the example. Obviously the fetched address has to be stored in the zero page.
This mode is only used with the Y register. It differs in the order that Y is applied to the indirectly fetched address. An example instruction that uses indirect index addressing is
LDA ($86),Y . To calculate the target address, the CPU will first fetch the address stored at zero page location $86. That address will be added to register Y to get the final target address. For
LDA ($86),Y, if the address stored at $86 is $4028 (memory is
0086: 28 40, remember little endian) and register Y contains $10, then the final target address would be $4038. Register A will be loaded with the contents of memory at $4038.
Indirect Indexed instructions are 2 bytes - the second byte is the zero-page address - $20 in the example. (So the fetched address has to be stored in the zero page.)
While indexed indirect addressing will only generate a zero-page address, this mode's target address is not wrapped - it can be anywhere in the 16-bit address space.← Prev: 6502-emulator Next: 6502-disassembler →
Post questions or comments on Twitter @realemulator101, or if you find issues in the code, file them on the github repository.