beneath-apple-dos/ch05.txt

208 lines
12 KiB
Plaintext

## CHAPTER 5 - THE STRUCTURE OF DOS
DOS MEMORY USE
DOS is an assembly language program which is loaded into RAM memory when the
user boots his disk. If the diskette booted is a master diskette, the DOS image
is loaded into the last possible part of RAM memory, dependent upon the size of
the actual machine on which it is run. By doing this, DOS fools the active BASIC
into believing that there is actually less RAM memory on the machine than there
is. On a 48K APPLE II with DOS active, for instance, BASIC believes that there
is only about 38K of RAM. DOS does this by adjusting HIMEM after it is loaded to
prevent BASIC from using the memory DOS is occupying. If a slave diskette is
booted, DOS is loaded into whatever RAM it occupied when the slave diskette was
INITialized. If the slave was created on a 16K APPLE, DOS will be loaded in the
6 to 16K range of RAM, even if the machine now has 48K. In this case, the APPLE
will appear, for all intents an purposes, to have only 6K of RAM. If the slave
was created on a 48K system, it will not boot on less than 48K since the RAM DOS
occupied does not exist on a smaller machine.
*** INSERT FIGURE 5.1 ***
A diagram of DOS's memory for a 48K APPLE II is given in Figure 5.1. As can be
seen, there are four major divisions to the memory occupied by DOS. The first
1.75K is used for file buffers. With the default of MAXFILES 3, there are three
file buffers set aside here. Each buffer occupies 595 bytes and corresponds to
one potentially open file. File buffers are also used by DOS to LOAD and SAVE
files, etc. If MAXFILES is changed from 3, the space occupied by the file
buffers also changes. This affects the placement of HIMEM, moving it up or down
with fewer or more buffers respectively.
The 3.5K above the file buffers is occupied by the main DOS routines. It is here
that DOS's executable machine language code begins. The main routines are
responsible for initializing DOS, interfacing to BASIC, interpreting commands,
and managing the file buffers. All disk functions are passed on via subroutine
calls to the file manager.
The file manager, occupying about 4.3K, is a collection of subroutines which
perform almost any function needed to access a disk file. Functions include:
OPEN, CLOSE, READ, WRITE, POSITION, DELETE, CATALOG, LOCK, UNLOCK, RENAME, INIT,
and VERIFY. Although the file manager is a subroutine of DOS it may also be
called by a user written assembly lanaguage program which is not part of DOS.
This interface is generalized through a group of vectors in page 3 of RAM and is
documented in the next chapter.
The last 2.5K of DOS is the Read/Write Track/Sector (RWTS) package. RWTS is the
next step lower in protocol from the file manager - in fact it is called as a
subroutine by the file manager. Where the file manager deals with files, RWTS
deals with tracks and sectors on the diskette. A typical call to RWTS would be
to read track 17 sector 0 or to write 256 bytes of data in memory onto track 5
sector E. An external interface is also provided for access to RWTS from a user
written assembly language program and is described in the next chapter.
THE DOS VECTORS IN PAGE 3
In addition to the approximately 10K of RAM occupied by DOS in high memory, DOS
maintains a group of what are called "vectors" in page 3 of low memory ($300
through $3FF). These vectors allow access to certain places within the DOS
collection of routines via a fixed location ($3D0 for instance). Because DOS may
be loaded in various locations, depending upon the size of the machine and
whether a slave or master diskette is booted, the addresses of the externally
callable subroutines within DOS will change. By putting the addresses of these
routines in a vector at a fixed location, dependencies on DOS's location in
memory are eliminated. The page 3 vector table is also useful in locating
subroutines within DOS which may not be in the same memory location for
different versions of DOS. Locations $300 through $3CF were used by earlier
versions of DOS during the boot process to load the Boot 1 program but are used
by DOS 3.3 as a data buffer and disk code translate table. Presumably, this
change was made to provide more memory for the first bootstrap loader (more on
this later). The vector table itself starts at $3D0.
DOS VECTOR TABLE ($3D0-$3FF)
ADDR USAGE
3D0 A JMP (jump or GOTO) instruction to the DOS warmstart
routine. This routine reenters DOS but does not
discard the current BASIC program and does not reset
MAXFILES or other DOS environmental variables.
3D3 A JMP to the DOS coldstart routine. This routine
reinitializes DOS as if it was rebooted, clearing the
current BASIC file and resetting HIMEM.
3D6 A JMP to the DOS file manager subroutine to allow a
user written assembly language program to call it.
3D9 A JMP to the DOS Read/Write Track/Sector (RWTS)
routine to allow user written assembly language
programs to call it.
3DC A short subroutine which locates the input parameter
list for the file manager to allow a user written
program to set up input parameters before calling the
file manager.
3E3 A short subroutine which locates the input parameter
list for RWTS to allow a user written program to set
up input parameters before calling RWTS.
3EA A JMP to the DOS subroutine which "reconnects" the DOS
intercepts to the keyboard and screen data streams.
3EF A JMP to the routine which will handle a BRK machine
language instruction. This vector is only supported by
the AUTOSTART ROM. Normally the vector contains the
address of the monitor ROM subroutine which displays
the registers.
3F2 LO/HI address of routine which will handle RESET for
the AUTOSTART ROM. Normally the DOS restart address is
stored here but the user may change it if he wishes to
handle RESET himself.
3F4 Power-up byte. Contains a "funny complement" of the
RESET address with a $A5. This scheme is used to
determine if the machine was just powered up or if
RESET was pressed. If a power-up occured, the
AUTOSTART ROM ignores the address at 3F2 (since it has
never been initialized) and attempts to boot a
diskette. To prevent this from happening when you
change $3F2 to handle your own RESETs, EOR (exclusive
OR) the new value at $3F2 with a $A5 and store the
result in the power-up byte.
3F5 A JMP to a machine language routine which is to be
called when the '&' feature is used in APPLESOFT.
3F8 A JMP to a machine language routine which is to be
called when a control-Y is entered from the monitor.
3FB A JMP to a machine language routine which is to be
called when a non-maskable interrupt occurs.
3FE LO/HI address of a routine which is to be called when
a maskable interrupt occurs.
WHAT HAPPENS DURING BOOTING
When an APPLE is powered on its memory is essentially devoid of any programs. In
order to get DOS running, a diskette is "booted". The term "boot" refers to the
process of bootstrap loading DOS into RAM. Bootstrap loading involves a series
of steps which load successively bigger pieces of a program until all of the
program is in memory and is running. In the case of DOS, bootstrapping occurs in
four stages. The location of these stages on the diskette and a memory map are
given in Figure 5.2 and a description of the bootstrap process follows.
*** INSERT FIGURE 5.2 ***
The first boot stage (let's call it Boot 0) is the execution of the ROM on the
disk controller card. When the user types PR#6 or C600G or 6(ctrl)P, for
instance, control is transfered to the disk controller ROM on the card in slot
6. This ROM is a machine language program of about 256 bytes in length. When
executed, it "recalibrates" the disk arm by pulling it back to track 0 (the
"clacketty-clack" noise that is heard) and then reads sector 0 from track 0 into
RAM memory at location $800 (DOS 3.3. Earlier versions used $300). Once this
sector is read, the first stage boot jumps (GOTO's) $800 which is the second
stage boot (Boot 1).
Boot 1, also about 256 bytes long, uses part of the Boot 0 ROM as a subroutine
and, in a loop, reads the next nine sectors on track 0 (sectors 1 through 9)
into RAM. Taken together, these sectors contain the next stage of the bootstrap
process, Boot 2. Boot 2 is loaded in one of two positions in memory, depending
upon whether a slave or a master diskette is being booted. If the diskette is a
slave diskette, Boot 2 will be loaded 9 pages (256 bytes per page) below the end
of the DOS under which the slave was INITed. Thus, if the slave was created on a
32K DOS, Boot 2 will be loaded in the RAM from $7700 to $8000. If a master
diskette is being booted, Boot 2 will be loaded in the same place as for a 16K
slave ($3700 to $4000). In the process of loading Boot 2, Boot 1 is loaded a
second time in the page in memory right below Boot 2 ($3600 for a master
diskette). This is so that, should a new diskette be INITed, a copy of Boot 1
will be available in memory to be written to its track 0 sector 0. When Boot 1
is finished loading Boot 2, it jumps there to begin execution of the next stage
of the bootstrap.
Boot 2 consists of two parts: a loader "main program"; and the RWTS subroutine
package. Up to this point there has been no need to move the disk arm since all
of the necessary sectors have been on track 0. Now, however, more sectors must
be loaded, requiring arm movement to access additional tracks. Since this
complicates the disk access, RWTS is called by the Boot 2 loader to move the arm
and read the sectors it needs to load the last part of the bootstrap, DOS
itself. Boot 2 now locates track 2 sector 4 and reads its contents into RAM just
below the image of Boot 1 (this would be at $3500 for a master diskette). In a
loop, Boot 2 reads 26 more sectors into memory, each one 256 bytes before the
last. The last sector (track 0 sector A) is read into $1B00 for a master
diskette. The 27 sectors which were read are the image of the DOS main routines
and the file manager. With the loading of these routines, all of DOS has been
loaded into memory. At this point, the bootstrap process for a slave diskette is
complete and a jump is taken to the DOS coldstart address. If the diskette is a
master, the image of DOS is only valid if the machine is a 16K APPLE II. If more
memory is present, the DOS image must be relocated into the highest possible RAM
present in the machine. To do this, the master version of Boot 2 jumps to a
special relocation program at $1B03. This relocator is 512 bytes in length and
was automatically loaded as the two lowest pages of the DOS image. (In the case
of a slave diskette, these pages contain binary zeros.) The relocator determines
the size of the machine by systematically storing and loading on high RAM memory
pages until it finds the last valid page. It then moves the DOS image from $1D00
to its final location ($9D00 for 48K) and, using tables built into the program,
it modifies the machine language code so that it will execute properly at its
new home. The relocator then jumps to the high memory copy of DOS and the old
image is forgotten.
The DOS boot is completed by the DOS coldstart routine. This code initializes
DOS, making space for the file buffers, setting HIMEM, building the page 3
vector table, and running the HELLO program.
Previous versions of DOS were somewhat more complicated in the implementation of
the bootstrap. In these versions, Boot 1 was loaded at $300 and it, in turn,
loaded Boot 2 at $3600, as does version 3.3. Unlike 3.3, however, 27 sectors of
DOS were not always loaded. If the diskette was a slave diskette, only 25
sectors were loaded, and, on 13 sector diskettes, this meant the DOS image ended
either with sector 8 or sector A of track 2 depending upon whether the diskette
was a slave or master. In addition, Boot 1 had a different form of
nibbilization (see chapter 3) than any other sector on the diskette, making its
raw appearance in memory at $3600 non-executable.
The various stages of the bootstrap process will be covered again in greater
detail in Chapter 8, DOS PROGRAM LOGIC.
*** INSERT FIGURE 5.3 HERE ***
.nx CH6.1