The  EXEC  module  (my  designation)  follows the FILSER routines
    which were discussed in the last article.  This  module  contains  the
    executive program and the remainder of the supervisor calls.

         The  first  routine  in EXEC is EXIT.  When a job is allocated to
    the system, the JOBS program sets EXIT as the first  program  the  job
    will execute.  EXIT first enables interrupts (in case the user program
    left  the  processor  LOCKed) and then determines if the EXIT call was
    forced by a CTRLC call.  If a Control  C  is  waiting  (J.CCC  set  in
    JOBSTS),  "^C"  is  sent  to the job's terminal and the JOBCMZ word is
    cleared, which aborts any remaining commands in a command  file.   All
    flags except J.ALC are cleared from the JOBSTS word and the J.MON flag
    is set.

         The  DDBCHN  is  then scanned to determine if the job has any I/O
    queued.  If it does, the remainder of the job's CPU time  is  used  to
    process  it.  (Queued interrupt driven I/O is not supported in the 4.2
    release of the monitor).

         The error control intercept (JOBERC) and  the  breakpoint  vector
    address  (JOBBPT)  are  both  cleared  and  the job's stack pointer is
    restored to the top of  the  job's  stack.   If  the  job  has  memory
    assigned  (the  J.NUL bit is not set in the JOBTYP word) the DEVTBL is
    scanned and any devices assigned to the job  are  deassigned  and  the
    following memory tests are performed.

         If  the  job  has  a  new memory allocation the first word of the
    job's memory will be cleared, insuring the memory  partition  contains
    no garbage.  The partition and any memory modules in it are tested for
    address errors. The system error message, "[MEMORY MAP DESTROYED]", is
    returned if the partition's base address or a module's address is odd,
    or the partition's base address or a module's address is above MEMEND.
    If  none of the module flag codes: FIL, FGD, or LOK are set the module
    is deleted.

         The memory calls, GETMEM and CHGMEM will always  return  an  even
    module size and clear the word following the module, but memory module
    errors  can  be  caused  by a program which itself modifies the module
    size word, either intentionally  or  by  accident.   The  location  of
    ascending  modules is determined by adding the module size word to the
    first housekeeping word.  If the contents of this location  are  zero,
    the  end  of  memory  modules is assumed to have been reached.  If the
    address is odd, caused by an odd byte count, or the address is  beyond
    then  end  of  user  memory  (MEMEND),  the  error is reported and the
    contents of the offending address are cleared.

         If a program leaves some garbage modules in  the  partition  (VUE
    used to) which cannot be deleted with DEL, a MEMORY 0 command followed
    by MEMORY XXXXX will restore the partition.

         Normally,  this  type  of memory error should not be fatal to the
    job or the system, but there are two bugs in EXIT which can cause  the
    job  or  the  system  to  crash.  The first is that no test is made to
    determine if a module, either real or erroneous,  extends  beyond  the
    end of the job's partition.  The second is in the method by which EXIT
    clears  the  erroneous address.  The current module's address is saved
    in R3 before the next module's address is calculated.  If  the  module
    creates an error the contents of R3 are cleared, however R3 is not set
    until  after  the  first  module  is  tested.  Therefore, if the first
    module creates an error,  the  contents  of  an  undetermined  R3  are
    cleared.

         If  the job has terminal output in progress, it will loop in EXIT
    until all terminal output has been processed after which the  terminal
    status flags will be reset (restoring normal terminal I/O) and control
    will pass to the executive program.

         The  executive  program  (hereafter  called EXEC) is AMOS command
    level, which upon entry issues the monitor prompt, ".", and calls  KBD
    where  the  job  is  descheduled until terminal input is available, or
    where, as described in the first of these articles, if a command  file
    is  being  processed, the input line buffer is filled from the command
    file data area.  After a command is entered, EXEC resets the job stack
    pointer to the top of the stack and determines  if  the  job  has  any
    memory  allocated.    If  the  job does not have any memory, EXEC will
    allocate to the job all of the available memory in the job's bank.  If
    at least 2000  decimal  bytes  are  not  available,  the  "[NO  MEMORY
    AVAILABLE]" message is issued and EXIT is called.

         A  FSPEC  call  with a null default extension is performed on the
    command line with the job run block (JOBRBK - partial DDB in the  JCB)
    indexed  to  receive  the file specification.  The file name is copied
    into the JOBNAM words, the J.MON bit cleared and the J.LOD bit set  in
    the  JOBSTS  word, and a search for the file is made.  The Alpha Micro
    document, "AMOS USER'S GUIDE" (DWM-00100-35), is somewhat ambiguous on
    what format is allowed for system commands (page  7-3),  however  full
    file specifications are allowed.  The file search order is documented,
    although  not accurately, in Appendix B of that manual, and is briefly
    summarized below.   If  the  Device,  Drive,  Extension,  or  PPN  are
    supplied on the command line, the appropriate search is bypassed.

    DEVICE          EXTENSION        PPN
    ------          ---------        ---
    system memory      PRG           N/A
    user memory        PRG           N/A
    DSK0:              PRG           [1,4]
    DSK0:              CMD           [2,2]
    user               PRG           user
    user               CMD           user
    user               PRG           user library

         If  the  search  failed  up  to  this point, DSK0:MDO.PRG[1,4] is
    loaded which attempts to locate the file in following order:

    DEVICE          EXTENSION        PPN
    ------          ---------        ---
    user               DO            user
    user               DO            user library
    DSK0:              DO            [2,2]

         If the file  is  found  it  is  loaded  into  the  job's  memory,
    providing  enough  memory is available.  If the file is not found, the
    command is echoed to  the  job's  terminal,  bracketed  with  question
    marks.    The  message  "?Insufficient  memory  for  program  load" is
    returned if the job did not have enough memory.

         After the file is loaded, EXEC tests its first word to  determine
    if  the  program  can  be run not logged in.  If the first word of the
    file is non-zero, the JOBUSR word is tested and if it is zero (the job
    is not logged in), the "[LOGIN  PLEASE]"  prompt  is  issued  and  the
    executive program exits.

         The  file's  extension  is  tested  and  if  it is "PRG", program
    execution begins with MOV R3,PC.  Upon  entry  into  the  program  the
    registers contain the following:
    R0 - base address of JCB
    R1 - cleared
    R2 - remainder of input line buffer
    R3 - base address of program
    R4 - cleared
    R5 - cleared

         A  file  with  an  extension  other than "PRG" is assumed to be a
    command file and EXEC moves the file in reverse order to  the  top  of
    the  job's  partition,  sets  the  C.SIL  bit  in the JOBCMS word, and
    branches to the entry point of EXEC.  If the  file  was  loaded  under
    control of MDO, the specified parameters are inserted into the command
    file  and a block move places the command file at the top of the job's
    partition after which MDO EXITs.

         The numeric conversion calls,  DCVT  and  OCVT  (or  HCVT  -  hex
    convert), follow EXEC.  They perform binary to ASCII conversions based
    on table entries, which limit the magnitude of the output.

         Following   the  conversion  routines  is  FSPEC  which  is  well
    documented in the "AMOS MONITOR CALLS MANUAL" (pp  6-8  through  6-9).
    Lower to upper case ASCII conversions are not made in FSPEC, therefore
    whatever  R2  points to (terminal input line buffer or program buffer)
    must be in upper case.

         PFILE follows FSPEC and  performs  in  essentially  the  opposite
    manner  to  FSPEC.   Its output is directed only to the job's terminal
    (via a TTYL) and PPN output is  always  in  octal  reqardless  of  the
    setting of the J.HEX flag in the JOBSTS word.

         The  JOBIDX,  JOBGET,  and  JOBSET require more words to describe
    than the amount of code they occupy in the monitor.  They are all SVCB
    calls and require a considerable amount of time to decode in the  SVCB
    processing  module.    If  speed  of  execution  for  a  program  is a
    consideration the following macro definition will  mimic  these  calls
    saving over sixty instructions to be executed:

    J.IDX = -1                                 ; JOBIDX control flag
    J.GET =  0                                 ; JOBGET control flag
    J.SET =  1                                 ; JOBSET control flag

    DEFINE  JCB     TAG,ITEM,CTRL
            PUSH    #ITEM                      ; load JCB index
            ADD     @#JOBCUR,@SP               ; build job table entry
            IF      LT,CTRL,  POP TAG          ; JOBIDX
            IF      EQ,CTRL,  MOV @(SP)+,TAG   ; JOBGET
            IF      GT,CTRL,  MOV TAG,@(SP)+   ; JOBSET
    ENDM

    ;       JOBIDX  R0,JOBTRM                  ; is duplicated by
            JCB     R0,JOBTRM,J.IDX
    ;       JOBGET  R0,JOBTRM                  ; is duplicated by
            JCB     R0,JOBTRM,J.GET
    ;       JOBSET  R0,JOBTRM                  ; is duplicated by
            JCB     R0,JOBTRM,J.SET

         The object code resulting from this macro will use between 62 and
    77  machine  cycles,  while  just the SVCB instruction and the ensuing
    RSVC instruction alone  consume  135  machine  cycles  (which  doesn't
    include any of the decoding timing).

         The  three  calls  USRBAS,  USREND, and USRFRE follow next in the
    monitor.  They function as described in the AMOS MONITOR CALLS MANUAL.
         The CTRLC call was briefly described in the previous  article  on
    TRMSER.    It  tests  the  J.CCC bit in the JOBSTS word and, if set, a
    Control C was entered at the job's terminal (or by the  KILL  program)
    and the argument address of CTRLC is placed in the saved PC.

         The  PRNAM  call sends its output to the job's terminal via a TTY
    call as does PRPPN.  Like PFILE,  PRPPN  displays  the  PPN  in  octal
    regardless of the setting of the J.HEX flag in the JOBSTS word.

         The  terminal  input line processing calls BYP, ALF, NUM, TRM and
    LIN occupy the next section of the monitor and are unremarkable except
    to note that ALF tests for upper case alphabetic characters only.

         The FILNAM call  functions  exactly  as  described  in  the  AMOS
    MONITOR CALLS MANUAL.

         The  GTOCT call follows FILNAM and is really two calls; GTOCT and
    GTHEX.  The GTHEX code is used if the J.HEX bit is set in  the  JOBSTS
    word.  If  the  leading  character  is  alpha,  it does not need to be
    preceded by zero.  If the input is greater  than  177777  octal  (FFFF
    hex),  causing  an  error  to  be  reported  (N  flag set), the result
    contained in R1 will be meaningless.

         GTDEC, unlike GTOCT will stop processing the input  line  if  the
    next character will cause the result to be greater the 65,535.

         The  GTPPN  call  will  always  process the input PPN on an octal
    basis regardless of the setting of the J.HEX bit.

         The final two calls in this section of the monitor are  the  PACK
    and  UNPACK calls for which no description will be attempted except to
    note that UNPACK uses a small (two word) table for unpacking.

         The next section of the monitor is DSKSER which is  mentioned  by
    Alpha  Micro only briefly in FILSER.  DSKSER is the generalized device
    driver for file structured devices  such  as  floppy  disks  and  hard
    disks.    It  simplifies  the actual code needed for a disk driver and
    allows the system to access several devices without a great amount  of
    code.    Like  other device drivers it has a comminucation area at its
    beginning which was defined in the last article.  The  attribute  word
    of  DSKSER  is  zero,  but all functions are supported, except ASSIGN.
    File structured devices cannot be assigned to one job, but for obvious
    reasons, two jobs cannot be given access to the same  file  structured
    device simultaneously.  The controlling job cannot lock other jobs out
    by  disabling  interrupts  because  other I/O devices might lose data.
    The  solution  is  to  increase   the   controlling   job's   priority
    considerably  until  it  is  done  with  the disk.  In DSKSER, this is
    accomplished by setting the job's priority  counter  to  177777  octal
    (about 18 minutes).

         Before  discussing  DSKSER's  routines,  the  structure of a disk
    driver communication area will be  described  as  well  as  the  three
    support routines used by DSKSER.

         Disk  drivers,  like  non-file  structured  device drivers have a
    communication area at their beginning, which contains some differences
    from other drivers.  The 200DVR.DVR disk driver communication area  is
    described below as an example:

    WORD 1    - logical record size
    WORD 2    - driver attributes
    WORD 3    - driver entry address offset
    WORD 4    - physical sector size
    WORD 5    - physical sectors per logical record
    WORD 6    - maximum record number
    WORD 7-16 - not used
    WORD 17   - maximum record number
    WORD 18   - directory entries per record
    WORD 19   - bitmap size

    The remaining five words are specific to the physical drive type.

         DSKSER  includes  three support routines for locating devices and
    files.  The first of these is a routine (DEVTST) to determine  if  the
    device  specified  in the DDB exists and is mounted.  If the device is
    not specified in the DDB, DEVTST will pick up the job's default device
    and drive.  If the device is specified, but the drive is not (DDB+23 =
    377), device 0 is used.  The appropriate error code is set in DDB+1 if
    the device is not found in the DEVTBL or the device is not mounted.

         The second routine (FILTST) is used to locate the  UFD  entry  of
    the  file  specified  in  the  DDB.  The calling sequence to FILTST is
    somewhat different than a normal subroutine call in that control flags
    are set to limit the actions FILTST can perform.  The sequence is:

    CALL    R5,FILTST               ; R5 is used as the linkage register
    WORD    FLAGS                   ; control flags

    Control flags:

    Bit 0 - locate file
    Bit 1 - return error if file already exists
    Bit 2 - test for programmer number match
    Bit 3 - lock directory (DSKDRL)

    Various combinations of flags can be used.  When FILTST returns, R5 is
    incremented past the control flags.

         The third routine (MFDTST) reads the  MFD  (record  one)  of  the
    device  to  locate  the specified UFD.  If the PPN is not specified in
    the DDB, JOBUSR is used to locate the UFD link.

         The following is a discussion of the DSKSER  routines.   Keep  in
    mind  that  these  routines  are called by FILSER and are not directly
    entered with an SVCB 0.  FILSER can call  any  devi
