There are four indexed addressing modes on the MOS 6502. I’ve found the last one, indirect indexed, the most useful in my high-res graphics mode experiments on the Apple II+, but wanted to write about them all a bit. There are interactive examples at the end of this post (requires Javascript).

Absolute Indexed

STA $0100,Y

The absolute indexed addressing mode adds the contents of either the X or Y register to the memory address given. This can be used when you need to access or modify multiple memory addresses anywhere within the 16-bit address space. Note that the maximum index range is limited to 8 bits, the width of the 6502 registers.

Assuming the Y register contains $08, the above instruction will fetch the contents of $0100+$08=$0108 and store it in the accumulator.

Zero-page Indexed

STA $F2,X

The zero-page indexed addressing mode is very similar to the above, absolute indexed mode. The difference is that there is only one byte for the first argument, which results in an address that is always in the zero page. If the calculated address will fall outside the zero page, it wraps.

Assuming that the X register contains $0F, the calculated address will be $F2+$0F = $0101. This falls outside of the zero-page, which will wrap to address $01.

Note that you should normally use the X register for this addressing mode. You can use the Y register, but it only works on the X register mnemonics (LDX, STX).

Indexed Indirect

LDA ($00, X)

The syntax for using the indexed indirect instruction is shown above. $00 is an absolute address referring to memory address 0000. X refers to the contents of the X register. Note that you cannot substitute X for Y while using indexed indirect. You likewise cannot use the X register with indirect indexed. Both this and the next addressing mode must be used with the accompanying register shown in these examples.

The contents of the X register will be added to the absolute address. Assuming X contains $02, the resulting address is $00 + $02 = $02. This is the memory location from which to fetch an address and retrieve the value stored in this address.

Note that this fetches a 16-bit address in little-endian format. For example, when reading the address at $02, it will use the $02 value as the low-order byte and $03 as the high-order byte.

0002: 20 
0003: 01 

Indirect Indexed

STA ($00),Y

The last indexed addressing mode is confusingly called indirect indexed, but is different than the previous mode in the order of operations. In the previous addressing mode, the index was added before reading the address. In indirect indexed, the register is added after the indirect address is read. (Confusing? It’s hard to explain too. 😵‍💫)

For example, indexed indirect would allow you to select a 16-bit address out of a table, while indirect indexed would allow you to iterate through memory after the 16-bit address is fetched. Paying close attention to the parentheses may help clarify this.

When provided with the zero-page address $00, this address is used as the low-order byte. The next address, in this example $01, is used as the high order byte. The contents of the y register are then added to this 16 bit address, allowing for indexed reference anywhere in the 6502’s memory space.

The last interactive example uses this to loop through memory. Modifying the address in the zero-page would also allow you to iterate through more than 256 values.

Summary

I found the indirect indexed mode the most useful when working with high-res graphics mode on the Apple II. A single page of HGR memory is $2000 (or 8192!) bytes long. All of these modes are useful for different situations, though.

The below 6502 assembler/emulator has been adapted from the source of the 6502js project, by Nick Morgan. The modified source is available here.

Examples:
Assembler:

Updated: