USR

From C64-Wiki
Jump to navigationJump to search
BASIC keyword
Keyword: USR
Abbreviation: U Shift+S
Type: Function
Token code: 183/$B7
Handling routine
in BASIC ROM:
784–786
$0310–0312
List of all BASIC keywords


Remark: This article describes the BASIC command USR in BASIC V2 at the Commodore 64.

Type: Floating Point Function
General Programming-Syntax: USR(<Number>)


USR is a user-defined function in the built-in BASIC interpreter: It accepts any valid BASIC expression (numeric or string) as a parameter, calls a user-defined machine language routine, and returns a resulting real number.

The addresses 785–786/$0311–$0312 form a pointer to the routine. Right after a cold start (power-on or reset), this pointer is set to 45640/$B248, where a short routine sends the system right into the BASIC error handler to report an ?ILLEGAL QUANTITY  ERROR — not a particular useful function...!

To make USR "do something useful", one must first provide a machine language routine that "does the useful part": This routine should "expect" it's input value to be in FAC (in the case of a numeric argument) or pointed to by the string descriptor pointer at address $64/$65 (in the case of a string argument), and must "deposit" it's resulting output value in FAC, before ending in an RTS.

USR allows "mixing" calculations performed in machine language and BASIC, like e.g.

B=X+40*USR(SQR(X)*1.667)

The USR function takes exactly one argument which is not optional, so omitting it or supplying more than one argument will result in a ?SYNTAX ERROR IN line. USR can accept any valid BASIC expression as an argument, but if called with a string argument, the function must signal that it is returning a numeric expression by writing #$00 to address $000D before returning, or else a ?TYPE MISMATCH ERROR IN line will occur. Also, in the case of a string argument, the function must be sure to remove the argument from the BASIC string stack by issuing a call to 46758/$B6A6.

Example[edit | edit source]

To demonstrate the USR function, try these POKE's to re-direct the USR function to the ROM routine called "DIV10" at 47870/$BAFE, which divides the given floating point real numer by 10:

POKE 785,254:POKE 786,186

This turns the USR function into a "divide-by-ten function". You can test it by typing e.g.:

PRINT USR(64)
 6.4
READY.

In this example, the argument in the parenthesis (the "64") was converted to a floating point number located in FAC (97–102/$61–$66), before the routine was called: In this example, the 64 was divided by 10, yielding 6.4. When the routine has done its job and returned control to the system, the result is parsed in the BASIC expression.

  • Another example
10 S1 = USR(123)
20 PRINT S1
30 PRINT USR(S1)
BASIC V2.0 (second release) Commands

ABS | AND | ASC | ATN | CHR$ | CLOSE | CLR | CMD | CONT | COS | DATA | DEF | DIM | END | EXP | FN | FOR | FRE | GET | GET# | GOSUB | GOTO | IF | INPUT | INPUT# | INT | LEFT$ | LEN | LET | LIST | LOAD | LOG | MID$ | NEW | NEXT | NOT | ON | OPEN | OR | PEEK | π | POKE | POS | PRINT | PRINT# | READ | REM | RESTORE | RETURN | RIGHT$ | RND | RUN | SAVE | SGN | SIN | SPC | SQR | STATUS/ST | STEP | STOP | STR$ | SYS | TAB | TAN | THEN | TIME/TI | TIME$/TI$ | TO | USR | VAL | VERIFY | WAIT