RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

OS_Byte


Introduction

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.

Parameters

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:

ADD Rn,R1,R2,LSL#8

Calling OS_Byte

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.

Calls where R0 is less than 128

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.

Calls where R0 is between 128 and 165 (inclusive)

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.

Calls where R0 is between 166 and 255 (inclusive)

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:

New value = (Old value AND R2) EOR R1

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.

Reading and writing values

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:

R2 = &FF and R1 = &00
and where the value is set to a particular number:
R2 = &00 and R1 = new value
Altering selected bits

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:

  • clear the bits of R2 corresponding to the bits you want to alter
  • set the corresponding bits of R1 to the new value you want these bits to have.

For example, to set bits 2 - 4 of a status variable to the binary pattern 101, and leave the rest unaltered, you would use:

R2 = &E3 (11100011 in binary) and
R1 = &14 (00010100 in binary)

In all cases, the calls in the range 166 - 255 return with the previous value of the variable in R1 and the value of the next variable in RAM (ie the one which would be accessed with R0+1) in R2. The exception is where R0 = 255, where there is no defined 'next' location, and so the value of R2 is undefined.

Altering any of these variables does not have any immediate effect, but may often seem to, as many are acted upon by interrupt routines.

Which call to use when

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.

OS_Byte and interrupts

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 do not change the way it alters the interrupt status
  • you do not make it take so long that interrupts are disabled for an unreasonably long time.

Adding OS_Byte calls

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.

The *FX command

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:

*FX 138,0,65

Calling *FX

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.

SWI calls


OS_Byte
(SWI &06)

General purpose call to alter status variables, and perform other actions

On entry

R0 = OS_Byte number (so for OS_Byte 1, R0 = 1)
R1, R2 - as required by individual OS_Byte

On exit

R0 preserved
R1, R2 - as returned by individual OS_Byte

Interrupts

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 mode

Processor is in SVC mode

Re-entrancy

SWI is re-entrant for some values of R0

Use

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:

  • If R0 is less than 128, then generally only R1 is used to pass further information. These calls set a status variable, and may also perform some other task. R2 is corrupted unless stated otherwise.
  • If R0 is between 128 and 165 (inclusive), 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.
  • For calls with R0 between 166 and 255 (inclusive) on entry, the action is always the same. R0 acts as an index to a status variable, which is altered using the contents of R1 and R2:

    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.

Related SWIs

OS_Word

Related vectors

ByteV

* Commands


*FX

Calls OS_Byte to alter status variables, and to perform other closely related actions

Syntax

*FX reason_code [[,] r1 [[,] r2]]

Parameters
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).

Use

*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.

Examples

*FX 138,0,&41 r2 is specified in hexadecimal

*FX 247 4_01 r1 is specified in base 4

Related commands

None

Related SWIs

OS_Byte

Related vectors

ByteV

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015