[Coco] lbsr and rts
William Astle
lost at l-w.ca
Wed Sep 16 20:06:29 EDT 2009
Since L010A and L010D both turn into JSR <$1E with a single byte after
it, and L013A has JSR <$2A followed by something that's probably data,
and assuming that L08F8 is not the disassembler out of sync (seems
unlikely given the sequence of code), here's what I think is happening.
I suspect that at process startup, the direct page is being loaded with
a couple of subroutines, one starting at $1E and one at $2A. I further
suspect that those subroutines examine the byte following the JSR call
and probably removed the return address from the stack. Since I don't
have the code, I'll contrive an example without all the direct page
stuff (the mechanics are the same whether it's a JSR to the direct page
or a BSR, JSR, or LBSR somewhere else):
SUBR PULS X
LDA ,X
* do stuff based on value in A
RTS
DO1 JSR SUBR
FCB 1
DO2 JSR SUBR
FCB 2
MAIN BSR DO1
BSR DO2
* ...
Let's trace it. MAIN calls DO1. This puts the address of the second BSR
on the stack. DO1 calls SUBR which puts the address of the FCB 1 on the
stack. The SUBR yanks first return address from the stack and stuffs it
in X, reads the byte pointed to, does some stuff, and returns...to the
previous return address. So even though you have a JSR at DO1, the RTS
in SUBR returns to the "BSR DO2" instruction after MAIN.
Quite frankly, I don't see the point of doing that unless the algorithm
is using some sort of self-modifying code. Since OS9 doesn't like
self-modifying code, the only way to do that is to copy the code you
want to modify into the process's data space and modify it there. Even
then, it seems like the whole point of that sequence is to obfuscate the
code.
I've seen similar tricks used with SWI, SWI2, and SWI3. I've even
written some really ugly code using even stranger tricks.
Wayne Campbell wrote:
> I may be missing something, but I thought calls to subroutines required a rts instruction. In Basic09, there has to be a RETURN statement for any given GOSUB, but not necessarily one-for-one. I can, for example, have a series of subroutine calls, where there are multiple entry points for the subroutine, and one RETURN statement, like:
>
> code
> GOSUB 20
> more code
> GOSUB 30
> more code
> END
>
> 20 code
> more code
> 30 even more code
> still more code
> RETURN
>
> It will not generate any errors, and as long as the code is written correctly, it will work.
>
> I have found, in the assembly code generated by disasm, that there are labels in the declarations (all those fcb's) that are being addressed in the code using lbsr op codes. Yet, there is no rts instruction anywhere in those fcb's. Can someone explain how this works? An example is:
>
> * The L010A label is addressed twice in the program code.
> L010A fcb $9D
> fcb $1E
> fcb $04
> * The L010D label is addressed ten times in the program code.
> L010D fcb $9D
> fcb $1E
> fcb $02
>
> this series continues until:
>
> L013A fcb $9D
> fcb $2A *
> fcb $00
> fcb $00
> fcb $72 r
> fcb $02
>
> In the code, the following statements address these labels:
>
> Both occurrences of the L010A label, and one of the L010D labels, occur in this routine:
> L08F8 ldx $02,s
> lda #$80
> lbsr L010A
> bne L090F
> lbsr L010D
> beq L0915
> leax $03,x
> lda #$20
> lbsr L010A
> beq L0915
>
> I just don't understand.
>
> Wayne
>
>
>
>
>
> --
> Coco mailing list
> Coco at maltedmedia.com
> http://five.pairlist.net/mailman/listinfo/coco
>
--
William Astle
lost at l-w.ca
More information about the Coco
mailing list