Page 1 of 1

Indirect indexed addressing

Posted: Fri Mar 12, 2010 11:59 pm
by rizz1010
Am I understanding indirect indexed addressing correctly? I am using asm6 by the way.

If I have these variables at $0400 and $0500
$0400
MyBytes .byte 0, 0, 0, 0, 0, 0

$0500
Pointer .byte 0, 0


In my code, I initialize these variables like so:
Pointer = $00
Pointer+1 = $04
MyBytes = $AA
MyBytes+1 = $BB
MyBytes+2 = $CC etc

Now, if I understand indirect indexed addressing on the 6502, I should be able to do this:
LDA (Pointer), Y
If Y = 1, then the accumulator should have $BB in it. However, it turned out that $04 was added to the accumulator, which was taken from Pointer+1 (not MyBytes+1 which I expected).



Thanks

Posted: Sat Mar 13, 2010 1:57 am
by koitsu
Let's not discuss assembler equates and so on -- they just add to the confusion when it comes to understanding a processor. Let's discuss actual 6502 operation. :-) Note the below addresses/code doesn't correlate with anything on the NES -- it's just discussing 6502...

Memory dump:

Code: Select all

$00A0: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
...
$9980: 01 23 45 67 89 AB CD EF 00 00 00 00 69 77 23 11
Code:

Code: Select all

LDY #4
LDA ($A8),Y
The first thing the CPU does is read the bytes at $A8 and $A9. $A8=88, $A9=99, so the "effective address" at this point is $9988.

The next thing the CPU does is add Y to the effective address. $9988 + 4 = $998C.

Finally, the CPU reads into the accumulator the value stored at the final effective address (that's $998C), which is value $69.

Make sense? Just verifying you truly understand how post-indexed indirect addressing works.

Your description of the problem almost makes sense, except you say "turns out $04 was added to the accumulator", which makes no sense whatsoever.

My advice is to use asm6's -l (that's dash-ELL) flag to generate an assembly listing, which will tell you exactly what the assembler is doing with your code and what it actually assembles into. You might be surprised to see something like, say, LDA (Pointer),Y being turned into LDA ($00),Y depending on whether or not you're actually saying "Pointer = $00" in your code or if you're doing "LDA #$00 ; STA Pointer".

I'm willing to bet you've either got some equates like "Pointer = $00" (same as Pointer EQU $00) which are confusing you, or you've got some labels named the same thing for memory as you do for actual equates (such as in your above example, Pointer could be interpreted as both an equate to $00, AS WELL as label that effectively is at address $0500). It's difficult to tell because of how you chose to word things, rather than just showing code. :-)

Posted: Sat Mar 13, 2010 6:56 am
by thefox
I'm guessing you're using NESASM? :) In NESASM you can't use () for indirect addressing (because of its crappy parser I guess), you have to use [].

Change your code to

Code: Select all

LDA [Pointer], Y
or maybe just scrap NESASM altogether and use ASM6/CA65 or something.

Posted: Sat Mar 13, 2010 7:37 am
by Banshaku
Yep, NESASM uses [] for indirect addressing. If you use () by mistake, no error will be thrown. This is what made the FT30 driver fail when I was converting it (forgot to convert some of them to []).

Posted: Sat Mar 13, 2010 9:57 am
by tokumaru
And your pointers must be in zero page. The instruction "LDA ($XXXX), Y" doesn't exist, only "LDA ($XX), Y" does.

Posted: Sat Mar 13, 2010 10:57 am
by koitsu
thefox wrote:I'm guessing you're using NESASM?
The start of his post says he's using asm6, so my guess is that he's either using equates in a way that he's not sure of, or asm6 isn't throwing an error when trying to do something like

Code: Select all

.org $0400
mylabel .db 0,0,0,0,0,0

.org $8000
ldy #4
lda (mylabel),y
And instead turning the LDA statement into something like LDA ($00),y or LDA ($04),y. Hard to say -- again, listings generation can answer this. But then again so could we if we could see the code. ;-)

Posted: Sat Mar 13, 2010 12:28 pm
by thefox
koitsu wrote:
thefox wrote:I'm guessing you're using NESASM?
The start of his post says he's using asm6, so my guess is that he's either using equates in a way that he's not sure of, or asm6 isn't throwing an error when trying to do something like
Oops, missed that. It could indeed by that ASM6 parser is seeing this as LDA $0500,Y because of the non-zeropage address.

