DOSPLUS 3.5 for the Model III - SYS3/SYS Disassembled
Page Customization
Page Index
SYS3/SYS
Other Navigation
Introduction/Summary
DOSPLUS 3.5 SYS3/SYS Disassembly - CLOSE@ and KILL@ (Model III)
SYS3/SYS is the low overlay that closes and removes files: CLOSE@ (request code 23H) and KILL@ (24H), and two routines other overlays request: 25H, which frees the space and the entries of a file by its logical file number (SYS14/SYS, the library command KILL), and 26H, which puts the name of an open file back into its control block without closing it (SYS11/SYS). SYS0/SYS loads it at 4E00H over the low overlay before it.
The file is a load module of 3 blocks, 733 bytes, from 4E00H to 50DCH, with the transfer address 4E00H. It uses the 256 bytes at 5100H, after its end, as the buffer for the granule allocation table (5100H); the hash index table and the directory sectors go through the system buffer at 4300HH.
The Parts of SYS3/SYS
| Address | Contents |
|---|---|
| 4E00H-4E0BH | The routine table (routines 2-6) and routine 2 (4E00H, 4E0AH). |
| 4E0CH-4E48H | CLOSE@: devices, the last buffer, Disk space full (4E0CH). |
| 4E4EHH-4F79HH | The directory entry brought up to date and the granules beyond the end of the file given back (4E4EH). |
| 4F7AHH-4FE8HH | Routine 6 and the file specification put back into the control block (4F7AH, 4F87H). |
| 4FE9HH-507CHH | KILL@, routine 5 and the freeing of segments and granules (4FE9H, 500EH, 504FH, 5070H). |
| 507DHH-50DCH | The date for an entry and the reading and writing of the two tables (507DH, 5095H). |
Closing a File
CLOSE@ looks at the type byte of the control block: only an open file (80H-87H) is closed. An open device (90H) and a control block that is not open come back at once with Register A = 00H. A file first has its buffer written, through SYS0/SYS's 4497H, when it is blocked and holds updated bytes; when that write fails with error 1BH (Disk space full), the end of file byte is set to 00H, the entry is brought up to date all the same and 1BH is returned at the end (4E3FH).
The directory entry is then read (4E4EH). When the file has been written to (bit 6 of FCB+02H) the entry gets the modified flag and the month in its +01H, the day and year in its +02H, the end of file byte in +03H and the number of sectors (the ending record number, plus 1 when the end of file byte is not 00H) in +14H-15H, and is written back. The date comes from DATE$ (507DH); bits 2-0 of the year are stored, which is the year less 1980 up to 1987.
Unless the entry is non-shrinkable (bit 7 of its +01H, kept in bit 7 of FCB+02H), the granules the file holds beyond its end are given back, whether or not the file was written to (4EAAH). The granules are counted over every segment of every entry of the file (FEH links to an extended entry), the granules needed are worked out with DIVD@ from the sectors and the sectors per granule, and the difference is freed one granule at a time from the end of the last segment: each granule's bit in the allocation table (read into 5100H) is cleared, the segment's count is lowered, an emptied segment becomes FFH FFH, and an extended entry left with no segment is freed (its first byte and its hash index byte set to 00H) and the entry before it loses its FEH link (4F3FH). The entry and the table are written at the end.
Last, the control block becomes the file's specification again: name, / and the extension, : and the drive's name from DCTTBL, and 03H (4F87H). The password is not put back. Routine 6 does only this part, for an open file, without closing it (4F7AH).
Removing a File
KILL@ needs an open file whose access level (bits 2-0 of FCB+01H) is 0 or 1; otherwise it returns error 25H (4FE9H). Routine 5 then frees the file: for each of its entries the segments are cleared in the allocation table (504FH), the entry is made inactive by clearing bit 4 of its first byte, and its hash index byte is set to 00H; the entry keeps its name and segments, which is what lets a recovery tool bring the file back, as the manual says. An entry whose list ends with FEH is followed to the extended entry it names. The table is written back last, and KILL@ clears the 32 bytes of the control block (5003H).
The granule bits are cleared by a RES n,(HL) instruction whose second byte is stored before it runs (5070H); the logical file number of the entry before a freed extended entry is stored into the operand of an LD B,n (4F4DH).
Differences from the Manual
The manual (T/25) says that after CLOSE@ a device's control block holds the device's name again. DOSPLUS 3.5 returns at once for a device (4E16H); the code after the RET, which would store an @ and a name, is not reached.
The manual does not say that CLOSE@ gives back the granules beyond the end of a file that was only read, nor that a Disk space full error while writing the last buffer still closes the file.
Differences from the Model I
The code is the same as the Model I SYS3/SYS. The Model III file has one more byte 00H and the instruction LD (IX+00H),40H in the code that is not reached (4E17H-4E1EH), so everything from 4E1FH on is 5 bytes higher, and it uses the Model III addresses of SYS0/SYS: the system buffer 4300H, DCTTBL 44E8H, DATE$ 421AH, and the jump vectors 448BH, 448EH, 4494H, 4497H, 449AH, 449DH, 44A3H and 4451H (DIVD@) in place of the Model I's direct calls.
Variables
Memory Outside SYS3/SYS
| Address Size | Contents |
|---|---|
| 4300HH-42FFHH 256 bytes | System Sector Buffer Directory sectors (4E57H, 4F90H) and the hash index table (50B9H). |
| 44E8HH 32 bytes | DCTTBL Drive names at +02H (4FCBH). |
| 421AHH-421CHH 3 bytes | DATE$ The year less 1900, the day and the month (507DH). |
Work Areas
| Address Size | Contents |
|---|---|
| 5100H-51FFH 256 bytes | Allocation Table Buffer 5100H |
| 4F5CHH 1 byte | Logical File Number Of the entry before a freed extended entry: the operand of LD B,n (4F4DH, 4F5BH). |
| 507BHH 1 byte | RES Opcode The second byte of RES n,(HL) (5077H). |
| 5100H + cylinder 1 byte | Cylinder Byte Bit n set when granule n is in use (4F1BH, 5051H). |
The Directory Entry (as SYS3/SYS uses it)
| Offset | Contents |
|---|---|
| +00H | Bit 7 extended entry, bit 4 active (4E5BH, 4F3BH, 5032H). |
| +01H | Bit 7 non-shrinkable, bit 6 modified, bits 3-0 the month; in an extended entry, the logical file number of the entry before (4E72H, 4F4BH). |
| +02H | Day (bits 7-3) and year (bits 2-0) (4E82H). |
| +03H | The end of file byte (4E87H). |
| +05H-0FH | The name and extension (4F98H). |
| +14H-15H | The number of sectors (4E9AH). |
| +16H-1DH | Four segment descriptors: the cylinder, then bits 7-5 the first granule and bits 4-0 the granules less 1 (4EB4H). |
| +1EH-1FH | FFH FFH, or FEH and the logical file number of an extended entry (4F67H). |
The File Control Block (as SYS3/SYS uses it)
| Offset | Contents |
|---|---|
| +00H | Type: 80H-87H an open file, 90H a device (4E0CH). |
| +01H | Bits 2-0 the access level (4FECH). |
| +02H | Bit 7 non-shrinkable, bit 6 modified (4E64H, 4EAAH). |
| +06H | The drive. |
| +07H | The logical file number. |
| +08H | The end of file byte. |
| +0CH-0DH | The ending record number (4E8DH, 4ED5H). |
Outside Routines
| Address | Contents |
|---|---|
| 448EH | SYS0/SYS: the file control block check and wrapper (4E37H, 4F7AH, 4FE9H). |
| 448BH | SYS0/SYS: the wrapper entered after the check (4E13H, 500EH). |
| 4497H | SYS0/SYS: write the buffer when it holds updated bytes (4E3AH). |
| 4488H | SYS0/SYS: DISKIO%, functions 6 (SREAD) and 7 (SWRITE) (5095H). |
| 44A3H | SYS0/SYS: LOCDCT% (4E54H, 5015H). |
| 449AH, 449DH | SYS0/SYS: read and write the directory sector of a logical file number. |
| 4451H | SYS0/SYS: DIVD@ (4EE5H). |
| 4494H | SYS0/SYS: 8 bit divide (4F12H). |
Disassembly
4E00H - The Routine Table
Data: SYS3/SYS's table of routines 2-6, one word each, used by SYS0/SYS's overlay request handler (its 49D3H-49E6H) for the request codes 22H-26H. CLOSE@ (4428H) requests 23H and KILL@ (442CH) 24H; SYS14/SYS requests 25H (its 553AH) and SYS11/SYS 26H (its 56E9H). No file of the diskette requests 22H.
4E0AH - Routine 2
Nothing to do when SYS0/SYS's record locator brings SYS3/SYS back.
4E0CH - CLOSE@ - Close a File or a Device
Routine 3, requested by CLOSE@ (4428H) with Register Pair DE pointing to a file or device control block. An open file (type byte 80H-87H) has its last buffer written, its directory entry brought up to date, the granules beyond its end given back (unless the entry is non-shrinkable) and its name, extension and drive put back into the control block. Anything else (an open device, type 90H, or a control block that is not open) returns at once with Register A = 00H and nothing changed. Register A returns 00H with the Z FLAG, or an error code with the NZ FLAG.
4E4EH - Bringing the Directory Entry Up to Date
Reads the sector of the file's directory entry (logical file number FCB+07H, drive FCB+06H). When the file has been written to (bit 6 of FCB+02H), the entry gets the modified flag, today's date, the end of file byte and the number of sectors, and is written back. Then, unless the entry is non-shrinkable (bit 7 of FCB+02H, from bit 7 of the entry's +01H), the granules beyond the end of the file are given back (4EAAH on). It ends at 4F87H, which puts the file name back into the control block.
4F7AH - Routine 6 - Putting the Name Back
Requested with code 26H (SYS11/SYS, its 56E9H) for the open file at Register Pair DE: the directory entry is read and the file's name, extension and drive are put back into the control block as a file specification, as CLOSE@ does, but nothing is written to the diskette.
4F87H - The File Specification Put Back
Makes the file control block at Index Register IX the file's specification again: the name (up to 8 characters), a / and the extension when there is one, a : and the drive's name from DCTTBL, and 03H at the end. The password is not put back (the manual, T/25, says the same). The directory sector of the file's entry is read again first when the buffer holds another sector.
4FE9H - KILL@ - Remove a File
Routine 4, requested by KILL@ (442CH) with Register Pair DE pointing to an open file control block. The file needs an access level of 0 or 1 (FCB+01H bits 2-0), else error 25H. Its granules are given back in the granule allocation table, every entry of the file is made inactive (bit 4 of the first byte cleared, the rest left, so a recovery tool can find it) and has its hash index byte cleared; then the 32 bytes of the control block are set to 00H.
500EH - Routine 5 - Freeing a File's Space and Entries
Requested with code 25H (SYS14/SYS, its 553AH) with Register B the logical file number of a file's first entry and Register C its drive; KILL@ comes in at 5011H. For each entry of the file in turn: its segments are freed in the granule allocation table (read into 5100H), the entry is made inactive and written, and its byte in the hash index table is cleared; an entry whose list ends with FEH goes on to the extended entry it names. The table is written back at the end.
504FH - Freeing a Segment
Clears in the granule allocation table at 5100H the bits of the granules of the segment Register E (cylinder), Register D (bits 7-5 the first granule, bits 4-0 the number less 1). The segment may run on into the next cylinders: the granule count wraps at the granules per cylinder (DCT+10H at Index Register IY).
5070H - Freeing a Granule
Clears bit Register A (0-7) of the byte at Register Pair HL, by storing the second byte of a RES n,(HL) instruction (86H + n times 8) at 507BH and running it.
507DH - The Date for the Directory Entry
Returns Register B = the month (bits 3-0 of 421CH) and Register C = the day (bits 4-0 of 421BH) in bits 7-3 and bits 2-0 of the year (421AH, the year less 1900) in bits 2-0, the form of an entry's +02H; Register A returns the month as well. The manual gives bits 2-0 as the year less 1980: 80 is a multiple of 8, so the two agree for 1980-1987.
5095H - Reading and Writing the Tables
5095H reads and 50A7H writes the granule allocation table (directory sector 0) of drive Register C through 5100H; 50B9H reads and 50CBH writes the hash index table (directory sector 1) through 4300H, the system buffer. Each returns the Z FLAG when done, or the NZ FLAG with error 14H, 15H, 16H or 17H.
5100H - The Table Buffer
Not in the file: the granule allocation table of the drive is read here (5095H) and written from here (50A7H), one byte per cylinder from 5100H, bit n set when granule n of the cylinder is in use.