ce  driver  on  the
    system, of which DSKSER is only one.

         The  first  routine in DSKSER is the physical READ/WRITE routine.
    This is the only section of DSKSER which actually makes calls  to  the
    device driver.  A call to DEVTST insures that the device exists and is
    mounted.  The  specified record number (DDB+10) is tested to determine
    if it is within the range of the device.  If the  READ/WRITE  call  is
    valid,  the  device  is  locked  to  this  job  by resetting the job's
    priority counter  as  described  above.   The  DDB  record  number  is
    multiplied  by  the number of sectors per logical block for the device
    to obtain the physical sector for  the  device  and  the  transfer  is
    initiated.    Upon  return  from  the device driver the job's priority
    counter is reset to 1 and, if no other jobs are  currently  scheduled,
    the  routine  returns.  If other jobs are scheduled, the job is put to
    SLEEP for one clock tick (presumably to give other jobs CPU time).

         The OPEN routine handles all  four  OPEN  calls:  LOOKUP,  OPENI,
    OPENO,  and OPENR.  The OPENO call insures that the user has access to
    the PPN and that the file does not already exist with a call to FILTST
    and then allocates a disk record for file data.  The  physical  record
    number  is returned in DDB+10 and DDB+42.  The buffer index (DDB+6) is
    set to two.  The OPENI and OPENR calls  locate  the  file  and  if  it
    exists  insure  that it is the same type as specified in the open code
    of the DDB (DDB+35).  If the file type matches, the number of  records
    in the file is placed in DDB+36, the byte count of the last record (or
    -1  if a random file) is set in DDB+40, and the first record number is
    set in DDB+42 and DDB+10. The LOOKUP call does not distinguish between
    random and sequential files.

         The CLOSE call locks the disk directory and then locates the  UFD
    of  the  PPN  specified in DDB+32 with an MFDTST call.  If a directory
    for the PPN is not allocated, CLOSE will  allocate  a  record.   If  a
    directory for the PPN already exists, CLOSE locates the first empty or
    deleted  entry,  or if the record is full, allocates another directory
    record.  Once an empty directory entry is found, the file name and the
    file directory parameters are inserted into the directory, the  bitmap
    is  updated,  and  the  directory is unlocked. If it was neccessary to
    allocate a directory record,  the  unused  words  in  the  record  are
    cleared to nulls to insure there are no spurious entries.

         The  INPUT  routine follows CLOSE.  For files open for sequential
    input, INPUT executes a READ based on the  record  number  in  DDB+10.
    The link to the next record is updated in DDB+10 and the buffer index,
    DDB+6,  is  set  to  two, bypassing the link word.  For files open for
    random processing, INPUT uses the data in DDB+10 as an offset from the
    base of the file contained in DDB+42.  DDB+10 is not updated.

         The DSKSER OUTPUT routine for files open  for  sequential  output
    can  be  called on two levels (DDB+22 - call level).  A level one call
    is made with a normal user program OUPUT call  which  first  allocates
    another disk record for the next call, inserts that record number link
    into  the  first  word  of  the DDB buffer, writes the current record,
    increments the record count (DDB+36), resets the buffer index to  two,
    and  sets  the next record number in DDB+10.  A level two call is made
    through a FILSER CLOSE call, which in turn  calls  the  FILSER  OUTPUT
    routine  to write the last record. This call does not allocate another
    record, instead it determines the amount data in the  DDB  buffer  and
    fills out to the record size with nulls before writing the record.

         The  OUTPUT  routine for files open for random processing insures
    that the user has access to the PPN with a FILTST call and then writes
    to the record using the file base offset in DDB+10 added to  the  file
    record base in DDB+42 as the current record number.

         The  DELETE  routine locks the directory, insuring the user's PPN
    grants access to the file, sets the first word of the file name in the
    directory entry to -1 and then deallocates each record  the  file  had
    used from the bitmap.

         The  RENAME  routine also locks the directory, insures the user's
    PPN allows access to the directory, determines that a file of the same
    name does not already exist and then enters the new name, contained in
    the three words following the DDB, into the directory in place of  the
    previous name.

         The  three  support  routines for DSKSER, described above, follow
    the above routines in the monitor.

         The FILSER SPECL routines are SVCB 0,  function  code  14  octal,
    calls:  the  bitmap  service  calls  DSKDRL,  DSKDRU,  DSKALC, DSKDEA,
    DSKBMR, DSKBMW, and DSKCTG.  They reside in the monitor directly after
    the above described DSKSER routines.  These calls are fully  described
    in the AMOS MONITOR CALLS MANUAL in the section entitled "DISK SERVICE
    MONITOR  CALLS"  (pp  6-17  through 6-21) and the reader is advised to
    refer to that document for detailed information.

         Directly following these seven calls is a bitmap service routine.
    The function of this routine is to  locate  the  device's  bitmap  (if
    any), rewrite it if neccessary, and recompute the hash total to insure
    the  current  bitmap is correct.  If the bitmap is currently locked by
    some other job, this routine will stall until the bitmap is free.   If
    the bitmap hash total is not correct, the drive is apparantly disabled
    by  setting  the drive number contained in the bitmap's partial DDB to
    177.

         Following this routine is  the  supervisor  call  HTIM  which  is
    called by 200DVR.DVR if PERSCI drives are being used.  HTIM copies the
    HLDTIM argument into HLDTIM+2 and inserts a clock tick counter routine
    into  the  CLKQUE  which will decrement the HLDTIM+2 argument until it
    reaches zero.  Upon reaching zero, the routine sends  the  command  to
    unload  the  heads of the disk drive and then deschedules itself.  The
    routine will not be scheduled again if it is already running.

         The next area of the system monitor is a 2000 (decimal) byte area
    reserved for the system disk driver.  MONGEN.PRG  inserts  the  driver
    routine  here  and updates the MEMBAS word in the system communication
    area to reflect the end of the driver.  Describing the functioning  of
    a  disk  driver  is  beyond  the  scope  of this article.  However, in
    passing, it should be noted that disk drivers  maintain  data  storage
    areas within their own code.

         The  last  section  of  the monitor is INITIA, the initialization
    program.  INITIA is not  actually  part  of  the  monitor,  it  merely
    defines the initial system parameters and starts the first job running
    the  SYSTEM.INI  command  file;  it  is  eventually  overwritten as it
    resides above the base of system memory.

         As described in the first  article,  after  one  of  the  various
    monitor  loaders, the controller board's PROM routine, MONTST, WNGLOD,
    HWKLOD, etc., load the system, interrupts are disabled and a CLR PC is
    executed which sets PC to absolute memory location  0.  This  location
    initially  contains  a  JMP  instruction  to  INITIA.  INITIA branches
    around its own stack and starts a memory test to  determine  how  much
    memory  the  system  has  available  in BANK 0, starting at the end of
    INITIA and testing in 1K increments.  When the end of memory is found,
    it is set into MEMEND.  JOBTBL and JOBCUR  both  get  the  address  of
    MEMBAS, JOBESZ is defined (currently 292 decimal bytes), and the first
    JCB entry is cleared.  MEMBAS is reset to the end of this first JOBTBL
    entry.

         An  8K  partition  is  then  set  up  at  the end of memory which
    contains a temporary terminal line table for a pseudo terminal with  a
    pseudo  interface  driver.  This terminal is attached to the first job
    and allows it to communicate until the first terminal is  defined.   A
    temporary  device  table  (DEVTBL)  entry  is  also  allocated  in the
    partition for DSK0: and has no bitmap.  The various  JCB  entries  are
    then  inserted  into  the first JOBTBL entry including logging the job
    into [1,4].

         "SYSTEM.INI<CR><LF>" is entered in the command file buffer at the
    top of the partition and the address of EXIT is set on the job's stack
    as the saved PC of the first program the job will  run.   The  job  is
    then  scheduled  for  CPU time with a JRUN, after which INITIA enables
    interrupts and loops, waiting for the first clock interrupt  to  start
    the job with system initialization.