What is the practical use of indexed indirect addressing?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

truffly
Posts: 7
Joined: Wed Jul 18, 2018 1:50 pm
Contact:

What is the practical use of indexed indirect addressing?

Post by truffly »

Hello all,

I was recently working on an NES project, and I realized I really needed some pointers in order to deal with a graphics buffer. As such, I am using indirect indexed addressing with the Y register -- for example,

Code: Select all

lda (zp), y
I can understand very practical uses for this--you load in a ZP address, and it uses that byte and the subsequent byte as a pointer to the address you want to access; from there, it uses the Y register as an index. This seems very useful, as it lets us point to, for example, an array, and access an element from the array using the Y register.

But why would you ever need to use indexed indirect addressing with the X register? What practical purpose does this serve? There has to be some situation where this feature would prove useful, otherwise I'd assume it wouldn't be featured in the processor design. Have you ever used indexed indirect addressing in your programs? Do you think it is particularly useful, or do you think indirect indexed addressing is a better tool?

Thanks in advance for the replies!
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: What is the practical use of indexed indirect addressing

Post by lidnariq »

much as lda (zp),y lets you take a pointer and add Y to it, lda (zp, x) lets you load one of multiple different pointers.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What is the practical use of indexed indirect addressing

Post by tokumaru »

truffly wrote:But why would you ever need to use indexed indirect addressing with the X register? What practical purpose does this serve?
That is indeed the least used addressing mode in the 6502, but there are a few cases where it may be useful. The intended use is obviously for when you have an array of pointers, so you can use X to select which pointer to use. One common example often mentioned here is sound engines, which have to handle multiple tracks, so it may be convenient to select the track to read using the X register, which you can also use to access other word-sized attributes/states of each track.

It basically allows access to multiple streams that are supposed to be read sequentially, meaning that there's no need to preserve the base address and you can simply increment the pointers themselves in order to move on to the next item.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: What is the practical use of indexed indirect addressing

Post by dougeff »

With (zp, x) mode, remember that the table of pointers needs to be in the zeropage, because it wraps back into the zeropage. Also, you need to Inx twice to switch between them.

Correct me if I'm wrong, it's been a while since I used it.
nesdoug.com -- blog/tutorial on programming for the NES
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: What is the practical use of indexed indirect addressing

Post by tepples »

For example, in my Pently audio driver, because audio channels' MMIO ports in $400x are 4 apart, the pointers stored in zero page are also 4 bytes apart.

Code: Select all

; Pently persistent zero page layout
;       +0                +1                +2                +3
;  0  | Sq1 sound effect data ptr           Sq1 music pattern data ptr
;  4  | Sq2 sound effect data ptr           Sq2 music pattern data ptr
;  8  | Tri sound effect data ptr           Tri music pattern data ptr
; 12  | Noise sound effect data ptr         Noise music pattern data ptr
; 16  | Sq1 envelope data ptr               Attack music pattern data ptr
; 20  | Sq2 envelope data ptr               Conductor track position
; 24  | Tri envelope data ptr               Tempo counter
; 28  | Noise envelope data ptr             Play/Pause        Attack channel
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: What is the practical use of indexed indirect addressing

Post by koitsu »

Question better-suited for 6502.org forum, as it's about 6502 and not so much NES.

In general, indirect indexed ((foo),y) is more useful given that it allows you to address the entire 64KByte memory space. That said:

