Operating Systems 02

By Chris Dewhurst

Originally published in EUG #60

This article appeared in the HOME COMPUTER ADVANCED COURSE MAGAZINE (c) 1984

In the first part of this series we looked at how an operating system is arranged in general terms and examined and, in particular, how the BBC Micro's OS is arranged. In this instalment, we'll look at how the BBC OS actually uses its memory, and how vectors are used in a computer operating system.

The BBC Micro makes use of various areas of memory, many of which have multiple functions. A typical example of this is page &9 of the memory - the area of RAM between locations &900 and &9FF - which is used, at different times, as the RS432 output buffer, a cassette output buffer, speech workspace and extended sound workspace! No one can accuse Acorn of not getting the most from its memory.

A further example is the block from &0E00 to &1900; in a BBC Micro with a cassette recorder as its filing system, this area of memory is free for use as BASIC program space. However, when a disc system is being used, this area is used as disc filing system workspace, reducing the amount of memory left for BASIC programs by over 2.5 Kbytes. This is extremely annoying in screen Modes 0 to 2, where memory is restricted anyway.

The final example of multiple use of memory is the area between &8000 to &BFFF. If a DFS ROM, a word processor or utility ROM is fitted in the machine, it will occupy this block. This is also the area of memory that the BASIC interpreter ROM resides in. These are called 'paged ROMs'; only one of them can be active at any one time. The ROM required is selected by the operating system, and 'switched in', or 'paged in' - hence the name. Under normal circumstances, the BASIC ROM is paged in, and the BASIC interpreter is running, thus enabling us to type in and execute BASIC programs. However, when we execute a DFS command, the OS pages the DFS ROM, executes the command, and then pages the BASIC ROM back in. During the execution of the DFS commands, the BASIC ROM is simply ignored. Other ROMs, such as the Telesoftware Filing System or the Wordwise wordprocessor chip, also occupy this memory space and are also paged in and out as required. It's probably just as well that the BBC Micro uses the same area of memory for several purposes, as otherwise there'd be little memory left for us to work with.

User Memory

Once the OS has taken its share of the computer memory, what remains is the available user memory. The BASIC system variable PAGE contains the address of the Start of BASIC program area, and the variable HIMEM points to the start of the screen display memory; the space between is available for BASIC programs, variables and machine code programs. Type in this instruction to find these addresses, and the memory available for BASIC programs:


In the following table, you'll find a brief description of the relative merits of different storage areas for machine code in the BBC Micro.

       When Area is Suitable For Machine      Type of Filing System
                 Code Programs                Tape:    Disc:
       ---------------------------------      ---------------------
       &0D00 - &0DFF
       Page &D - only if no paged ROMs are       (o)      X
       in the machine

       &0B00 - &0CFF
       Page &B and &C - if no user defined
       characters or user function keys          (o)      (o)
       are used in the program

       &0A00 - &0AFF
       Page &A - if serial inferface is not      (o)      (o)
       in use

       Space saved in BASIC program area in
       the DIM command
       ---------------------------------      ---------------------
       o = OK; (o) = OK with Reservations; X = Not used

For most routines that are to be used in conjunction with BASIC programs, storing the code in the BASIC program area is the best method.

Once the machine code is in memory, it generally needs some workspace to allow it to run. Most 6502 machine code programs require some zero page locations as workspace, mainly because certain indexed addressing instructions will need zero page locations. Acorn have made extensive use of this page for the OS, but some locations have been set aside for machine code programming. A byte by byte account of what each of the OS locations does is little use to the programmer, and directly accessing these locations is not encouraged - the useful locations should be accessed by calling the appropriate OS versions, thus avoiding problems when a machine code program written under one OS version is run under a different version.

                  Zero page location    Usage
                  ------------------    -----
                  &FA - &FF             OS
                  &F8 / &F9             Unused in OS 1.2
                  &A0 - &F7             OS
                  &90 - &9F             Econet
                  &70 - &8F             Unused
                    0 - &6F             BASIC

Entering The OS

The two major routes we can take to use the routines in the BBC OS are the OSBYTE and OSWORD routines:

