IEN 198
     INDRA Note 1041
     15th. September 1981
            Extended Memory MOS for a UNIX Development Host
                              Robert Cole
          ABSTRACT: This note describes a version of  the
               RSRE  Extended Memory MOS that can be used
               with a UNIX development  host.   The  run-
               time  MOS system design is explained.  The
               linking and loading phases are  described.
               Documentation is included in an appendix.
                     Department of Computer Science
                       University College, London

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
                              C O N T E N T S
       1.  Introduction..............................................2
       2.  Linking on UNIX...........................................3
       3.  Loading...................................................5
       4.  MOS Initialisation........................................7
       5.  MOS Runtime...............................................7
       6.  DDT.......................................................7
                                 - 1 -               [Robert Cole]

1. Introduction
        Recently a version of  MOS  (Micro  Operating  System)  was
     developed  at RSRE [1] which enabled the extra memory capacity
     of 11/23 and 11/34 computers to be used.  The development  was
     carefully  designed  to increase the buffer space available to
     all processes without adding significant  'context  switching'
     overheads.  A  further  development  at  UCL has used the same
     design, but for use on a UNIX development host.  Standard UNIX
     software  does  not  cater  for  extended memory systems to be
     built by users.  As a result a new linker was produced, giving
     some  flexibility to the resulting MOS system.  It was decided
     to extend the EMMOS system of RSRE  by  using  both  USER  and
     KERNEL  addressing  modes  to  provide  extra  protection  and
     addressing space.
        Figure 1 shows the two address mode maps that are  used  at
             ___________             ___________
             |         |             |  stack  |
             |         |             |---------|
             |  I/O    |             | process |
             |  page   |      7      | buffers |
             |         |             |---------|
             |         |             |  data   |
             |_________|             |_________|
             |         |             | process || write
             |   DDT   |      6      |  text   || protected
             |_________|             |_________||
             |         |             |         |
             :         :      5      :         :
             : shared  :      :      : shared  :
             : buffers :      :      : buffers :
             :         :      2      :         :
             |_________|             |_________|
             |PCTs+DCTs|      1      |PCTs+DCTs||
             | drivers |             | drivers || write
             |   MOS   |      0      |   MOS   || protected
             |_________|             |_________||
               kernel                   user
                      Figure 1. Runtime Memory Map
     Here the I/O page is only available to  the  Kernel  mode  and
     both  MOS  and  the  process instructions are protected during
     process execution.  The UNIX object format naturally separates
     text  (instructions)  from  data  (program variables) so it is
     possible to use this in our design.  The last page of the user
     address  space  is  loaded with the process data at the bottom
     and the process stack is created at  the  top.   The  full  8K
     bytes  is  allocated  so any space left between can be used as
                                 - 2 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     process private buffer space and managed by the system  buffer
     management code.
        Buffers, which are common to  all  processes,  are  set  up
     above  the  MOS  Kernel and below the processes.  Normally the
     processes are all loaded in pages 6  and  7,  however  a  very
     large  process  may  force  this boundary down to page 5.  The
     size of the  MOS  Kernel  will  vary  from  system  to  system
     depending on the number of processes, the number and nature of
     devices, and any other code that is shared between  processes.
     The  MOS  Kernel size is rounded up to the next page boundary.
     Figure 1 shows 2 pages being used for MOS.   The  Kernel  mode
     (and MOS initialisation) stack is placed at the top of the MOS
     Kernel space.  Thus the shared buffer area is squeezed by code
     requirements,  however  figure  1 shows 4 x 8K of buffer space
     (half the virtual address space) and  is  probably  the  worst
     case.   In  addition  most  processes  will  have some private
     buffer space.
        During MOS execution the  processes  are  'swapped  in'  by
     manipulating  the  Memory  Management  Unit  (MMU)  registers.
     Apart from loading these registers to swap in  a  new  process
     the  only  other overhead of the extended memory system is the
     need to disable the write protection on the MOS Kernel when an
     EMT  from a process occurs.  The protection is re-enabled when
     control is returned to the process text.
        The remainder of this note describes in detail the linking,
     loading,   and   runtime   phases.    The  appendices  contain
     documentation on building the extended memory MOS.
     2. Linking on UNIX
        The standard UNIX linker (ld) is only capable of building a
     single  64K  byte  module.   Using a version of ld from MITRE,
     which had some modifications for building an overlay,  ld  was
     extended.   From the description above it can be seen that the
     MOS Kernel is in the address space of each process,  but  that
     the  process  (text  and  data)  address  spaces  are mutually
     exclusive.  This arrangement is most like an  overlay  system,
     with  the  MOS  Kernel  as  the root.  The program, lk (lk for
     link), was used to build the root and  link  in  each  overlay
     separately.   Obviously  each overlay should be able to access
     the root, but not vice versa.
        The lk program uses two symbol tables, one  for  the  root,
     and  one  for  the  current  overlay.  The overlay symbols are
     purged when the overlay definition is complete and the overlay
     has been linked.  A mechanism was required for MOS to identify
     overlay code at runtime for swapping, as well as for  them  to
                                 - 3 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     be  easily  indicated  from  the  C  configuration  file.  The
     mechanism chosen is to label each overlay by a tag  symbol  at
     link  time.  The symbol is given a unique value by the linker.
     The symbol itself can be used in C programs, and later in DDT,
     to identify a particular overlay (process).
     An example command sequence to lk could be:
          lk mos.o config.o \
          { _tag1 -n -b 0140000 -e _ent1 proc1.o lib.a }
          { ... } defines an overlay
          _tag1 is the tag symbol, the leading underscore is
           required where the symbol is referenced in C code
          -b 0140000 gives the base address at which the overlay
           code is to linked (page 6)
          -e _ent1 defines the entry address for this overlay
        The -b  flag is used to relocate the overlay  code  to  the
     top  end of the address space.  The -n flag causes the data to
     be relocated to the next page boundary (if possible).  At  UCL
     we  use a modified version of cc, called mcc, to build the MOS
     load file.  Mcc will expand the "{ tagn" to become  "{ tagn" -
     n -b 014000"   and  the  "}"  become  "-l }",  thus  providing
        The  object  code  output  is  organised  as  a  number  of
     subfiles,  one  for the root, and one for each overlay.  These
     subfiles are packed into a single output file using the ar (V)
     format.   Size (I)  and  nm (I)  have  been modified to accept
     files in ar format and operate on the subfiles.
        From the runtime map, fig. 1, it can be seen that DDT is in
     the  Kernel  address space, but at the opposite end to that of
     MOS.  To achieve this lk recognises the tag "ddt" and marks it
     as being in the root (by the magic word) but treats the module
     as an overlay for linking purposes.
        The normal a.out (V) header has been modified by using  the
     unused  word to include the tag symbol value and the base page
     into which the overlay should be swapped.  The format is now:
                                 - 4 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     typedef struct filhdr { /* a.out format header */
             int     magicw;
     #define VMAGIC  0405
     #define FMAGIC  0407
     #define NMAGIC  0410
     #define IMAGIC  0411
     #define ROOTMAGIC 0515 /* root file in overlay system */
     #define OVNMAGIC  0525 /* overlay with separate I and D */
     #define OVFMAGIC  0535 /* overlay with contiguous I and D */
             int     tsize;
             int     dsize;
             int     bsize;
             int     ssize;
             int     entrypt;
             char    tag, page;      /* for MOS overlays */
             int     relflg;
     } FILHDR;
     3. Loading
        Once the complete MOS system has been linked and  is  ready
     in  the  ar  format  file; it has to be loaded into the LSI or
     PDP-11.  To manage the MMU and set up the overlays  ready  for
     swapping  a special loader is used in the target computer.  At
     UCL we load this as an  ordinary  program  using  a  down-line
     loader.   The  program  is  then  automatically started by the
     primary bootstrap and continues as the (secondary) bootstrap.
        Each subfile is passed to the secondary  bootstrap  in  two
     parts,  first  the  16 byte a.out header, followed by the text
     and data.  The a.out header enables the bootstrap  to  see  if
     the file contains root code or is an overlay.
        If the subfile is a root file (magic word  =  0515)  it  is
     loaded  into the 1st 6 physical pages and the MMU is not used.
     Any symbols associated with the root are placed at the end  of
     the last physical page (page 30), the amount of space left for
     the root symbols is an assembly constant  shared  between  the
     virtual  bootstrap, virtual MOS and DDT.  The page byte in the
     a.out header allows loading to begin  on  any  page  boundary.
     Note that DDT is loaded into page 6 using this mechanism.  The
     secondary boot operates from the very top of physical  page  6
     so that DDT should not overwrite this.
        If the subfile is an overlay it is  loaded  above  physical
     location  0160000.   The text and data are loaded contiguously
     in 1K byte blocks from UNIX.  When the text and data have been
     loaded  (the a.out header contains the size, this is used as a
     check against the amount received) the physical address of the
                                 - 5 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     top of the 8K process page boundary is calculated.  The layout
     of a process is shown in Fig. 2.
          bytes                         bytes
        !   H    !                !      .        !            |
        !   E    !                !   D  .        !            |
        !   A    !      TEXT      !   A  .        !            |
        !   D    !                !   T  .        !            |
        !   E    !                !   A  .        !            |
        !   R    !                !      .        !            |
             ! denotes a 64 byte block boundary
                      Figure 2. Overlay load map.
        The a.out header is copied into the first  64  byte  block,
     this  block  is  used as a control block for the overlay.  The
     format of this control block is:
     typedef struct { /* overlay header block structure */
       int magic;      /* magic word */
       int tsize;
       int dsize;
       int bsize;
       int ssize;
       int entry; /* entry address for process */
       char tag;
       char page; /* same as a.out header up to here */
       int used;  /* indicates overlay already used */
       int memlo; /* address of first free loc in o/v */
       int next;  /* points to next overlay header */
       int par[16]; /* MMU register contents to */
       int pdr[16]; /* 'swap' this process in */
        The base of the 8K page is, of course, the first data byte.
     This  means  there  is  a  hole  in  the process address space
     between the end of the text and the first word  of  the  data.
     There  is  no  physical  memory assigned to this area.  If the
     subfile has any symbols these are loaded  above  the  extended
     data  page.   When  the data and text have been loaded the bss
     area is set to zero, this only occurs at load time.  When  the
     symbols have been loaded the virtual loader calculates the PAR
     and PDR register contents for  the  process  by  assuming  all
     unloaded  pages  are  allocated to the low physical memory and
     are full (all 8K in use).  The loaded pages are given the  PAR
     and  PDR  values  needed to 'swap' in this process.  The first
     location in the process  private  buffer  pool  is  calculated
     (size  of  data  +  bss  +  2 + 0160000)  and the PAR contents
                                 - 6 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     needed to access the next process control block.  In this  way
     the  first  overlay  control  block  is  always at 0160000 and
     subsequent overlays can be found  by  using  the  chain.   The
     virtual  loader  (and  MOS)  do all address calculation in PAR
     content values.
        Thus the loader sets up the process, and the necessary  MMU
     register values, to enable MOS to use the overlay easily.
     4. MOS Initialisation
        Apart from some modification to the  synchronous  I/O  code
     the changes to MOS were in the once only system initialisation
        The MMU is enabled as soon as MOS  loads  the  kernel  mode
     registers  to  provide  the same mapping as though the MMU was
     disabled. A window page is used to map into  the  overlays  by
     loading  a single PAR register with the values provided by the
     loader.  Any spare physical memory between  the  last  overlay
     and  the  MOS  Kernel  symbols  is  divided into 8K pieces and
     initialised with a control block.  These may be used when  two
     or more processes share the same text.
        The control block used for each overlay means there was  no
     need  to increase the size of the Process Control Table (PCT),
     this was convenient as the size is currently 32 bytes.
     5. MOS Runtime
        As pointed out in [1] it is necessary  to  use  the  shared
     buffer  area  for  all I/O and especially IORBs.  This was the
     only change that needs to be made to MOS processes.   However,
     some processes share routines and data space, these have to be
     loaded in the Kernel.  All the facilities described in [2] are
        The synchronous I/O routines (sin, sout,  bin,  bout)  will
     copy  data  between  the  process  data  page  and  the shared
     buffers, if necessary.
     6. DDT
        The debugging program DDT is always loaded in the  extended
     MOS.   This has the same commands and features as the ordinary
     DDT.  In addition the  following  command  will  'swap  in'  a
     process, and its symbol table.
                                 - 7 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
          <tag>$l - load an overlay
          $l      - load the 'normal' address space
        The <tag> should be a tag symbol used in  linking.   If  no
     tag  is  given;  DDT  itself,  and the I/O page are mapped in.
     Processes can be swapped randomly in DDT, this does not affect
     the running of the system.
        The only (apparent) facility not readily converted  is  the
     use  of  single  step  over RTT and RTI instructions where the
     address mode is changed by that instruction.
        Note, that when DDT is entered via a break  (breakpoint  or
     single  step)  PS and SP contain the values in use at the time
     of the break, thus are not necessarily the SP of the  mode  in
     which  DDT  is  running.   Also when the break occured in user
     mode the address space contains the user process, not the  I/O
                                 - 8 -               [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
      1. Wiseman, S.R., Davies, B.H., Memory Management Extensions
         to the SRI Micro Operating System for PDP- 11/23/34/40,
         IEN 136, May 1980
      2. Cole & Treadwell, MOS User Guide, 2nd Ed.,
         Indra Note 1042
                                 - 9 -               [Robert Cole]

        This appendix contains an example of building a virtual MOS
     system   using   the   normal   mechanisms,  plus  the  system
     documentation for mcc and lk,
                             - Appendix 2 -           [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
                   Example of Building a vMOS System
        The vMOS system is defined in a cnf file in the same way as
     an  ordinary  system.   The difference is that the lk 'tag' is
     used instead of the entry address.  In our example a TCP  test
     system is built:
     extern   monitor, control, vcs, tcp, inet, monsl;
     PCTE pcts[]     {
       setpcte("opcon", &control, &dt1i, &dt1o, 300, 0, 0),
       setpcte("tcp", &tcp, &cty1, 0, 200, 0, 0),
       setpcte("internet", &inet, 0, 0, 300, 0, 0),
       setpcte("cstest", &vcs, &cty2, 0, 200, 0, 0),
       setpcte("monitor",&monitor, 0, 0, 200, 0, 0),
       setpcte("monslave", &monsl, 0, 0, 200, 0, 0),
     Note that there is  no  mechanism  for  automatically  loading
     complete  processes  so  the Internet and monitoring processes
     are explicitly named.  For this  reason  there  is  a  special
     version  of  the  TCP  process  that does not attempt to spawn
     those processes.
        The commands to mcc must indicate all of the procceses.  In
     this  example  a  large  number  of routines are loaded in the
     kernel to enable them to be shared amongst processes.  In fact
     this  is  to  do  with  the  monitoring and all that should be
     shared is the name of the routine.
     mcc -o vtcptst tcpcnf.c vtcppnt.c monpid.c \
     inprnt.c inaddr.c vprintf.o -l1 \
     { control -e opcon opcmds.c -l1 } \
     { vcs -e cstest cstest.o } \
     { monitor -e vmontr -lv } \
     { monsl -e monslave -lv } \
     { tcp -e vtcpm -lv } \
     { inet -e inetm -lv -l1 }
        To show how mcc expands this  command  the  actual  command
     line  to  lk  is  shown  below.  Note that new-lines have been
     inserted to improve the clarity of the example.
                             - Appendix 3 -           [Robert Cole]

Extended Memory MOS for                                IEN 198
     a UNIX Development Host                        INDRA Note 1152
     lk -X /ucl/mos/lib/vmos.o -o vtcptst tcpcnf.o vtcppnt.o
     monpid.o inprnt.o inaddr.o vprintf.o -l1
     { _control -b 0140000 -n -e _opcon opcmds.o -l1 -l }
     { _vcs -b 0140000 -n -e _cstest cstest.o -l }
     { _monitor -b 0140000 -n -e _vmontr -lv -l }
     { _monsl -b 0140000 -n -e _monslave -lv -l }
     { _tcp -b 0140000 -n -e _vtcpm -lv -l }
     { _inet -b 0140000 -n -e _inetm -lv -l1 -l }
     { ddt -b 0140000 -s /ucl/mos/lib/vddt.o }
        When converting from an  ordinary  MOS  system  to  a  vMOS
     system the 2 major problems are:
       1. Different processes that share  memory  or  routines,  or
          even addresses.
       2. Searching libraries so that only  the  required  routines
          are  built  into  an  overlay,  and  not  included in the
                             - Appendix 4 -           [Robert Cole]

     LK(I)                 15th. September 1981                 LK(I)
               lk  -  link editor for Extended Memory MOS
               lk [ { tag ] -sulxnebo name ...  [ } ]
               Lk is a modification of ld(I)  that  can  build  an  overlay
               system  of  the type used in the Extended Memory MOS system.
               All the features of ld are supported.  If  no  overlays  are
               defined  lk  behaves  exactly  the  same  as  ld,  only less
               Overlays are defined  by  enclosing  switches  and  filename
               arguments  between curly brackets "{}".  Each overlay has to
               have a name, thus the first argument after every open  curly
               bracket  is  taken  as  the symbol naming that overlay.  The
               symbol is known as the overlay tag.  Each  tag  is  given  a
               unique value by lk.  The overlay definition syntax is:
                                 { tag -sulxneb name... }
               Any arguments not bracketed are used  to  define  the  root.
               Root  arguments  may  appear in any position between overlay
               definitions.  All symbols defined in the root arguments  are
               available  to  all  overlays.  Symbols defined in an overlay
               are purged when processing of the overlay is complete.  Thus
               it is not possible to have references between overlays.
               Lk produces output in  ar(V)  format.   The  root  and  each
               overlay  are  separate subfiles in the output.  Each subfile
               is a complete a.out(V) format file with symbols if required.
               The default output name is "a.out".
               Where symbols are used in the argument list (in -e, -u,  and
               as  the  overlay tag) they must be preceded by an underscore
               if they are also defined in C programs.
               If any argument is a library, it is searched exactly once at
               the  point  it  is  encountered  in the argument list.  Only
               those routines defining an unresolved external reference are
               loaded.   If  a  routine  from  a library references another
               routine in the library, the referenced routine  must  appear
               after  the  referencing  routine  in  the library.  Thus the
               order of programs within libraries is important.
               Lk understands several  flag  arguments  which  are  written
               preceded by a '-'.  Except for -l, they should appear before
               the file names.
                                        - 1 -

     LK(I)                 15th. September 1981                 LK(I)
               The options suxXneb have a local effect when used within  an
               overlay definition.  If used outside an overlay their effect
               is global, but can be overridden by other flags or values.
               -s      'squash' the output,  that  is,  remove  the  symbol
                   table  and relocation bits to save space (but impair the
                   usefulness of the debugger).  This information can  also
                   be removed by strip.
               -e      The next argument is taken as a symbol defining  the
                   entry address of the overlay or object output.
               -u      take the following argument as a symbol and enter it
                   as  undefined  in  the symbol table.  This is useful for
                   loading wholly  from  a  library,  since  initially  the
                   symbol  table  is  empty  and an unresolved reference is
                   needed to force the loading of the first routine.
               -l      This option is an abbreviation for a  library  name.
                   -l  alone  stands  for  'liba.a',  which is the standard
                   system library for MOS systems.  -lx stands for 'libx.a'
                   where  x  is  any character.  A library is searched when
                   its name is encountered, so the placement  of  a  -l  is
                   significant.   The  MOS  libraries  are  kept in the MOS
                   system directory and lk searches this directory for  the
                   libraries defined by the -l switch.
               -x      do not preserve local (non-.globl)  symbols  in  the
                   output  symbol table; only enter external symbols.  This
                   option saves some space in the output file.
               -X      Save local symbols  except  for  those  whose  names
                   begin  with  'L'.  This option is used by mcc to discard
                   internally  generated  labels  while  retaining  symbols
                   local to routines.
               -n      Arrange that when the output file is  executed,  the
                   text  portion  will  be  read-only  and shared among all
                   users executing the file.  This involves moving the data
                   areas  up  the  the  first  possible  4K  word  boundary
                   following the end of the text.  In an overlay  this  has
                   the  effect  of  relocating  the data to the next memory
               -o      The next argument is taken the name  of  the  output
                   file, this overrides the a.out default.
               -b      The next argument is taken as a  number  giving  the
                   base address at which linking is to begin.  This is used
                   to relocate overlays above the root.   An  octal  number
                                        - 2 -

     LK(I)                 15th. September 1981                 LK(I)
                   may be given by using a leading zero (0).
               lib?.a   libraries
               liba.a   MOS system library
               lib1.a   TCP/IP/OPCON library
               lib2.a   X25 library
               libv.a   virtual MOS library
               a.out    output file
          SEE ALSO
               as(I), ld(I), ar(I)
               MITRE, then Robert Cole at UCL.
                                        - 3 -

     MCC(I)                15th. September 1981                MCC(I)
               mcc - C compiler and MOS system builder
               mcc [{ tag] [-c] [-p] [-O] [-F] [-S] [-P] file ...  [}]
               Mcc is the UNIX C compiler which is used to  produce  a  MOS
               system  load file.  Mcc is very similar to cc(I) except that
               the command line to the loader (ld(I) or lk(I)) causes a MOS
               kernel  to  be  included  and  MOS  system  libraries  to be
               Arguments whose names end with '.c' are taken to be C source
               programs; they are compiled, and each object program is left
               on the file whose name is  that  of  the  source  with  '.o'
               substituted  for  '.c'.   The '.o' file is normally deleted,
               however, if a single C program is compiled and loaded all at
               one go.
               If curly brackets are used in the argument list an  extended
               memory  system (vMOS) is assumed.  For building vMOS systems
               mcc will call lk rather than ld for linking.  Some expansion
               is done by mcc for certain arguments in a vMOS system,
                          "{ tag" becomes "{ _tag -b 0140000 -n"
                                    "}" becomes "-l }"
               Arguments  following  the  -e  switch  have  an   underscore
               prepended  to  convert  C  symbols  to  overlay symbols, the
               overlay tag is similarly treated.   The  virtual  kernel  is
               loaded, and the DDT segment added to the lk command.
               Mcc will compare the modify dates on all source files  ('.s'
               or  '.c') with any object files ('.o') of the same name.  If
               the object file has a later modify date then the source file
               is not compiled.
               The following flags are interpreted by mcc.   See  ld(I)  or
               lk(I) for load-time flags.
                -c      Suppress the loading phase of the compilation,  and
                     force  an  object file to be produced even if only one
                     program is compiled.
                -p      Causes a production version of the MOS kernel to be
                     loaded  (mosp.o).  The  default  MOS  kernel is mosr.o
                     which includes DDT.
                -O      Invoke an object-code optimizer.
                                        - 1 -

     MCC(I)                15th. September 1981                MCC(I)
                -F      Force the compilation of a  source  file,  even  if
                     there is a later object code file available.
                -S       Compile  the  named  C  programs,  and  leave  the
                     assembler-language   output   on  corresponding  files
                     suffixed '.s'.
                -P      Run only the macro  preprocessor  on  the  named  C
                     programs,  and leave the output on corresponding files
                     suffixed '.i'.
               Other  arguments  are  taken  to  be  either   loader   flag
               arguments,   or   C-compatible  object  programs,  typically
               produced by an earlier cc or mcc run, or  perhaps  libraries
               of C-compatible routines.  These programs, together with the
               results of any compilations specified, are  loaded  (in  the
               order  given)  to  produce  a  loadable MOS system with name
               file.c                          input file
               file.o                          object file
               a.out                           MOS system output
               /tmp/ctm?                       temporary
               /lib/c[01]                      compiler
               /ucl/mos/lib/mos[pr].o          MOS kernels
               /ucl/mos/lib/liba.a             MOS system library
               /ucl/mos/lib/lib[12v].a         MOS utility libraries
          SEE ALSO
               ''Programming in C- a tutorial,'' C Reference Manual,
               ld(I), lk(I), load(I)
               The diagnostics produced by C  itself  are  intended  to  be
               self-explanatory.   Occasional  messages  may be produced by
               the assembler or loader.  Of these, the most mystifying  are
               from  the  assembler,  in  particular  ''m,''  which means a
               multiply-defined external symbol (function or data).
               UCL - Robert Cole
                                        - 2 -