Transient Utility files (filetype &FFC) contain position independent code which is loaded into the RMA and executed in User Mode.
The purpose of a Utility is for when you want to run a small utility and then return back to the program environment that you were in prior to calling the Utility (unlike loading an Absolute program which would normally replace the current program).
On entry to a transient Utility, the registers are as follows:
Entry conditions | |
---|---|
R0 | Pointer to first character of command the line |
R1 | Pointer to first character of the command tail (will be a control character if no parameters given) |
R12 | Pointer to 1024 bytes of workspace |
R13 | Pointer to end of workspace, for stack |
R14 | Return address |
A transient Utility is entered in User Mode with interrupts enabled. You should only call X form SWIs, and if there is an error, you should exit by setting the V flag and pointing R0 to an error block.
The operating system provides you with 1024 bytes of workspace, which includes the stack descending downwards from the end of the workspace. If more space is required, it should be claimed from the RMA.
You must exit the transient Utility with MOV PC, R14
(after freeing any RMA claims). As you are never the “current program”, you must not call OS_Exit.
Aemulor may trigger problems with some Utilities. If the Utility is known to be 32 bit safe, it should be marked as such by appending the four bytes ‘3
’ ‘2
’ ‘O
’ (upper case ‘o’) and ‘K
’ (in that order!) to the end of the file.
This can be achieved by adding this to the end of the Utility source:
DCS "32OK"
RISC OS Ltd has defined a header for Utility programs.
This is documented here for completeness, though please note that RISC OS 5 does not make use of such a header, and Aemulor would still require the “32OK” word at the end of the file.
ROLtd Utility Header | ||
---|---|---|
+0 | Branch to entry point (to skip over header) | |
+4 | First magic value &&79766748 (“Hgvy”) | |
+8 | Second magic value &216C6776 (“vgl!”) | |
+12 | Read only size (or 0 to mean the size of the file) | |
+16 | Read/write size (or 0 to mean the size of the file) | |
+20 | Either 26 or 32 depending on whether built for 26 bit or 32 bit systems |
The two magic values are ROT13 for “Utility!”.
A simple example program, reports if the system is 26 bit or 32 bit.
DIM code% 76 FOR l% = 0 TO 2 STEP 2 P% = code% [ OPT l% ADR R0, thisisa SWI "XOS_Write0" TEQ R0, R0 TEQ PC, PC ADREQ R0, is32 ADRNE R0, is26 SWI "XOS_Write0" ADR R0, bitsystem SWI "XOS_Write0" MOV PC, R14 .thisisa EQUS "This is a "+CHR$(0) .is32 EQUS "32"+CHR$(0) .is26 EQUS "26"+CHR$(0) .bitsystem EQUS " bit system."+CHR$(0) ALIGN EQUS "32OK" ] NEXT OSCLI("Save $.26or32 "+STR$~(code%)+" "+STR$~(P%)) OSCLI("SetType $.26or32 &FFC") END