Intermediate tips for beginners (???) stack, jsr,rts content
Oct 27, 2021 0:31:06 GMT -5
VectorX likes this
Post by gauze on Oct 27, 2021 0:31:06 GMT -5
I mentioned a gotcha I ran into before else where on here:
if you use jsr/bsr/lbsr to run a subroutine you wrote you should only exit it using rts!
I found out the hard way that exiting out with a jmp or bra type instruction left the stack filling up until it wrote into my RAM putting garbage in my variables! If for whatever reason you want to be clever you can puls the return address off the stack and discard it. If you have no idea what I mean or how to do this DON'T DO IT!
another one I ran into today:
If you call a subroutine with jsr/bsr/lbsr and ever use the S stack for temporary storage, make sure you also remove the added values from the stack before hitting rts.
real life code example where I have 2 ways to exit the first half of the routine before doing the rest,
1) by entering 3 characters in the onscreen dialog
or
2) after a time out period so it doesn't stay on the High Score initials entry screen forever
but without clearing what we added to S stack this happens:
there's a couple ways to avoid this:
1. on exit from the early part of the routine, add logic to pull the bytes off the stack "puls d" in
this case just like in the normal flow
2. test for time out before saving the font settings
As things grow and you add stuff in the middle of things to add features stuff like this are bound to bite you once in a while. Learn from my mistakes!
I should probably write smaller routines too, that do one thing instead of 2 or 3 or 10.
happy coding
if you use jsr/bsr/lbsr to run a subroutine you wrote you should only exit it using rts!
I found out the hard way that exiting out with a jmp or bra type instruction left the stack filling up until it wrote into my RAM putting garbage in my variables! If for whatever reason you want to be clever you can puls the return address off the stack and discard it. If you have no idea what I mean or how to do this DON'T DO IT!
another one I ran into today:
If you call a subroutine with jsr/bsr/lbsr and ever use the S stack for temporary storage, make sure you also remove the added values from the stack before hitting rts.
real life code example where I have 2 ways to exit the first half of the routine before doing the rest,
1) by entering 3 characters in the onscreen dialog
or
2) after a time out period so it doesn't stay on the High Score initials entry screen forever
but without clearing what we added to S stack this happens:
jsr check_highscore ; call our routine saves 16-bit address right after this ubstruction in S
...
check_highscore: ; our routine
{init stuff}
hs_loop: ; top of endless loop ... until one of 2 things happen mentioned above
{bunch of stuff}
lda hsentry_index
cmpa #3 ; did 3 chars for HS, now SAVE
lbeq doHSsave ; breaks out of the endless loop before changing font
{bunch of stuff}
ldd Vec_Text_HW ; store our original font settings
pshs d ; in S
ldd #$FE40 ; before changing them
std Vec_Text_HW ;
{bunch of stuff}
; check time out
jsr Dec_3_Counters
tst Vec_Counter_1
bne keepitgoing
dec hse_timeout
beq doHSsave ; S has more bytes in it than just return address... OOPS!
{more stuff}
; bottom of the loop ...
puls d
std Vec_Text_HW ; but here we restore S to its original state, all is well if we haven't timed out!
jmp hs_loop ; back to top
; save our high score and initials to eeprom
doHSsave
{bunch of stuff that doesn't touch S}
rts ; move S to PC ... disaster if we have timed out!!
there's a couple ways to avoid this:
1. on exit from the early part of the routine, add logic to pull the bytes off the stack "puls d" in
this case just like in the normal flow
2. test for time out before saving the font settings
As things grow and you add stuff in the middle of things to add features stuff like this are bound to bite you once in a while. Learn from my mistakes!
I should probably write smaller routines too, that do one thing instead of 2 or 3 or 10.
happy coding