JMP, fine...JSR, nope...
Moderator: Moderators
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: JMP, fine...JSR, nope...
Just to be clear, you're not expecting registers to be preserved during JSR and restored at RTS, right?
If you're using ca65, you can output your labels to a text file with the -Ln linker flag. You can then search for the label in that text file to find its address, or better yet, turn that label file into an FCEUX debug symbols file which will show the labels directly in the debugger. There is a python script that does this in an example I made a while ago: minimal ca65 example
If you're using ca65, you can output your labels to a text file with the -Ln linker flag. You can then search for the label in that text file to find its address, or better yet, turn that label file into an FCEUX debug symbols file which will show the labels directly in the debugger. There is a python script that does this in an example I made a while ago: minimal ca65 example
Last edited by rainwarrior on Wed Jan 14, 2015 10:54 am, edited 2 times in total.
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: JMP, fine...JSR, nope...
Other helpful things when debugging:
1. Debug > Trace logger.
This lets you dump a text file containing every instruction executed and the status of every register/flag at each step.
2. Conditional breakpoints.
This lets you set a breakpoint that also has a condition.
See: FCEUX debugger guide
For example, if you know that if something is wrong if A is 5 at line $8075, then what you can do it start a trace log at a time before things go wrong, create an execuition breakpoint on 8075 with the condition A==#5, then run until the breakpoint is hit. Stop the trace at this point, and you will have a log of everything that happened up until that breakpoint. From here you can work backwards from the end of the file until you see exactly what caused the problem.
1. Debug > Trace logger.
This lets you dump a text file containing every instruction executed and the status of every register/flag at each step.
2. Conditional breakpoints.
This lets you set a breakpoint that also has a condition.
See: FCEUX debugger guide
For example, if you know that if something is wrong if A is 5 at line $8075, then what you can do it start a trace log at a time before things go wrong, create an execuition breakpoint on 8075 with the condition A==#5, then run until the breakpoint is hit. Stop the trace at this point, and you will have a log of everything that happened up until that breakpoint. From here you can work backwards from the end of the file until you see exactly what caused the problem.
Re: JMP, fine...JSR, nope...
They're not? Hm...that is definitely news to me...Just to be clear, you're not expecting registers to be preserved during JSR and restored at RTS, right?
So if I were to do something like this:
Code: Select all
LDX #$01
JSR whatever
.......
whatever:
TXA
RTS
I'm guessing what you meant is that THIS will not work:
Code: Select all
LDX #$01
JSR whatever
.....
whatever:
INX ; no longer preserved, because something was done to affect it
TXA ; accumulator is no longer preserved as it was before the jump, because something was done to affect it
RTS
Re: JMP, fine...JSR, nope...
I guess you miss kasumi's comment.
this is what I think your code is doing(' is for branch).
versus jsr way
this is what I think your code is doing(' is for branch).
Code: Select all
loop: ;(6)
jmp TileCheckRigth ;(1)
somewhere: ; ('4)
;...
skipdec: ;(4)
jmp loop ;(5)('5)
TileCheckRigth: ;(2)
;...
jmp skipdec ;(3) there is not a problem, everything is jump
;...
jmp somewhere ; ('3)
Code: Select all
loop: ;(6)
jsr TileCheckRigth ;(1) push program counter to stack
somewhere: ; ('4)
;...
skipdec: ;(4)
jmp loop ;(5) ('5)
TileCheckRigth: ;(2)
;...
jmp skipdec ;(3) miss one rts, this corrupts stack
;...
rts ; ('3)
Re: JMP, fine...JSR, nope...
Oooooh! I gotcha now. I think some synapse just fired.
So I'd have to RTS back from the JSR, or otherwise get rid of the last value pushed to the stack, as it's hooked to the RTS. It's just still sitting on the stack lingering, and the next time something pulls from the stack, it's pulling that value...something like that?
Huh. Man...I better go through my code with a highlighter and make sure I haven't made this mistake anywhere else!
So I'd have to RTS back from the JSR, or otherwise get rid of the last value pushed to the stack, as it's hooked to the RTS. It's just still sitting on the stack lingering, and the next time something pulls from the stack, it's pulling that value...something like that?
Huh. Man...I better go through my code with a highlighter and make sure I haven't made this mistake anywhere else!
Re: JMP, fine...JSR, nope...
To expand on rainwarrior's comment/question: the contents of A, X, and Y are not "backed up" and "restored" when doing a JSR/RTS. Take this code for example:JoeGtake2 wrote:They're not? Hm...that is definitely news to me...Just to be clear, you're not expecting registers to be preserved during JSR and restored at RTS, right?
Code: Select all
lda #$01
ldx #$aa
ldy #$bb
;
; At this point in the code, A = $01, X = $AA, Y = $BB
;
jsr someplace
;
; At this point in the code, A = $00, X = $22, Y = $BB
;
loop:
jmp loop ; Just to keep the code below this from being run
someplace:
ldx #$22
lda #0
rts
If that comes as a surprise to you, i.e. "I thought A/X/Y were backed up when JSR was used, and restored when RTS was used!", then that would be a bug. Is it *the* bug? I don't know, that's for you to figure out.
So if you need to back up and restore registers, you need to make sure your subroutines push those values onto the stack when the routine starts, and pull them off right before the end (and remember to pull them off the stack in the opposite order as you pushed them on). Again the same code, but fixed to back up and restore A/X/Y:
Code: Select all
lda #$01
ldx #$aa
ldy #$bb
;
; At this point in the code, A = $01, X = $AA, Y = $BB
;
jsr someplace
;
; At this point in the code, A = $01, X = $AA, Y = $BB
;
loop:
jmp loop ; Just to keep the code below this from being run
someplace:
phx
pha
ldx #$22
lda #0
pla
plx
rts
I don't use PHY/PLY anywhere in the "someplace" routine because Y isn't modified; but you could add it there just as a safety net if you wanted, no harm done (other than some CPU cycles wasted).
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Re: JMP, fine...JSR, nope...
I'm sorry, I might be on drugs here... But PLX/PHX and PLY/PHY are not real 6502 commands... Right?
Re: JMP, fine...JSR, nope...
No I got it.
Celius, I think he was just using that to abbreviate TAX -> PHA. I knew what he meant. Unless I'm mistaken.
But Koitsu, yeah, I get it. I was misreading Rainwarriors meaning (specified in the edit). I get it. I had a moment of revelation when Nostromo posted that visual example. It was the exact same thing EVERYONE was saying, but seeing it like that for some reason just kicked over whatever blockage was happening in my brain.
JSR puts a value into the stack. Without the RTS, the value never gets pulled. So when I was JMPing out of the subroutine, there was leftover junk in the stack, and I'm pretty sure that's what was causing the problem. I may have done this in other places too, so I'll have to go back through and check. I wasn't making the correlation between JSRing and the stack...I understood using PHA PLA to push and pull the accumulator the stack, but just didn't know (or at least, didn't factor) that JSR RTS also pushed and pulled to the stack.
Thanks for all the input - sorry for being so dense! haha
Celius, I think he was just using that to abbreviate TAX -> PHA. I knew what he meant. Unless I'm mistaken.
But Koitsu, yeah, I get it. I was misreading Rainwarriors meaning (specified in the edit). I get it. I had a moment of revelation when Nostromo posted that visual example. It was the exact same thing EVERYONE was saying, but seeing it like that for some reason just kicked over whatever blockage was happening in my brain.
JSR puts a value into the stack. Without the RTS, the value never gets pulled. So when I was JMPing out of the subroutine, there was leftover junk in the stack, and I'm pretty sure that's what was causing the problem. I may have done this in other places too, so I'll have to go back through and check. I wasn't making the correlation between JSRing and the stack...I understood using PHA PLA to push and pull the accumulator the stack, but just didn't know (or at least, didn't factor) that JSR RTS also pushed and pulled to the stack.
Thanks for all the input - sorry for being so dense! haha
Re: JMP, fine...JSR, nope...
Nope! {PH|PL}{X|Y} were added on the 65C02.Celius wrote:PLX/PHX and PLY/PHY are not real 6502 commands... Right?
You might also want a PHP/PLP sometimes.
(Interrupts and RTI include status push-pulls and don't need them added.)
Also, if you had imbalanced push-pulls, those use the same stack as the return address generated/used by JSR/RTS.
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Re: JMP, fine...JSR, nope...
I figured they weren't, but it seems like the kind of thing I would glance over and then learn about 10 years later
. It's also good to clarify here for anyone browsing the Newbie Help Center so they don't get confused.
Re: JMP, fine...JSR, nope...
Sigh. :( As Myask pointed out they're 65c02. I often forget which opcodes the 65c02 introduced in comparison to the original 6502 (and to me that's funny since I started with 6502, went to 65c02 within about 6 months, then later to 65816) -- the only one I always remember is how inc (a.k.a. inc a) doesn't exist on 6502 (instead forced to clc / adc #1); the others I often forget. Thanks guys for keeping me on my toes + pointing out this mistake of mine. Apologies if anyone reading this thread misses that mistake / gets bitten by it.Celius wrote:I'm sorry, I might be on drugs here... But PLX/PHX and PLY/PHY are not real 6502 commands... Right?
Revamped routine which does the same thing but works on 6502:
Code: Select all
someplace:
pha
txa
pha
ldx #$22
lda #0
pla
tax
pla
rts
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: JMP, fine...JSR, nope...
JoeGtake2: You had the part I was asking about correct, I was just asking because you mentioned that using TAY/TYA to manually restore A helped. It sounds like you have cleared up your confusion though, otherwise.
Re: JMP, fine...JSR, nope...
This is of modest use, though a bunch of the 816 opcodes get overridden by the new ones he put in. (Might also be c02, not sure; only barely familiar with either).koitsu wrote:Sigh.Celius wrote:I'm sorry, I might be on drugs here... But PLX/PHX and PLY/PHY are not real 6502 commands... Right?As Myask pointed out they're 65c02. I often forget which opcodes the 65c02 introduced in comparison to the original 6502 (and to me that's funny since I started with 6502, went to 65c02 within about 6 months, then later to 65816)
It looks nice, anyway.
Re: JMP, fine...JSR, nope...
Charts like that tend to be hard for me to follow because they seem "thrown together" (and in my experience a lot of people who have "charts of opcodes" end up making mistakes -- there are all sorts of 6502 web pages that have these which are riddled with mistakes. They get mentioned here once in a while). I prefer stuff like what's in the WDC manual:Myask wrote:This is of modest use, though a bunch of the 816 opcodes get overridden by the new ones he put in. (Might also be c02, not sure; only barely familiar with either).
It looks nice, anyway.
...but then I just realised on the per-opcode-breakdown, the formatting (column sizes and layout) in the PDF is completely botched compared to the actual Ron Lichty and David Eyes book, making the one in PDF format hard to read. Hahaha wow... way to go WDC. *sigh*