www.riscos.com Technical Support:
Most SWIs deal with only one task. For example, OS_Module deals with modules, OS_RemoveCursors just removes cursors, and so on. However, there are two SWIs which perform a wide variety of operations. They are called OS_Byte and OS_Word. They exist, principally, to ease the conversion of software from the older BBC and Master series of computers. The operating systems on these older machines have two corresponding routines called OSBYTE and OSWORD.
Because the calls are multi-purpose, they tend to appear in more than one chapter of this manual. This chapter documents OS_Byte in general terms, so that when examples of its use are given later on, you will understand the entry and exit conditions better. The next chapter outlines how OS_Word works.
OS_Byte takes one, two or three parameters. The first parameter, passed in R0, is the reason code. This indicates which particular action you require OS_Byte to take. It has the range 0 - &FF. Thus when we talk about 'OS_Byte 81', this is shorthand for 'OS_Byte with R0 set to 81 on entry'. A complete list of the OS_Byte numbers may be found in the Index of OS_Bytes.
The second and third parameters are passed in R1 and R2. These too are in the range 0 - &FF; the name OS_Byte comes from the fact that it deals with byte-wide parameters.
In fact, all OS_Byte routines mask out the top 24 bits of the parameters when they use them. Although these top bits are not used, calls to OS_Byte always preserve them in R0; the same applies for R1 and/or R2 where they are documented as preserved. If you are writing a routine to implement or decode OS_Byte calls, you must make sure you preserve the top 24 bits, at least in R0. This means you will have to mask the parameter(s) into temporary registers rather than back into the passed parameters.
Some OS_Byte calls return values. On earlier Acorn computers these were always byte-wide, but on RISC OS computers some of these values may now be too large to fit in a single byte, and should be treated as whole words. For example, if you were reading the number of spaces left in a buffer using OS_Byte 128, you might read the two 'byte' result returned in R1 (low byte) and R2 (high 'byte' - in fact 24 bits) like this:
You call the OS_Byte SWI in exactly the same way as any other SWI. See the chapter entitled An introduction to SWIs for details.
The calls may be grouped into three main classes, according to the value of R0 on entry.
If R0 is less than 128, then only R1 is used to pass further information. However, R2 is often used as a temporary register and corrupted in the process. You use these calls to set status variables, which the computer uses to control its operation. For example, OS_Byte 5 sets the status variable for the type of printer that is connected.
In addition to setting the appropriate status variable, these calls may also perform some other task. For example, OS_Byte 5 also waits for the current printer buffer to become empty before returning. Although these calls sometimes return the 'previous' state of the status variable, they are normally used for the action they perform, rather than the information they return.
If R0 is between 128 and 165, both R1 and R2 are used to hold parameters, and both registers may contain information on exit from the call. The calls are often used for the results they return, rather than to perform particular actions.
For calls with R0 between 166 and 255 on entry, the action is always the same. R0 acts as an index into the RAM which holds the status variables. They are held in consecutive memory locations, so R0=166 accesses the first one, R0=167 accesses the second one, and so on. The contents of R1 and R2 determine what happens to the status variable:
On exit, R1 holds the old value of the status variable, and R2 holds the value of the status variable in the next memory location.
The most useful application of this rule occurs when the old value is returned without being altered (allowing the status to be read 'non-destructively') as shown below:
These are the only cases which are stated in the descriptions of OS_Bytes in this guide. Other values of R1 and R2 may be used to alter only selected bits of the status variable. You should:
For example, to set bits 2 - 4 of a status variable to the binary pattern 101, and leave the rest unaltered, you would use:
Altering any of these variables does not have any immediate effect, but may often seem to, as many are acted upon by interrupt routines.
Many of the calls in this last group access the same status variable as the low-numbered calls, between 0 and 127. However, as noted above, the lower group may also perform some other action in addition to changing the variable value. This means that the lower group should be used to alter a variable, whereas the upper group may be used for reading the current value without changing it.
Like most important SWIs, OS_Byte is vectored so you can alter how it works. Before its vector is called, interrupts are disabled. Most OS_Byte routines are so short that there is no need for them to re-enable interrupts - instead they rely on RISC OS doing this when control is returned to you. Because these OS_Byte routines do not re-enable interrupts they are also used by interrupt handling routines.
If you replace or alter an OS_Byte routine, make sure that:
You can add your own OS_Byte calls to RISC OS by installing a routine on the software vector that OS_Byte calls use. For full details, see the chapter entitled Software vectors.
There is an alternative, but less preferable way of adding OS_Byte calls. If you issue an OS_Byte with a number that RISC OS doesn't recognise, it issues an Unknown OS_Byte service call to all modules. Your module can then trap this service call and implement the new OS_Byte. For full details, see the chapter entitled Modules.
Because OS_Bytes perform many useful functions, a * Command is provided to call the routine directly. It has the syntax:
*FX <reason code>[[,] <r1> [[,] <r2>]]
The command is followed by one, two or three parameters, which may be separated by spaces or commas. The values reason code, r1 and r2 are loaded into register R0, R1 and R2 respectively; then OS_Byte is called. Any omitted values are set to zero. So:
MOV R0,#138 MOV R1,#0 MOV R2,#65 SWI OS_Byte
has the same effect as:
The *FX command does not display any returned values; you cannot use it to read the values of status variables from the command line. It is called in the same way as any other * Command; see the chapter entitled * Commands and the CLI for details.
General purpose call to alter status variables, and perform other actions
R0 = OS_Byte number (so for OS_Byte 1, R0 = 1)
R1, R2 - as required by individual OS_Byte
R1, R2 - as returned by individual OS_Byte
Interrupts are disabled by the OS_Byte decoding routine
Interrupt status is unaltered (ie remains disabled) for most values of R0
Fast interrupts are enabled
Processor is in SVC mode
SWI is re-entrant for some values of R0
The action taken by this SWI depends on the reason code passed in R0. You should see the individual documentation of each OS_Byte for full details:
New Value = (Old Value AND R2) EOR R1
To read the status variable, use R1 = &00, and R2 = &FF. To write to the status variable, use R1 = new value, and R2 = &00.
For an index of all OS_Byte calls, see the chapter entitled Index of OS_Bytes.
Calls OS_Byte to alter status variables, and to perform other closely related actions
*FX reason_code [[,] r1 [[,] r2]]
|reason_code||from 0 to 255|
|r1||from 0 to 255|
|r2||from 0 to 255|
The parameters are in decimal by default, but you may specify other bases (see Examples below).
*FX alters status variables, which the computer uses to control its operation. You can either read from them, or write to them. Some *FX commands will also perform other actions closely related to the status variable that is being altered.
This command merely calls the SWI OS_Byte, passing the reason code in R0, r1 in R1, and r2 in R2. The reason code determines which status variable is affected.
Individual *FX commands are not documented. You should instead refer to the documentation of individual OS_Bytes. For example, to see what *FX 138, ... will do, see the entry for OS_Byte 138. For an index of all OS_Byte calls, see the chapter entitled Index of OS_Bytes.
*FX 138,0,&41 r2 is specified in hexadecimal
*FX 247 4_01 r1 is specified in base 4