[Coco] Surprising find when calling USRn(X)

Sean Conner sean at conman.org
Wed Nov 6 15:48:36 EST 2024


It was thus said that the Great Johann Klasek once stated:
> On Tue, Nov 05, 2024 at 09:22:13PM -0500, Sean Conner via Coco wrote:
> 
> > The assembly subroutine:
> > 
> > 	GIVBF	equ	$B4F3
> 
> Here you should check in A if the expected type is given otherwise
> X won't contain a descriptor address at all ...

  Yes, of course.  It was just a quick test.

> The current type is derived from the last expression evaluated. The
> expression of the argument is this last expression and determines the
> type of the whole expression USRx() which has to match the variable type
> of the assignement. The reported "Type Mismatch" is telling this.
> 
> For 
> 
> > 	110 Y$=USR0(VARPTR(X$)):PRINT Y$
> 
> to work the code above has to put a discriptor pointer (maybe a temporary
> descriptor on the string descriptor stack) with a string allocated on the
> string heap (containing the result) into the ACC0 and set the type to
> "string".
> Otherwise, the rule applies that the assignment type and argument type are
> identical.

  But none of that was documented in either _Getting Started with Color
BASIC_or _Getting Started with Extended Color BASIC_.  And it's _Getting
Started with Extended Color BASIC_ that says to:

	Y$=USR0(VARPTR(X$))

  Anyway, I finished adding a new output format for my 6809 assembler [1],
which is to output a BASIC program to poke the machine code into memory,
which is why I was playing around with this stuff.  Given this program:


		include	"basic.i"
		include	"basic-int.i"
		include	"dp.i"

		.opt	basic strspace 300
		.opt	basic defusr0 both
		.opt	basic defusr1 decstr
		.opt	basic defusr2 addone
		.opt	basic defusr3 identity
		.opt	basic defusr4 maskstr

		org	$7F00

;***************************************************************************

both		beq	.number			; handle number
		ldx	_STRPTR,x		; point to string data
.text		lda	,x			; just increment each character
		inca				; B already has length
		sta	,x+
		decb
		bne	.text
		rts				; return
.number		ldx	#.pi			; FP0 = FP0 * pi
		jmp	CB.FMULx

.pi		.float	3.1415926

;***************************************************************************

decstr		jsr	CB.strchk		; looking for a string
		ldx	_STRPTR,x		; get string pointer
.text		lda	,x			; decrement each character
		deca
		sta	,x+
		decb
		bne	.text
		rts

;***************************************************************************

addone		jsr	CB.numchk		; check for number
		ldx	#.one			; add one to FP0
		jmp	CB.FADDx

.one		.float	1.0

;***************************************************************************

identity	rts				; identity function

;***************************************************************************

maskstr		jsr	CB.strchk		; check for string
		stb	CB.strdes + _STRLEN	; save length of new string
		jsr	CB.rsvpstr		; reserve string space
		ldb	CB.strdes + _STRLEN	; get length
		lda	#'*'			; masking character
.mask		sta	,x+
		decb
		bne	.mask
		ldx	CB.frespc		; point to new string
		stx	CB.strdes + _STRPTR
		jmp	CB.putstrdes		; add to string pool

;***************************************************************************

		end

And selecting the BASIC format, you get the following output:

10 DATA39,11,174,2,166,132,76,167,128,90,38,248,57,142,127,19,126,186,202,130,73,15,218,104,189,177,70,174,2,166,132,74,167,128,90,38,248,57,189,177,67,142,127,47,126,185,194,129,0,0,0,0,57,189,177,70,215,86,189,181,109,214,86,134,42,167,128,90,38
20 DATA251,158,37,159,88,126,181,76
30 CLEAR300,32511:FORA=32512TO32588:READB:POKEA,B:NEXT:DEFUSR0=32512:DEFUSR1=32536:DEFUSR2=32550:DEFUSR3=32564:DEFUSR4=32565

ready to be MERGEed into an existing BASIC program.  And there are options
to change the line numbering if so desired.

The example program I have to drive this code is:

	100 X=USR0(2):PRINT X:X$=USR0("HELLO"):PRINT X$
	105 X=USR1(5):REM WILL ERROR OUT
	110 X$=USR1("THERE"):PRINT X$
	115 X$=USR2("HELLO"):REM WILL ERROR OUT
	120 X=USR2(1):PRINT X
	130 X=USR3(3.1415926):PRINT X:X$=USR3("IDENTITY"):PRINT X$
	135 X=USR4(4):REM WILL ERROR OUT
	140 P$="PASSWORD":H$=USR4(P$):PRINT P$,H$

  What I've found is that on entry to a DEFUSRn routine:

	X - points to either FP0 ($4F), or a string descriptor, depending
	    upon type (not documented?)
	A - 0 if number, 255 if string (not documented?)
	B - length of string if A = 255 (not documented?)

	INTCVT ($B3ED) - converts contents of FP0 to D
	GIVBF  ($B4F3) - converts B to FP0 (unsigned)
	GIVABF ($B4F4) - convertd D to FP0

	VARPTR(var) - set FP0 to address of numberic variable, or string
                      descriptor of string variable

  -spc

[1]	https://github.com/spc476/a09


More information about the Coco mailing list