[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