Difference between revisions of "USR"

From BeebWiki
Jump to: navigation, search
m (Added ARM note.)
m (Slight formatting changes.)
Line 55: Line 55:
 
== BBC MOS API Access ==
 
== BBC MOS API Access ==
 
To ensure cross-platform compatibility, most non-6502 implementations of BBC
 
To ensure cross-platform compatibility, most non-6502 implementations of BBC
BASIC translate <code>CALL</code>s and <code>USR</code> to MOS API entries to
+
BASIC translate <code>CALL</code>s and <code>USR</code> to MOS API entries
an equivalent call to the underlying MOS. The only addresses that are supported
+
to an equivalent call to the underlying MOS. The only addresses that are
by this are those listed below. The values in A%, X% and Y%, or the data or
+
supported by this are those listed below. The values in A%, X% and Y%, or
control block pointed to by X%, are passed in an appropriate manner to the
+
the data or control block pointed to by X%, are passed in an appropriate
underlying system.
+
manner to the underlying system.
  
 
{| class="wikitable" cellpadding="0"
 
{| class="wikitable" cellpadding="0"
Line 124: Line 124:
  
 
On 8-bit platforms the high 24 bits of X% and Y% are ignored, and the
 
On 8-bit platforms the high 24 bits of X% and Y% are ignored, and the
control block is found with X%+256*Y%. On platforms with larger registers, the
+
control block is found with X%+256*Y%. On platforms with larger registers,
control block is found at X%, ignoring Y% completely. Some platforms will
+
the control block is found at X%, ignoring Y% completely. Some platforms
check if X%<256 and use X%+256*Y%, though this should not be relied on.
+
will check if X%<256 and use X%+256*Y%, though this should not be relied on.
  
 
An additional advantage is that the control block is easily accessed with
 
An additional advantage is that the control block is easily accessed with
Line 134: Line 134:
 
Yes, 32000 passes A%=R1, etc., '''not''' R0.
 
Yes, 32000 passes A%=R1, etc., '''not''' R0.
  
When calling &FFCE with A%=0 to close a file, 6502 BASIC requires the channel
+
When calling &FFCE with A%=0 to close a file, 6502 BASIC requires the
to be passed in Y% but in ARM BASIC the channel must be passed in X%.
+
channel to be passed in Y% but in ARM BASIC the channel must be passed in
When calling from BASIC, the <code>[[CLOSE|CLOSE#]]</code> statement should be used.
+
X%. When calling from BASIC, the <code>[[CLOSE|CLOSE#]]</code> statement
 +
should be used.
  
  

Revision as of 17:56, 12 November 2017

USR is a BASIC function to call (execute) a machine code routine in memory or BBC MOS API entry. It returns a numerical result back to BASIC. On most non-6502 platforms, BBC BASIC intercepts calls to the standard BBC MOS API entries and translates them to an equivalent action.

USR
Availability Present in all versions of BBC BASIC.
Syntax BASIC I-V <num-var> = USR(<numeric>)
Token (hex) BASIC I-V BA (function)
Description BASIC I-V Sets the main CPU registers to the values of the resident integer

variables, and calls a machine code routine at the address given in the <numeric>. The routine should exit with the normal subroutine return instruction. After the routine exits, USR returns an integer holding values returned in CPU registers.

Associated keywords ?, !, $, CALL

Description

USR allows a BASIC program to use a piece of machine code as part of its operation. Machine code is a program in the form of binary data that can be run directly by the central processing unit (CPU).

USR is one of the ways to access functions of the MOS (its Application Programming Interface, or API.) Advanced programmers can also use USR to improve the performance of a BASIC program by rewriting the most time-consuming parts in machine code, as it runs much, much faster than the equivalent BASIC code.

Because USR is involved with the low level architecture of the computer, its precise function depends on which CPU is running BASIC. The CPU-specific preparation is the same as in CALL, except that there is no table of variables as USR's only argument is the <numeric> address. In general, USR sets certain CPU registers to the values of the resident integer variables, and jumps into a machine code routine at the address given in the <numeric>.

After the routine exits, BASIC captures a certain portion of the CPU's state, and returns it as the numeric result of the USR function. The value that is returned is again CPU-dependent:

BBC MOS API Access

To ensure cross-platform compatibility, most non-6502 implementations of BBC BASIC translate CALLs and USR to MOS API entries to an equivalent call to the underlying MOS. The only addresses that are supported by this are those listed below. The values in A%, X% and Y%, or the data or control block pointed to by X%, are passed in an appropriate manner to the underlying system.

Address MOS call Action
&FFF7 OSCLI Execute *command.
&FFF4 OSBYTE Various byte-wide functions.
&FFF1 OSWORD Various control block functions.
&FFEE OSWRCH Write character to output stream.
&FFE7 OSNEWL Write NewLine to output stream.
&FFE3 OSASCI Write character or NewLine to output stream.
&FFE0 OSRDCH Wait for character from input stream.
&FFDD OSFILE Perform actions on whole files or directories.
&FFDA OSARGS Read and write information on open files or filing systems.
&FFD7 OSBGET Read a byte from an a channel.
&FFD4 OSBPUT Write a byte to a channel.
&FFD1 OSGBPB Read and write blocks of data.
&FFCE OSFIND Open or close a file.

Register usage

CPU Registers on entry Result returned by USR
6502 A=A%, X=X%, Y=Y%, Cy=b0 of C% b0-7=A, b8-15=X
b16-23=Y, b24-31=P
6809 A=A%, B=B%, U=U%, X=X%, Y=Y%, Cy=b0 of C% b0-7=A, b8-15=X
b16-23=Y, b24-31=CC
Z80 A=A%, B=B%, C=C%, D=D%, E=E%, H=H%, L=L% b0-b15=HL'
b16-b31=HL
Z80
BBC API call
A=A%, L=X%, H=H%, E=E% b0-b7=A, b8-b23=HL, b24-31=F
32016 R1=A%, R2=B%, R3=C%, R4=D%, R5=E%, R6=F%, R7=G% b0-b31=R1
32016
BBC API call
R1=A%, R2=X%,
R3..R7=contents of control block at X%
b0-b7=R1, b8-b23=R2
PDP-11 R0=A%, R1=B%, R2=C%, R3=D%, R4=E%, R5=F% b0-b15=R0, b16-b31=R1
PDP-11
BBC API call
R0=A%, R1=X%, R2=Y% b0-b7=R0, b8-b23=R1
ARM R0=A%, R1=B%, R2=C%, R3=D%, R4=E%,
R5=F%, R6=G%, R7=H%, R8=I%, R9=J%
b0-b31=R0
ARM
BBC API call
R0=A%, R1=X%, R2=Y%, or
R1..R5=contents of control block at X%
b0-b7=R0, b8-b31=R1

When passing the address of a data structure or control block, code similar to the following should be used.

   DIM ctrl% 31      :REM Control block, may be anywhere in 32-bit memory space
   X% = ctrl%        :REM X% holds full 32-bit address
   Y% = X% DIV 256   :REM Y% holds 32-bit address, shifted right 8 bits

On 8-bit platforms the high 24 bits of X% and Y% are ignored, and the control block is found with X%+256*Y%. On platforms with larger registers, the control block is found at X%, ignoring Y% completely. Some platforms will check if X%<256 and use X%+256*Y%, though this should not be relied on.

An additional advantage is that the control block is easily accessed with X%, for example, X%!2=load%, etc.

Notes

Yes, 32000 passes A%=R1, etc., not R0.

When calling &FFCE with A%=0 to close a file, 6502 BASIC requires the channel to be passed in Y% but in ARM BASIC the channel must be passed in X%. When calling from BASIC, the CLOSE# statement should be used.


-- beardo 19:06, 5 May 2007 (BST) Jgharston 17:40, 8 October 2007 (BST) Jgharston (talk) 15:02, 19 August 2017 (CEST)