Error calculating address with forward references
ATasm is a 6502 command-line cross-assembler.
Brought to you by:
schmelze
Hi!
I have this code:
levelMap = levelData + $1000
* = $600
lda levelMap+1,x
lda levelData
rts
levelData .byte 0
The compiler calculates levelData as 0x606, and the final code is:
00:06 BD 07 16 lda levelMap+1,x
03:06 AD 06 06 lda levelData
06:06 60 rts
07:06 00 levelData .byte 0
Equates:
LEVELMAP: 1606
Symbol table:
LEVELDATA: 0606
The error comes from a previews pass where the addressing mode of levelMap+1 is being calculated. Using some additional logging I see this (logging is mine):
do_cmd process symbol LDA at address 0600 from buf LDA
parse_operand.1 get_expression = 0, levelMap+1
parse_operand.6 first pass
parse_operand.6 first pass a=0 rel[sym->addr]=ffffffff
parse_operand.6 first pass sym->addr=32 vidX=88 a_y[sym->addr]=b9 z_y[sym->addr]=b9
do_cmd process symbol LDA at address 0602 from buf LDA
That log info comes from this:
printf("parse_operand.6 first pass\n");
if ((a<256)||(rel[sym->addr]>=0)) {
printf("parse_operand.6 first pass a=%x rel[sym->addr]=%x \n", a, rel[sym->addr]);
printf("parse_operand.6 first pass sym->addr=%i vidX=%d a_y[sym->addr]=%x z_y[sym->addr]=%x \n", sym->addr, vidx, a_y[sym->addr], z_y[sym->addr]);
if ((sym->addr==30)|| /* pad a few zero-page opcodes */
(sym->addr==31)||
((vidx=='Y')&&((a_y[sym->addr]==z_y[sym->addr]))))
pc+=3;
else
pc+=2;
}
As you can see, only the "Y" case is evaluated. If I change the code with Y indexing, I get the expected results
00:06 B9 08 16 lda levelMap+1,y
03:06 AD 07 06 lda levelData
06:06 60 rts
07:06 00 levelData .byte 0
Equates:
LEVELMAP: 1607
Symbol table:
LEVELDATA: 0607
I'm not sure why only the "Y" case is evaluated. May be just adding the "X" case will be enough to fix this?
Now that I give it a second look, the problem is that "LDA address,y" is always a 16 bit address, but with X can be in the zero page or above, so there is no way at that point to determine the size of the address, or is there?
Bug confirmed in V1.08-trunk100. Workaround by reordering is possible here
levelData .byte 0
levelMap = levelData + $1000
For those interested I fixed this bug in V1.10 of atasm
https://github.com/CycoPH/atasm