OSBYTE enables us to affect the behaviour of many OS routines, by passing control codes and parameters in the A, X and Y registers of the 6502. In BASIC, we can access the OSBYTE routines via the *FX command. *FX is followed by either two or three numbers: the first number is the control or function code passed to the A register; the second is the number passed to the X register; and the third is the number passed to the Y register. The third parameter is not required by all OSBYTE calls. In machine code, OSBYTE is called at address &FFF4. These two versions are equivalent in function:

                   BASIC           Assembly Language
                   ------          -----------------
                   *FX4,1          LDA #4
                   LDX #1
                   JSR &FFF4

The value in the A register defines exactly what a particular call to OSBYTE will do. The above call, for example, affects the actions of the cursor keys; the parameter passed over in the X register specifies whether the cursor keys retain their normal editing function or whether they simply return an ASCII code.

It's a sad fact of life that all OS routines cannot be affected by OSBYTE. Its main drawback is the limit on the number of parameters that you can pass over to the routine. If we ignore the contents of the A register, which tells the OS which routine within OSBYTE we wish to use, then we can only pass two parameters in the X and Y registers. If we want to pass any more than this then we use the second routine, OSWORD.

OSWORD enables us to do such things as sound generation, disc reads and writes, and so on. This is the difference between OSWORD and OSBYTE; OSBYTE affects *how* the OS does certain tasks, and OSWORD enables us to do particular tasks. OSWORD obtains its parameters from a *parameter block* that is pointed to on entry to the OSWORD routine by the 6502 X and Y registers. This parameter block is situated in RAM, and its size and arrangement depend upon the OSWORD call being made. The A register contains a function code that determines which of the OSWORD functions are to be executed by the OS. Once the registers and the parameter block have been prepared, OSWORD is called at address &FFF1. OSBYTE and OSWORD are the principal means of entry to the OS; because of their importance, we'll look at them in greater detail in later parts of the series.

Other OS routines are entered, from BASIC, by typing in an asterisk (*) followed by the command. The presence of the * causes the command following it to avoid the BASIC interpreter and be passed to an OS routine that bears the name OSCLI, meaning 'Operating System Command Line Interpreter'. This interprets the OS commands that are typed in and acts upon them by calling the appropriate routines in the OS. Such commands are often called * or Star Commands. The table shown lists those Star Commands recognised by the BBC; any not recognised, spelt incorrectly or without the correct number of parameters will usually give the "Bad command" error message.

Command       Description and Comments
-------       ------------------------
*HELP         This will give the version number of the BASIC. It can 
              also be used to gain information about other paged ROMs
              fitted - e.g. *HELP DFS

*BASIC        This command will enter the BASIC language. A variation of
              this command, such as *WORD, will enter a paged ROM, in
              this case View

*CODE         In OS 1.2 only. This enables the user to add new commands
*LINE         to the OS

*KEY          Used to program the function keys

*MOTOR n      Used to control the tape motor relay: n=0 turns the relay
              off and n=1 turns the relay on

*ROM, *TAPE   Used to initialise the appropriate filing system - i.e.
*DISC, *NET   *TAPE will enter the 1,200 baud tape filing system, and
              *DISC will enter the disc filing system

*FX           This enables the programmer to control the values of
              various OS variables, thus controlling the behaviour of
              the OS

*RUN, *OPT    These are all filing system commands and will be examined
*LOAD, *.     later in the series

*SPOOL        *SPOOL sends the screen output to the screen and to a 
              file. *EXEC reads in data from a file as if it were being
              read from the keyboard

*TV x,y       Affects the vertical position of the screen and the screen
              interface: x=0 means no change in vertical position, x=1
              moves the screen down one line, x=255 moves screen up one
              line; y=0 interlace on, y=1 interlace off. The effects of
              this command come into operation at the next mode change
              and stay in effect until a - or another *TV
              command is issued

For further explanation of the use of these commands, consult the BBC Micro's user guide.

