Difference between revisions of "USR"
m (Added 6809.) |
m (Added ARM note.) |
||
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 to MOS API entries to an equivalent call to the | + | BASIC translate <code>CALL</code>s and <code>USR</code> to MOS API entries to |
− | underlying MOS. The only | + | an equivalent call to the underlying MOS. The only addresses that are supported |
− | below. The values in A%, X% and Y%, or the data or control block pointed to by | + | by this are those listed below. The values in A%, X% and Y%, or the data or |
− | X%, are passed in an appropriate manner to the underlying system. | + | control block pointed to by X%, are passed in an appropriate manner to the |
+ | underlying system. | ||
{| class="wikitable" cellpadding="0" | {| class="wikitable" cellpadding="0" | ||
Line 131: | Line 132: | ||
===Notes=== | ===Notes=== | ||
− | Yes, | + | 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 <code>[[CLOSE|CLOSE#]]</code> statement should be used. | ||
+ | |||
-- [[User:Beardo|beardo]] 19:06, 5 May 2007 (BST) | -- [[User:Beardo|beardo]] 19:06, 5 May 2007 (BST) | ||
[[User:Jgharston|Jgharston]] 17:40, 8 October 2007 (BST) | [[User:Jgharston|Jgharston]] 17:40, 8 October 2007 (BST) | ||
+ | [[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 15:02, 19 August 2017 (CEST) |
Revision as of 14:02, 19 August 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.
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 CALL
s 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)