I mentioned in part 1 that there’s a convenient routine to convert a real number into a signed 16-bit integer. However, Basic line numbers are 16-bit unsigned numbers when parsed into Basic code. So there has to be a routine to turn a real value in fac1 into a 16-bit integer as part of the interpretation of Basic text that starts with a line number.

[ part 1 | part 3 | part 4 | part 5 | bonus ]

And indeed there is. It is called getadr and is located at $b7f7. It supposedly is to turn a real value between zero and 65536 into a 16-bit unsigned integer. For both values the floating point accumulator fac1 is used. The resulting integer value is stored in locations $64 and $65 of fac1, high byte first.

Since the usr machine language routine stores the function value entered in Basic into fac1 as a real number, the next steps should be easy:

  • call getadr ($b7f7) to convert a real into a unsigned 16-bit integer
  • read $64 in .A and $65 in .Y, both part of fac1
  • process the integer into a value stored in .A and .Y
  • subtract 32768 to convert the unsigned integer into a signed integer value between -32768 and 32767, which givayf needs
  • turn .A and .Y into a real, by calling the givayf ($b391) routine

To not over-complicate things at this point, we should interpret the “process the integer” as “do nothing”, effectively skipping the processing step. We will develop our “is this number prime” routine later. All we want to know if the supplied value between 0 and 65536 is accepted and can be used as such.

This method is certainly somewhat error-prone (never underestimate the power of typos), because it requires some workaround in Basic to deal with the signed integer value that our usr machine language routine returns to Basic.

After entering the source code in the assembly listing “usrfunction 0.2”, I copied the hexdump from Virtual 6502 Assembler and wrote the Basic program “testusrf 0.2” in the next listing to see if I got it right. This was what I wanted to test:

  • boundaries 0 and 65535
  • fractional numbers between 0 and 65536, exclusive—use a few values of the expression 65536*rnd(ti)
  • errors with numbers that are < 0 or >= 65536 (use -1 and 65536)
*= $c000

; usrfunction 0.2
; use an unsigned integer
; and, for now, do nothing with it

getadr = $b7f7
givayf = $b391
fac1int = $64

        jsr getadr      ;convert real into unsigned int
        lda fac1int     ;load high byte in .A
        ldy fac1int+1   ;load low byte in .Y
        nop             ;do nothing for now
        sec
        sbc #%10000000  ;subtract $8000 (32678) to make it a signed integer
        jmp givayf      ;make it real and return to Basic
0 rem testusrf 0.2
10 poke 785,0:poke 786,192:rem set usr address to $c000
20 forn=49152to49165:readb:poken,b:next:rem read in machine code
30 data 32,247,183,165,100,164,101,234
40 data 56,233,128,76,145,179
70 x=0:gosub 100
80 x=65535:gosub 100
90 for i=0 to 9:x=rnd(ti)*65536:gosub 100:next
99 end
100 print "x =";x;", usr(x) =";usr(x)+32768:return

Here is the output of that Basic program, with two values entered by hand, which should throw error messages:

run
x = 0 , usr(x) = 0
x = 65535 , usr(x) = 65535
x = 12161.1233 , usr(x) = 12161
x = 3073.54893 , usr(x) = 3073
x = 54247.0177 , usr(x) = 54247
x = 36356.0453 , usr(x) = 36356
x = 58801.1164 , usr(x) = 58801
x = 37546.6392 , usr(x) = 37546
x = 54977.7024 , usr(x) = 54977
x = 61029.0648 , usr(x) = 61029
x = 12345.8034 , usr(x) = 12345
x = 63762.592 , usr(x) = 63762

ready.
?usr(-1)

?illegal quantity  error
ready.
?usr(65536)

?illegal quantity  error
ready.

It worked, which is always a relief.

Now the routine we want (“is this number prime?") doesn’t have to result into an unsigned 16-bit value. We only want to be able to input such a value. The output we expect is either a “Yes” (-1) or “No” (0). So a signed 16-bit integer is exactly what we need.

So why did I do this workaround? I wanted to know if it is at all possible to work around this limitation, in case I ever needed that. It certainly is, as the Basic example shows.

In part 3 I will (finally) start coding for the question whether or not the supplied number is a prime number. This should be interesting.