We can pass commands to the Command Line Interpreter (CLI) by using the OS routine or by the direct method. OSCLI's uses are twofold: first of all, it enables us to pass commands shown in the table to the CLI from machine code should we want to; and secondly it enables us to pass BASIC string variables over to the CLI. The programs that follow feature both these uses. Notice that the integer variables, A%, X% and Y%, pass their values directly into the A, X and Y registers. X% (or the X register) and Y% (or the Y register) point to the position in memory of the string of characters, that is to be treated as a * command, and is to be interpreted and executed by the OSCLI routine. X holds the low byte of the address and Y holds the high byte of the address.

    BASIC version                   BASIC + Assembly Language Version
    -------------                   ---------------------------------
    10DIM C 100                     10DIM C 100
    20oscli=&FFF7                   20oscli=&FFF7
    30INPUT"ENTER COMMAND",$C       30FOR I%=0 TO 2 STEP 2
    40$C=A$                         40P%=&C00
    50X%=C MOD 256                  50[ OPT I%
    60Y%=C DIV 256                  60.code    LDX #C MOD 256
    70CALL oscli                    70         LDY #C DIV 256
    80GOTO 30                       80         JSR oscli
                                    90         RTS
                                   100]:NEXT I%
                                   110INPUT "ENTER COMMAND ",A$
                                   130CALL code
                                   140GOTO 110

Running this program produces a prompt: the user types in a * command, presses RETURN and the command will be executed. The rather odd-looking DIM statement in line 10 of both these programs forces the computer to set aside 100 bytes of memory in the space set aside for BASIC variables and initialises the variable 'C' with the address of the start of this block of memory. This 100 bytes can then be used for storing machine code programs, or, as in this case, data for machine code programs. The $C=A$ statement puts the bytes that make up the command string held in A$ into the block of 100 bytes, starting at the first byte reserved by the DIM command. In both programs, the X and Y registers (or the X% and Y% variables) are set up and the call is made to OSCLI. The command string is then executed.

This program is the basis of a routine for use in menu-driven programs, where it might be useful to allow the user to do things like catalogue discs or tapes without leaving the program. The command required is simply put in to the string variables and passed to OSCLI for execution. Typing *A$ will not work. The OS will attempt to execute a command called *A$, which simply doesn't exist!

Using this technique, it is also possible to pass numeric variables to a * command by using the STR$ function to convert them into strings. Normally, the CLI will not accept any variable names passed to it; it gives the Bad Command error message instead of trying to evaluate the variable concerned.

Any * command that is not recognised by the OS is passed over to any paged ROMs. Each one is asked if it recognises the command; if it does then it executes it. Commands not passed for execution in this fashion are then treated as bad commands *only if* a fast filing system, such as a disc drive, is not in use. If it is, then the disc will be inspected to see if it contains a file with the same name as the command (without the *). If it does, then the file is loaded into the machine and treated as a machine code program. This can cause *big* problems if the file isn't a machine code program! The computer usually 'hangs' until you put it out of its misery. If such a file isn't found then the "Bad Command" error message is printed.

                          BBC Micro Memory Map:
       &FF00-&FFFF     OS ROM
       &FEC0-&FEC1     ADC Chip
       &FEA0-&FEA2     6854
       &FE80-&FE83     8271 Floppy Disc Controller
       &FE60-&FE7F     User VIA
       &FE40-&FE5F     System VIA
       &FE30           Paged ROM Select
       &FE20-&FE21     Video ULA
       &FE08           6850
       &FE00-&FE07     6845 CRTC
       &FD00-&FDFF     JIM
       &FC00-&FCFF     FRED
       &C000-&FBFF     OS ROM
       &8000-&BFFF     BASIC ROM / Paged ROMs
       &7FFF           RAM Top
                      (Video RAM
       Changeable)    (BASIC Stack
       boundaries)    (Top of variables ?2+256*?3
                      (BASIC Program
       &1900           PAGE for Disc
                       BASIC Program or DFS Workspace
       &E00            PAGE
       &D00-&DFF       Paged ROM Wkspace or User Machine Code
       &C00-&CFF       User-Defined Characters
       &B00-&BFF       User-Defined Keys
       &900-&AFF       BUFFERS
       &800-&8FF       SOUND Workspace
       &400-&7FF       BASIC Workspace
       &3E0-&3FF       Keyboard Buffer
       &380-&3DF       Tape System Variables
       &300-&37E       VDU Wkspace for text/graphics
       &236-&2FF       OS Workspace and Variables Written by FX Calls
       &200-&235       Vectors
       &100-&1FF       6502 stack
       &0-&FF          Zero Page