A simple jump table is one of the most common uses of the indexed indirect addressing ((foo,x)) mode. Example routine, where you load the "table index" into the accumulator in advance (ex. lda #4 / jmp doit):

Code: Select all

doit:
  asl
  tax
  jmp (table,x)
  ...

table:
  .dw routine1
  .dw routine2
  .dw routine3
  .dw routine4
  .dw routine5
  .dw routine6
  ...
There are tons of ways you can accomplish the above differently. It all depends on use cases and programmer/developer choice. It is impossible to know each and every one of them. OP asked for one, so there it is. If you want others, just ask, but they're all generally the same -- all use-cases that are table-based, particularly a table of pointers.

"Programming the 6502" by Rodney Zaks, 1983, has several examples of where indexed indirect addressing is useful.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: What is the practical use of indexed indirect addressing

Post by FrankenGraphics »

Just maybe, you could additionally use the addressing mode to prefetch a strip of data (or cherrypick data here and there into a strip) at a time when you have plenty of time to do so, in order to read the resulting strip from zp at another time when you don't have as much time, using indexed indirect. That is, if you have the zp to spare.

Some games use a soubroutine handler that load pointers piecemeal and then go to them based on some return value from a subroutine. Instead, you could maybe rather load a whole strip of them this way. An then, if one of the pointed-to subroutines needs to modify what's next in order, it can do so, either by modifying next pointer, or the simply the x register, before returning. The "what's next" handler will just step on to the next or specified pointer cluelessly. It makes for a simple "what's next routine", i think... I'm clearly not an expert.

Basically: you lay out a preliminary string of pointers that is the basic marching order of a section of the program, and then the subroutines will evaluate something and for example modify the what's next counter or a cell within the strip.


Edit: "Pre-indexed indirect addressing is useful for choosing one of a set of indirect addresses to use" -Lance Leventhal, in 6502 assembly language programming, page 3-10. So yeah, what everyone basically already said. The book also contains atomic examples of using CMP and EOR with indexed indirect, but they seem to be mostly there to explain what is happening if you use it. They aren't part of any explanation why you might want to do that.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What is the practical use of indexed indirect addressing

Post by tokumaru »

koitsu wrote:

Code: Select all

jmp (table,x)
The original 6502 can't do that, though... That's probably a 65816 thing.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: What is the practical use of indexed indirect addressing

Post by FrankenGraphics »

yeah... the book i just read from confusingly stated that jmp could be seen as indexed indirect, but that x is always 0. That's one weird way to put that it is not indexed indirect, haha. But the rule for jmp stands.

Instructions that can use indexed indirect:
ADC
AND
CMP
EOR
LDA
ORA
SBC
STA
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: What is the practical use of indexed indirect addressing

Post by koitsu »

tokumaru wrote:
koitsu wrote:

Code: Select all

jmp (table,x)
The original 6502 can't do that, though... That's probably a 65816 thing.
My apologies, you're right, the 6502 cannot do this. The indirect indexed addressing mode for jmp was introduced in the 65c02, thus the 65816 has it as well.

It's not the first time I've made this mistake publicly. Those that know me well know I often "screw up" some opcodes when doing 6502 in this way. This is because when I first started doing 6502, I actually started on an Apple IIE, which was a 65c02, which has several additional instructions and opcodes with additional addressing modes (inc a / dec a or just inc / dec, instead of clc / adc #1 or sec / sbc #1 is the most well-known). About 6 months later I started doing work on an Apple II+ (6502), followed by 6-8 months later getting an Apple IIGS (65816). So, my brain tends to have a memory of 65c02/65816 addressing modes and instructions. It's very easy to forget which (of the more basic) aren't available on the 6502.

That said: I can quote some examples from the book I referenced if asked (and that is a pure 6502 book).
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: What is the practical use of indexed indirect addressing

Post by FrankenGraphics »

Please do! This stuff is interesting, especially as my book is quite sparse on practical examples.

From MOS technology's own reference manual:
"An attempt to define problems to take advantage of this shorter memory and execution time by defining fields should be investigated first. However, in almost every program, the same operation must be performed several times. In those cases, it is sometimes more useful to define a subroutine and set the values that the subroutine will operate on as fields in memory. Pointers to these fields are placed in the Zero Page of memory and then the indexed indirect operation is used to perform the function. This is the primary use of the indexed indirect operation. "

It also specifically but very briefly mentions "polling I/O" and "string processing".
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: What is the practical use of indexed indirect addressing

Post by pubby »

If Y is tied up you can set X to zero and use it as a worse way to pointer dereference. That's what I use it for.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What is the practical use of indexed indirect addressing

Post by tokumaru »

pubby wrote:If Y is tied up you can set X to zero and use it as a worse way to pointer dereference. That's what I use it for.
Yeah, I've done that too.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: What is the practical use of indexed indirect addressing

Post by Bregalad »

tepples wrote:For example, in my Pently audio driver, because audio channels' MMIO ports in $400x are 4 apart, the pointers stored in zero page are also 4 bytes apart.

Code: Select all

; Pently persistent zero page layout
;       +0                +1                +2                +3
;  0  | Sq1 sound effect data ptr           Sq1 music pattern data ptr
;  4  | Sq2 sound effect data ptr           Sq2 music pattern data ptr
;  8  | Tri sound effect data ptr           Tri music pattern data ptr
; 12  | Noise sound effect data ptr         Noise music pattern data ptr
; 16  | Sq1 envelope data ptr               Attack music pattern data ptr
; 20  | Sq2 envelope data ptr               Conductor track position
; 24  | Tri envelope data ptr               Tempo counter
; 28  | Noise envelope data ptr             Play/Pause        Attack channel
This is pure genius !! I never tought of doing things like this before.
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: What is the practical use of indexed indirect addressing

Post by calima »

pubby wrote:If Y is tied up you can set X to zero and use it as a worse way to pointer dereference. That's what I use it for.
That's one more thing the later processors fixed, they have jmp (ptr).
Post Reply