I have a case where I need to use JMP's indirect ability, but in a manner similar to JSR/RTS, such as
1F00 do something...
1F40 JMP ($138A) <--- Jumps to address pointed to by $138A
1F45 continue on... <---- but i want to somehow come back here when done
Problem is, I want to be able to come back after doing the extra work...much like a JSR/RTS. Can I somehow use PHP to save where I am, so that I can JMP back to where I came from? JSR/RTS is what I really need to do, but I need to do it indirectly.
You can manually push the address you want to return to, minus one, on the stack, in this case $1F44. Then when you want to return from the JMPed to code, use an RTS. The RTS gets its return address from the stack, so it will pull whatever you put there ($1F44) and continue from the next address ($1F45).
Eg.,
LDA #>continue
PHA
LDA #<continue-1
PHA
JMP (wherever)
continue:
blah blah blah
....
wherever:
blah blah blah
RTS
this is right but your posted code should better read like
lda #>(continue-1)
pha
lda #<(continue-1)
pha
...
just in case continue would be e.g. $1000, then your code would produce
lda #$10
pha
lda #$ff
pha
instead of
lda #$ff
pha
lda #$ff
pha
Thanks for the correction! I knew I shouldn't post code at 4AM with blurry eyes and no sleep. :D
Naw, you guys are making it too difficult with the stack acrobatics. First, code the following subroutine:
myjsrfar stx vector+1 ;store JSR target address lo
sty vector+2 ;ditto for high
vector jmp $0000 ;take the jump
Now, to actually use this:
ldx #<jsrtarget ;jsr target lo
ldy #>jsrtarget ;jsr target hi
jsr myjsrfar ;off you go!
Works like a charm and runs no risk of spanking the stack and causing a crash. Any questions?
if one likes self-modifying code...... but you know that there are situations were selfmod is not possible (e.g. ROM)
for my taste i like the stack manipulation more than selfmodding, but thats a matter of taste...
You also can use a jump table:
table:
jmp (wherever1)
jmp (wherever2)
jmp (wherever3)
...
...
do something
jsr (table+0)
continue doing
...
...
wherever1:
do subroutine
RTS
...
So you dont't have to mess around with registers or the stack.
WTE
Quote from: wte on January 15, 2008, 08:31 AM
You also can use a jump table:
yeah, much better although it's much simpler to use a label for each jmp:
jsr table0
jsr table1
jsr table2
rts
table0: jmp (address0)
table1: jmp (address1)
table2: jmp (address2)
If you want to save a few cycles then instead of putting the vector at the specifed address, you could put the jmp instruction itself at that address.
Quote from: smf on January 15, 2008, 08:54 AM
yeah, much better although it's much simpler to use a label for each jmp:
Yeah, but I also didn't want to mess around with labels ;)
Otherwise I had something used like this:
;jump table
i_wherever1: jmp (wherever1)
i_wherever2: jmp (wherever2)
i_wherever3: jmp (wherever3)
...
...
do something
jsr (i_wherever1)
continue doing
...
...
wherever1:
do subroutine
RTS
...WTE
Quote from: hannenz on January 14, 2008, 09:17 PM
if one likes self-modifying code...... but you know that there are situations were selfmod is not possible (e.g. ROM)
for my taste i like the stack manipulation more than selfmodding, but thats a matter of taste...
So, pick a pair of locations for an indirect jump if you want ROMmable code. Locations $03FE and $03FF are unused in both the C-64 and C-128. Change JMP $0000 to JMP ($03FE) in the above code and store the JSR target into those locations. Try not to make something simple so complicated. <Grin>