TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - BOOT/SYS Disassembled
Page Customization
Page Index
BOOT/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 BOOT/SYS Disassembly - Boot Sector and System Data Sector (Model I)
BOOT/SYS is the first file on every NEWDOS/80 v2.0 diskette: the first five sectors of track 0 (one granule), directory entry code 00H. Only its first three sectors hold data. Sector 0 is the boot sector, which the Model I ROM's bootstrap (069FH) reads into 4200H-42FFH and jumps to at 4200H; sector 1 is an identical copy; sector 2 is the system data sector, which holds the PDRIVE table and the SYSTEM options.
The boot sector's only job is to load SYS0/SYS, which starts at track 0, sector 5, right after BOOT/SYS. It reads SYS0/SYS sector by sector into a buffer at 5100H-51FFH and processes it as a load module: a type 01H record is a block of bytes to be stored at its load address, a type 02H record is the transfer address, types 00H and 03H-1FH are skipped, and a type of 20H or more means the file is not a load module (NO SYS). When the transfer address is reached, the byte there must be A5H, which SYS0/SYS has at 4D00H; the boot sector then jumps to the byte after it, 4D01H, the start of SYS0's reset code. A sector that cannot be read in 10 tries gives ERROR. Both messages clear the screen and leave the computer looping until RESET is pressed.
The code uses both Z80 register sets. The main set (Register Pair HL) keeps the pointer into the sector buffer and the load address and count of the current record (Register Pairs DE and BC); the alternate set keeps the track and sector to read next (Register Pair DE') and, during a read, the FDC addresses and the try count. The EXX at 4255H switches to the disk set and the EXX at 42B6H switches back. The routine that fetches a byte (4252H) only increments Register L: when L wraps to 00H the buffer is used up and the next sector is read. This boot module is basically two main routines, and Cliff Ide treated them as such by use of the EXX register swap. In fact, Cliff uses the PUSH command only 3 times in this entire boot routine!
Another thing done here, more out of necessity than anything else, is to use the Model I memory locations for the Floppy Disk Controller (37ECH-37EFH) and the drive select latch (37E1H). The Model I didn't have ports so it couldn't be any other way (thanks to Eric Dittman for pointing this out), but it remains that by doing it this way only 1 opcode is needed to test and manipulate the controller, instead of 2 (for example BIT 1,(HL) on the status register). The first byte stored into the FDC, FEH, is not a 1771 command; as Blair Robbins has pointed out, on a Percom doubler it selects the single density controller.
SYS0/SYS's last load block runs to 51DAH, over the sector buffer at 5100H-51FFH. Running the loader on SYS0/SYS shows that every byte stored into 5100H-51DAH is stored after the buffer byte at that position has already been read, so the overlap does no harm. The stack at 41E0H and the boot code at 4200H-42FFH are not touched, since SYS0/SYS loads nothing between 4080H and 4307H.
The page shows all five sectors. Sector 0 is shown as code at 4200H-42FFH; sectors 1 to 4 are shown at the offsets their bytes have when read into the 4200H buffer (which is how SYS16 and SYS17 address the system data sector: 42A0H, 42F0H and so on).
The Five Sectors
| Sector | Contents |
|---|---|
| 0 | The boot sector (4200H-42FFH): the loader for SYS0/SYS, the messages ERROR and NO SYS, and bytes 02H (directory starting lump) and FDH-FFH (PDRIVE bytes +6, +2 and +7 of drive 0) used as data. |
| 1 | An exact copy of sector 0. FORMAT writes the same image as sectors 0 and 1 (SYS6 6700H). |
| 2 | The system data sector: PDRIVE records for drives 0-9 (bytes 00H-9FH, 16 bytes each), numeric SYSTEM options (A0H-A9H, D0H-D1H), the validity byte A5H (EFH) and the yes/no SYSTEM options (F0H-F1H, F8H-FAH). Read at reset by SYS0, and by SYS16 (PDRIVE), SYS17 (SYSTEM) and SYS6. |
| 3, 4 | E5H in every byte; no data. They make BOOT/SYS one full granule (five sectors). |
Bytes Filled In by FORMAT
FORMAT (SYS6) writes a boot sector image from 64BAH-65B9H with some bytes filled in for the drive being formatted. On this diskette the values are those of drive 0's PDRIVE record (35 tracks, 10 sectors per track, single density, standard interface).
| Address Size | Contents |
|---|---|
| 4202H 1 byte | 11H: the directory's starting lump (DDSL). Stepped over by the CP 11H at 4201H. SYS6 6797H stores it. |
| 4208H 1 byte | FEH: the first byte written to the FDC (Percom single density). SYS6 6784H makes it FFH for a double density drive 0. |
| 4210H 1 byte | 00H: the value written to the FDC sector register, PDRIVE byte +6. SYS6 675FH stores it. |
| 4212H-4213H 2 bytes | 0005H: the first sector (05H) and track (00H) of SYS0/SYS, each raised by 1 when sectors or tracks are numbered from 1 (SYS6 6774H, 676FH). |
| 4261H 1 byte | 0AH: the sectors on one side of a track (SYS6 6791H). |
| 42B0H 1 byte | 0AH: the sectors per track (SYS6 678BH). |
| 42B5H 1 byte | 00H: the first sector number of a track, 01H when sectors are numbered from 1 (SYS6 6778H). |
| 42FDH-42FFH 3 bytes | 00H, 07H, 00H: PDRIVE bytes +6, +2 and +7 of the drive (SYS6 675CH, 67A6H, 6765H). |
Variables
Memory used by the boot sector while it runs (it has no variables inside the sector itself).
| Address Size | Purpose |
|---|---|
| 37E1H 1 byte | Drive select latch: 01H selects drive 0, 09H drive 0 on the second side (bit 3). |
| 37ECH 1 byte | FDC command register (written) and status register (read): bit 7 not ready, 5 record type, 4 record not found, 3 CRC error, 2 lost data, 1 data request, 0 busy. |
| 37EDH 1 byte | FDC track register, set to 0 at 420CH. |
| 37EEH 1 byte | FDC sector register: the PDRIVE drive select byte at 420FH, then the sector to read (426DH). |
| 37EFH 1 byte | FDC data register: the destination track of the Seek (426DH), then each byte read from the diskette. |
| 41D6H-41DFH 10 bytes | The stack (Stack Pointer 41E0H): at most the return address into the loader, Register Pairs DE and BC saved during a read (425DH, 425EH) and the return addresses of 42CEH and 42D7H; at the end 4D01H, the entry of SYS0's reset code, pushed at 424AH. |
| 5100H-51FFH 256 bytes | Sector buffer: the sector of SYS0/SYS being processed. Register Pair HL points into it; 4252H reads the next sector when Register L wraps to 00H. |
| Register | Use |
|---|---|
| HL | Main set: the buffer pointer (51FFH at the start, then 5100H-51FFH). Alternate set during a read: 37E1H, then 37ECH. |
| DE | Main set: the load address of the current record. Alternate set: Register D = the track and Register E = the sector to read next; during a read 37EFH. |
| BC | Main set: Register B = the record type being counted down, Register C = the bytes left in the record. Alternate set: Register B = tries left; during a read the buffer pointer. |
Disassembly
4200H - Boot Sector: Entry and FDC Reset
The Model I ROM's bootstrap (069FH) reads track 0, sector 0 of the diskette in drive 0 into 4200H-42FFH and jumps to 4200H. Nothing is set up for this code: the registers hold whatever the ROM left in them, and interrupts are still enabled until 4203H.
4215H - Load SYS0/SYS Record by Record
SYS0/SYS is a load module: a sequence of records, each a type byte, a length byte and the data. Type 01H is a load block (two address bytes, then length minus 2 bytes of data), type 02H is the transfer address (two bytes); types 00H and 03H-1FH are skipped; a type of 20H or more means this is not a load module. The bytes come one at a time from the sector buffer at 5100H-51FFH through 4252H, which reads the next sector when the buffer is used up.
Record Loop
Each pass reads one record header. Register Pair HL (main set) is the buffer pointer, the alternate Register Pair DE' the next sector to read.
422EH - Type 01H: Copy a Load Block
Register E holds the low byte of the load address and Register C the record length. The block's data bytes are copied to their load address one by one.
Data Byte Loop
Register Pair HL = buffer pointer, Register Pair DE = load address, Register C = data bytes left. Also used by 4240H to skip the bytes of other record types.
4240H - Not Type 01H: Transfer Address or Skip
Reached from 422CH with Register B = the record type minus 1, Register C = the record length and Register E = the first byte after the length.
424CH - NO SYS: SYS0/SYS Is Not a Load Module
Reached from 4221H (a record type of 20H or more) or by falling through from 424BH (no A5H at the transfer address).
4252H - Fetch the Next Byte of SYS0/SYS
Returns in Register A the next byte of the sector buffer (5100H-51FFH) at Register Pair HL. When the buffer is used up it falls into 4255H, which reads the next sector first.
4255H - Read the Next Sector of SYS0/SYS into 5100H
Reads the sector named by the alternate Register Pair DE' (Register D = track, Register E = sector) of drive 0 into 5100H-51FFH, with up to 10 tries, then advances DE' to the following sector. Returns with the main register set restored, Register Pair HL = 5100H and Register A = the first byte of the sector.
Try Loop
Register B = tries left, Register Pair DE = track and sector. Each try selects drive 0, seeks and reads; a failed try restores the head to track 0 (42B9H) and comes back here.
The operand at 4261H is the number of sectors on one side of a track, filled in by FORMAT (SYS6 6791H: the sectors per track, halved for a double sided drive). It is 0AH (10) on this diskette. If the sector number is below it the CARRY FLAG is set.
Wait for the First Byte
The status bits kept are 7 (not ready), 1 (data request) and 0 (busy). The JP PO loops while exactly one (or three) of them is set; the usual exit is busy plus data request (two bits, even parity).
Transfer Loop
Register Pair DE = 37EFH (data register), Register Pair BC = the next buffer byte, Register Pair HL = 37ECH (status). The data request test is repeated three times in a row so that the loop is short enough for the FDC's data rate.
42A4H - End of the Read: Check the Status
Reached when the FDC is no longer busy (429AH) or the drive went not ready (42A2H). Register Pair HL = 37ECH; the stack holds the tries (Register Pair BC) and the track and sector (Register Pair DE).
The operand at 42B0H is the number of sectors per track (both sides), filled in by FORMAT (SYS6 678BH). It is 0AH (10) on this diskette. The Z FLAG is set when the track is used up.
FORMAT (SYS6 6778H) stores 01H in the operand at 42B5H when the drive's sectors are numbered from 1.
42B9H - A Failed Try: Restore and Retry
Register B = the tries left, Register Pair DE = track and sector, Register Pair HL = 37ECH.
42C3H - Display a Message and Stop
Entered with Register Pair HL pointing to a message (42DDH ERROR or 42E5H NO SYS). The characters are displayed through the ROM up to the 03H that ends the message, and the computer then loops on that byte for ever; the user must press RESET.
42CEH - Wait Until the FDC Is Not Busy
Entered with Register Pair HL = 37ECH (the FDC status). Returns with Register A = the FDC status once bit 0 (busy) is clear.
42D7H - Short Delay
A fixed delay of six passes through a DEC/JR loop. Register A is used as the counter and returns 00H; the other registers and the memory are not touched.
42DDH - Messages and the Rest of the Boot Sector (Data)
The two messages displayed by 42C3H, then the unused bytes of the sector and three bytes that FORMAT fills in from the drive's PDRIVE record.
Sector 1: A Copy of the Boot Sector
The second sector of BOOT/SYS (track 0, sector 1). It holds exactly the same 256 bytes as sector 0: FORMAT writes its boot sector image (SYS6 64BAH) as both sector 0 and sector 1 of every diskette it formats (SYS6 6700H). The ROM reads only sector 0. The bytes are shown in rows of 32, at the offsets they have in the sector (4200H = byte 00H).
Sector 2: The System Data Sector (Data)
The third sector of BOOT/SYS (track 0, sector 2) holds the system data of the diskette: ten PDRIVE records, the numeric SYSTEM options, a validity byte and the yes/no SYSTEM options. It is read into the buffer at 4200H by SYS0's reset code (through the DOS FCB at 4480H, whose NEXT is sector 2), which copies the first 10 bytes of the records for drives 0-3 to 4371H-4398H and stores the options into the resident code; by SYS16 (PDRIVE) and SYS17 (SYSTEM), which change and rewrite it; and by SYS6 (6424H) when COPY or FORMAT need the PDRIVE data. The rows are shown at the addresses the bytes have in that buffer, which is how SYS16 and SYS17 address them (42A0H, 42F0H ...).
Sectors 3 and 4: Unused (Data)
BOOT/SYS is five sectors long (its directory entry gives an EOF of 0500H) because it fills the first granule of the diskette (a granule is five sectors). Only sectors 0-2 hold data; sectors 3 and 4 are filled with E5H.