I use jump absolute in a few places in my project, and was wondering if there was a good workaround for the jmp ($xxFF) bug. Really, I just need the ability to get to a routine variably (I'm not a very good explainer). But when the needed routines address is stored in temp memory.
I don't think you can get around the bug (and some say it's not even a bug)... Why not just make sure the addresses are stored at even memory locations? You'll never have to worry about this "bug" if you do this.
Ok, thats fine. I'm just readjusting them with NOPs. How would I make sure they're at even address other going to the listing file after compilation and finding the bad ones.
I'm using ca65 by the way.
How are you ordering them? Are these addresses at random locations? If you have many of them, the organized thing to do would be to place them all in a list, one after the other. That way, if the first is at an even address, all the others will too.
These are RAM values right? When you create labels to point to these locations make sure the labels represent even numbers.
The values to jump are yes. But its a 2 byte storage area, not a list of address/pointer type vars. I just use the .proc command to close the scope around the routines. All of the them that need to be jumped to are stored in the same basic area, one after the other, depending on use.
mbrenaman wrote:
How would I make sure they're at even address
[...]
I'm using ca65 by the way.
.ALIGN
I think you are misunderstanding the basic opcodes. JMP absolute has no pathological behavior. JMP indirect does when the low byte of the intermediate address is $FF. You will almost always store the target address in RAM, so it's easy to avoid having it cross a page boundary.
Code:
lda #$34
sta $200
lda #$12
sta $201
JMP ($200) ; JMP $1234
Quote:
mbrenaman wrote:
How would I make sure they're at even address
[...]
I'm using ca65 by the way.
.ALIGN
Excellent. This is something I was looking for.
Quote:
I think you are misunderstanding the basic opcodes. JMP absolute has no pathological behavior. JMP indirect does when the low byte of the intermediate address is $FF. You will almost always store the target address in RAM, so it's easy to avoid having it cross a page boundary.
Code:
lda #$34
sta $200
lda #$12
sta $201
JMP ($200) ; JMP $1234
Yesterday was a long day. I don't know why I kept writing Absolute. I meant Absolute
Indirect.
Wait a minute. Its not the address to jump to that messes it up. Its the pointer's address in RAM. Doh!
Example :
Code:
lda #$34
sta $2FF
lda #$12
sta $300
JMP ($2FF) ; JMP "Not really where it would jump to"
Right?
Code:
lda #$11
sta $200
lda #$22
sta $2FF
lda #$33
sta $300
JMP ($2FF) ; JMP $1122
The reason people encounter problems with this instruction is that JMP ADDR is often incorrectly defined to fetch the address from ADDR and ADDR+1, when it really fetches it from ADDR and ((ADDR + 1) AND $FF) OR (ADDR AND $FF00), that is, only incrementing the lower 8 bits without any carry. Correct the documentation and the claimed bug in the processor goes away.
Usually, you'll want to store the adress to jump in a two-var pointer. And if you keep all yours two vars pointers in zero-page, you will be sure that the high byte of jmp ($xxxx) is always $00, so it won't cross RAM page boundaries.
If you want to do this out of page zero, you have one change out of 256 that this bug happens to you. That is fairly low, but to keep sure, I think .align 2 will do the work.
Doing this out of ram is just stupid, since as long as you can read an adress in ROM you can use jmp absolute. The only exeption to this is if you want a kind of software interupt, where you'd use jmp ($fffa) for a software NMI or jmp (£fffc) for a software reset. Since the adresses are fix, you won't meet that bug. You could also use jmp NMI and jmp Reset in absolute.
I understand. Thank you for your help everyone. I plan to just make use of .ALIGN.
blargg wrote:
JMP ADDR is often incorrectly defined to fetch the address from ADDR and ADDR+1, when it really fetches it from ADDR and ((ADDR + 1) AND $FF) OR (ADDR AND $FF00)
You mean "JMP (ADDR) is incorrectly defined", right?