Memory Modules

From NitrOS-9
Jump to: navigation, search

Memory Modules

In Chapter 2, you learned that NitrOS-9 is based on the concept that memory is modular. This means that each program is considered to be an individually named object.

You also learned that each program loaded into memory must be in the module format. This format lets NitrOS-9 manage the logical contents of memory, as well as the physical contents. Module types and formats are discussed in detail in this chapter.

Module Types

There are several types of modules. Each has a different use and function. These are the main requirements of a module:

  • It cannot modify itself.
  • It must be position-independent so that NitrOS-9 can load or relocate it wherever space is available. In this respect, the module format is the NitrOS-9 equivalent of load records used in older operating systems.

A module need not be a complete program or even 6809 machine language. It can contain BASIC09 I-code, constants, single subroutines, and subroutine packages.

Module Format

Each module has three parts: a module header, a module body, and a cyclic-redundancy-check value (CRC value).

Module Header
Program
Or
Constants
CRC Value

Module Header

At the beginning of the module (the lowest address) is the module header. Its form depends upon the module’s use. The header contains information about the module and its use. This information includes the following:

  • Size
  • Type (machine code, BASIC09 compiled code, and so on)
  • Attributes (executable, re-entrant, and so on)
  • Data storage memory requirements
  • Execution starting address

Usually, you do not need to write routines to generate the modules and headers. All OS-9 programming languages automatically create modules and headers.

Module Body

The module body contains the program or constants. It usually is pure code. The module name string is included in this area.

The following figure provides the offset values for calculating the location of a module’s name. (See “Offset to Module Name.”)

CRC Value

The last three bytes of the module are the Cyclic Redundancy Check (CRC) value. The CRC value is used to verify the integrity of a module.

When the system first loads the module into memory, it performs a 24-bit CRC over the entire module, from the first byte of the module header to the byte immediately before the CRC. The CRC polynomial used is $800FE3.

As with the header, you usually don’t need to write routines to generate the CRC value. Most OS-9 programs do this automatically.

Module Headers: Standard Information

The first nine bytes of all module headers are defined as follows:

Relative Address Use
$00,$01 Sync bytes ($87,$CD)
$02,$03 Module size
$04,$05 Offset to module name
$06 Module type/language
$07 Attributes/revision level
$08 Header check

Sync Bytes

The sync bytes specify the location of the module. (The first sync byte is the start of the module.) These two bytes are constant.

Module Size

The module size specifies the size of the module in bytes (includes CRC).

Offset to Module Name

The offset to module name specifies the address of the module name string relative to the start of the module. The name string can be located anywhere in the module. It consists of a string of ASCII characters with the most significant bit set on the last character.

Type/Language Byte

The type/language byte specifies the type and language of the module.

The four most significant bits of this byte indicate the type. Eight types are predefined. Some of these are for OS-9’s internal use only. The type codes are given here (0 is not a legal type code):

Code Module Type Name
$1x Program module Prgrm
$2x Subroutine module Sbrtn
$3x Multi-module (for future use) Multi
$4x Data module Data
$5x-$Bx User-definable module  
$Cx NitrOS-9 system module Systm
$Dx NitrOS-9 file manager module FlMgr
$Ex NitrOS-9 device driver module Drivr
$Fx NitrOS-9 device descriptor module Devic

The four least significant bits of Byte 6 indicate the language (denoted by x in the previous Figure). The language codes are given here:

Code Language
$x0 Data (non executable)
$x1 6809 object code
$x2 Basic09 I-Code
$x3 Pascal P-Code
$x4-$xF Reserved for future use

By checking the language type, high-level language runtime systems can verify that a module is the correct type before attempting execution. Basic09, for example, can run either I-Code or 6809 machine language procedures arbitrarily by checking the language type code.

Attributes/Revision Level Byte

The attributes/revision level byte defines the attributes and revision level of the module.

The four most significant bits of this byte are reserved for module attributes. Currently, only Bit 7 is defined. When set, it indicates the module is re-entrant and, therefore, shareable.

The four least significant bits of this byte are a revision level in the range 0 to 15. If two or more modules have the same name, type, language, and so on, NitrOS-9 keeps in the module directory only the module having the highest revision level. Therefore, you can replace or patch a ROM module, simply by loading a new, equivalent module that has a higher revision level.

Note: A previously linked module cannot be replaced until its link count goes to zero.

Header Check

The header check byte contains the one’s complement of the Exclusive-OR of the previous eight bytes.

Module Headers: Type-Dependent Information

More information usually follows the first nine bytes of a module header. The layout and meaning vary, depending on the module type.

Module types $Cx-$Fx (system module, file manager module, device driver module, and device descriptor module) are used only by OS-9. Their formats are given later in the manual.

Module types $lx through $Bx have a general-purpose executable format. This format is often used in programs called by F$Fork or F$Chain. Here is the format used by these module types:

$00
Sync Bytes ($87, $CD)
Header
Parity
Module
CRC
$01
$02
Module Size (bytes)
$03
$04
Module Name Offset
$05
$06
Type
Language
$07
Attributes
Revision
$08
Header Parity Check
 
$09
Execution Offset
$0A
$0B
Permanent Storage Size
$0C
$0D
Additional optional header extensions
Module Body
object code
constants
and so on
24-bit CRC Check Value
 

As you can see from the preceding chart, the executable memory has four extra bytes in its header. They are:

$09,$0A Execution offset
$0B,$0C Permanent storage size

Execution Offset. The program or subroutine’s offset starting address, relative to the first byte of the sync code. A module that has multiple entry points (such as cold start and warm start) might have a branch table starting at this address.

Permanent Storage Size. The minimum number of bytes of data storage required to run. Fork and Chain use this number to allocate a process’ data area.

If the module is not directly executed by a Fork or Chain system call (for instance a subroutine package), this entry is not used by NitrOS-9. It is commonly used to specify the maximum stack size required by re-entrant subroutine modules. The calling program can check this value to determine if the subroutine has enough stack space.

When NitrOS-9 starts after a single system reset, it searches the entire memory space for ROM modules. It finds them by looking for the module header sync code ($87,$CD).

When NitrOS-9 detects the header sync code, it checks to see if the header is correct. If it is, the system obtains the module size from the header and performs a 24-bit CRC over the entire module. If the CRC matches, NitrOS-9 considers the module to be valid and enters it into the module directory. All ROM modules that are present in the system at startup are automatically included in the system module directory.

After the module search, NitrOS-9 links to the component modules it found. This is the secret to NitrOS-9’s ability to adapt to almost any 6809 computer. It automatically locates its required and optional component modules and rebuilds the system each time it is started.