Posted: Sat Mar 13, 2010 2:02 pm
by rizz1010
tokumaru wrote:And your pointers must be in zero page. The instruction "LDA ($XXXX), Y" doesn't exist, only "LDA ($XX), Y" does.


The solution has been found (it was the zero page issue).

Sorry for the confusion in my post koitsu (my actual code was assembly friendly, using LDA, STA instructions). When I read your post I was thinking "yes, that is exactly how I understand it" which was bugging me even more that my code wasn't working as was expected.


Regarding the $04 value put into the accumulator, apparently, if you try a 2 byte value with indirect indexed addressing, it ignores the value inside the address, and uses the address itself. So, going back to my example:
LDA (Pointer), Y ;Y = 1
It took the address where Pointer was ($0500), added 1 to that ($0501), and put $04 into the accumulator. $04 was the value held in $0501.


And thanks for the debugger tip with -l. I'd love to here a more detailed explanation of how to use that. Where does the -l get added exactly? As far as debugging goes, any other helpful hints are welcome. The day I discovered the hex editor was so nice.

Posted: Sat Mar 13, 2010 4:37 pm
by tokumaru
If you use a value > than $FF the assembler probably just considers the parenthesis as part of a logical expression (which evaluates to the value inside the parenthesis) rather than indirect addressing.

Posted: Sat Mar 13, 2010 7:09 pm
by koitsu
rizz1010 wrote:And thanks for the debugger tip with -l. I'd love to here a more detailed explanation of how to use that. Where does the -l get added exactly?
It's a command-line flag you pass to asm6. Read the README. :-)

I'd love to classify this as an asm6 bug, however, I still don't understand the way the problem manifests itself. You said:
rizz1010 wrote: Regarding the $04 value put into the accumulator, apparently, if you try a 2 byte value with indirect indexed addressing, it ignores the value inside the address, and uses the address itself. So, going back to my example:
LDA (Pointer), Y ;Y = 1
It took the address where Pointer was ($0500), added 1 to that ($0501), and put $04 into the accumulator. $04 was the value held in $0501.
I don't know how that would even be possible. The CPU doesn't know how to do anything like LDA ($0500),Y -- by this I mean there's no such addressing mode -- and the assembler should not be causing this somehow (the assembler doesn't know/care what Y is set to).

If LDA ($0500),Y is permitted by asm6, then that's a bug in the assembler.

Can you please show the listing generation for the code in question? Let's get to the bottom of this.

Posted: Sat Mar 13, 2010 7:12 pm
by koitsu
tokumaru wrote:If you use a value > than $FF the assembler probably just considers the parenthesis as part of a logical expression (which evaluates to the value inside the parenthesis) rather than indirect addressing.
I'm not sure that's the case either though, because:

1) What would the "value for Pointer" expand to? It should expand to a 16-bit address (e.g. $0500), which would turn the instruction into something invalid for the 6502 (specifically, LDA ($0500),Y).

2) It doesn't explain how the assembler would somehow generate $0501 for any part of the effective address.

3) He says "it took the address where Pointer was (e.g. $0500, added 1 to that (to make $0501), and loaded the contents from that address, which loaded $04 into the accum" -- that would imply the assembler, somehow, translated his code into either LDA $0500,Y (valid 6502, opcode $B9) or LDA $0501 (valid 6502, opcode $AD).

The generated assembly listing should answer the question.

Posted: Sat Mar 13, 2010 7:13 pm
by cpow
Pointer = $00
Pointer+1 = $04

How is this even valid? What am I missing?

Posted: Sat Mar 13, 2010 7:18 pm
by koitsu
NESICIDE wrote:Pointer = $00
Pointer+1 = $04

How is this even valid? What am I missing?
He wrote "pseudocode" in attempt to say this:

Code: Select all

LDA #$00
STA Pointer
LDA #$04
STA Pointer+1
Where Pointer is a label to $0500.

Posted: Sat Mar 13, 2010 7:22 pm
by cpow
koitsu wrote:He wrote "pseudocode"
Oh thank goodness!