[Coco] Surprising find when calling USRn(X)

Sean Conner sean at conman.org
Tue Nov 5 21:22:13 EST 2024


  I'm still working on writing assembly to interface with BASIC.  It's neve
rmentioned what registers need to be saved when calling USR() or USRn(), but
I thought I would be safe to double check with the Unravelled books.  It
seems like you can use any register, but reading the code for USRn()
revealed something interesting:

	L892C	BSR	L891C	GET STORAGE LOC OF EXEC ADDRESS FOR USRn
		LDX	,X	* GET EXEC ADDRESS AND
		PSHS	X	* PUSH IT ONTO THE STACK
		JSR	LB262	SYNTAX CHECK FOR ( & EVALUATE EXPR
		LDX	#FP0EXP	POINT X TO FPA0
		LDA	VALTYP	GET VARIABLE TYPE
		BEQ	L8943	BRANCH IF NUMERIC, STRING IF <> 0
		JSR	LB657	GET POINTER TO STRING DESCRIPTOR
		LDX	FPA0+2	GET VARIABLE POINTER
		LDA	VALTYP	GET VARIABLE TYPE
	L8943	RTS		JUMP TO USR ROUTINE (PSHS X ABOVE)

  The called assembly language routine gets X pointing either to FPA0, or
the address of the string descriptor; A is 0 if number, or <>0 ($FF
actually) if a string.  So there's no need to call INTCVT in the assembly
code, nor to use VARPTR() when calling USRn().  I found that the the
following program works:

	10 DATA166,132,174,2,95,235,128,74,38,251,83,126,180,243
	20 CLEAR200,32511:FORA=32512TO32525:READB:POKEA,B:NEXT:DEFUSR0=32512
	30 X$="HELLO, WORLD!":C=USR0(X$):PRINTX$,C
	40 X$=X$+CHR$(C):C=USR0(X$):PRINTX$,C

The assembly subroutine:

	GIVBF	equ	$B4F3

		org	$7F00
		lda	,x	; length
		ldx	2,x	; actual string
		clrb
	chksum	addb	,x+
		deca
		bne	chksum
		comb
		jmp	GIVBF
		end

  I checked _Getting Started With Extended Color BASIC_ and this is not
mentioned at all.  In fact, I seem to have found an error in the book.  It
states:

	A$=(USR1(VARPTR(B$))

	You can have your ML subroutine modify B$'s value and then end the
	routine with an RTS instruction.  This causes USR to return with
	B$'s modified value.

  So, I tried with the following code:

		INTCVT	equ	$B3ED

		org	$7F00
	lower1	jsr	INVCVT	; this becomes USR0 below
		tfr	d,x
	lower2	lda	,x	; this becomes USR1 below
		ldx	2,x
	loop	ldb	,x
		cmpb	#'A'
		blo	store
		cmpb	#'Z'
		bhi	store
		orb	#$20
	store	stb	,x+
		deca
		bne	loop
		rts
		end

And the following BASIC program:

	10 DATA189,179,237,31,1,166,132,174,2,230,132,193,65,37,6,193,90,34,2,202,32,231,128,74,38,239,57
	20 CLEAR200,32511:FORA=32512TO32538:READB:POKEA,B:NEXT:DEFUSR0=32512:DEFUSR1=32517
	100 X$="HELLO, WORLD!"
	110 X=USR0(VARPTR(X$)):PRINT X$
	120 X$="NICE TO MEET YOU"
	130 Y$=USR1(X$):PRINT Y$

  If I change line 110 to basically match the documentation:

	110 Y$=USR0(VARPTR(X$)):PRINT Y$

I get

	?TM ERROR in 110

  Line 130 works as is.  Go figure.

  -spc



More information about the Coco mailing list