TRS-80 DOS - TRSDOS v2.3 for the Model I - SYS3/SYS Disassembled
Page Customization
Page Index
SYS3/SYS
Other Navigation
Introduction/Summary
TRSDOS v2.3 SYS3/SYS Disassembly - Closing and Killing Files (Model I)
SYS3/SYS is the TRSDOS 2.3 system overlay that closes and kills files. SYS0/SYS loads it into the overlay area at 4E00H whenever an RST 28H code with 5 in bits 0-3 is executed, and enters it at 4E00H with that code in Register A and Register Pair DE pointing at the FCB. Before doing anything it checks every field of the FCB, so a stray or closed FCB is refused with error 26H (FILE NOT OPEN) rather than corrupting the directory.
The file holds 768 bytes in four load records covering 4E00H-50FFH, after a name record and a 169-byte copyright comment record; its transfer address is 4E00H. The code ends at 5085H and the rest of the file, 5086H-50FFH, is FFH filler. Every byte is shown once on this page, in address order, checked against S:\1\SYS3.SYS and its listing.
Memory Map
| Address Range | Use |
|---|---|
| 4E00H-4E6CH 109 bytes | Check the FCB field by field, then dispatch to close or kill. |
| 4E6DH-4F00H 148 bytes | Close: flush the buffer, update the directory entry, count the granules. |
| 4F01H-4F6DH 109 bytes | Free the granules a shrunken file no longer needs. |
| 4F6FH-4FCFH 97 bytes | Write the tables back and rebuild the filespec text in the FCB. |
| 4FD0H-5038H 105 bytes | Kill: free every granule and clear every entry the file uses. |
| 5039H-5067H 47 bytes | Free an extent's granules in the allocation table. |
| 5068H-5085H 30 bytes | Read and write the hash index table. |
| 5086H-50FFH 122 bytes | FFH filler, unused. |
Functions
Bits 0-3 of both codes are 5 (SYS3/SYS); bits 4-6 are the function that 4E00H tests. SYS0/SYS's fixed entry points supply the codes.
| Code | Entered From | Function |
|---|---|---|
| 95H | 4428H | Close the open file in the FCB at Register Pair DE (4E6DH). |
| A5H | 442CH | Kill (delete) the open file in the FCB at Register Pair DE (4FD0H). |
The Three Buffers
SYS3/SYS works on three 256-byte sectors of the directory track, each in its own buffer: the directory sector holding the file's entry in 4200H (read and written by SYS0/SYS's 4AC1H and 4AD6H), the granule allocation table in 4D00H (4AF0H and 4B03H), and the hash index table in 5100H, just above the file, read and written by SYS3/SYS's own 5068H and 5077H.
Closing
Close flushes the buffer if it holds changed records, then reads the file's directory entry and, when the end-of-file byte or the ending record number has changed, writes them back. It then counts the granules in the file's extents, following any continuation entries, and divides the ending record number by five to find how many granules the file actually needs. Any surplus granules are freed from the end of the file, an emptied extent is marked unused, and a continuation entry that becomes empty is unlinked. Finally the tables are written back and the FCB is turned back into the filespec text NAME/EXT:D.
Killing
Kill is refused with error 25H when the file's access level is 2 or more. Otherwise it frees every granule of the primary entry and of each continuation entry in the allocation table, clears each 32-byte entry to zero, zeroes each entry's hash index byte, writes the tables back and clears the FCB.
Notes from the Code
- The FCB check at 4E00H compares the FCB's and the buffer's high bytes with the top of memory at 404AH, so a close or kill of an FCB above installed memory is rejected as FILE NOT OPEN.
- Close reads the hash index table (4EFBH) only so that a continuation entry it empties can have its hash index byte cleared; a file with no continuation entries never changes the table.
- After a close the FCB no longer holds the open file's control fields; its first bytes are the filespec as text, ready to be parsed again.
- Kill follows the continuation chain through the FEH track byte, so a file spread across several directory entries is removed completely.
Variables
Self-Modified Operands
| Address | Purpose |
|---|---|
| 4F22H 1 byte | Operand of ADD A,nn at 4F21H: the track offset to the granule being freed (set at 4F16H). |
| 4FC8H 1 byte | Operand of LD A,nn at 4FC7H: the drive as a character for the rebuilt filespec (set at 4F8CH). |
| 5066H 1 byte | Operand of RES 0,B at 5065H: made RES n,B to clear the right granule bit (set at 5062H). |
Addresses Outside SYS3/SYS
| Address Range | Use |
|---|---|
| 404AH 1 byte | High byte of the top of memory, the upper limit for the FCB check at 4E09H and 4E20H. |
| 4200H-42FFH 256 bytes | Directory sector buffer (SYS0/SYS 4AC1H, 4AD6H). |
| 4D00H-4DFFH 256 bytes | Granule allocation table buffer (SYS0/SYS 4AF0H, 4B03H). |
| 5100H-51FFH 256 bytes | Hash index table buffer, above the file (5068H, 5077H). |
| 4892H, 4878H, 4AC1H, 4AD6H, 4AF0H, 4B03H, 4B55H, 4B84H, 4B35H, 46EFH SYS0/SYS | File call set-up, flush the buffer, read and write a directory sector, read and write the allocation table, the directory track, divide by a byte, read and write a system sector. |
Disassembly
4E00H - Function Dispatcher and FCB Check
SYS0/SYS's overlay call (4BFBH) enters SYS3/SYS here with Register A = the RST 28H code whose bits 0-3 are 5, and Register Pair DE = the FCB. Before dispatching, the FCB is checked field by field; any field that is wrong returns error 26H (FILE NOT OPEN) and nothing is done. Bits 4-6 then select the function: 10H (code 95H, 4428H) closes the file, 20H (code A5H, 442CH) kills it.
Restore Register Pair AF (Register A = the function code) from the stack. 4E4EH comes here.
Restore Register Pair AF from the stack. 4E07H, 4E0FH, 4E14H, 4E1EH, 4E23H, 4E2AH, 4E2EH, 4E35H, 4E39H, 4E47H and 4E52H come here.
4E6DH - Close a File (4428H)
Index Register IX = the open FCB. Writes the buffer if it holds changed records, updates the file's directory entry with the end-of-file byte and ending record number, then compares the granules the file holds with the granules its ending record number needs; any surplus granules are freed. Returns Register A = 00H and the Z FLAG, or an error number and the NZ FLAG.
Restore Register Pair HL (the entry's end-of-file byte) from the stack. 4E88H, 4E92H and 4E99H come here.
INCrement Register L (the entry pointer) by 1, to entry+16H, the first extent. 4E9CH comes here.
Fetch an extent's track from (HL) (Register Pair HL = the entry's extent) into Register A. 4EC7H, 4ECAH and 4ED7H loop back here.
If the NZ FLAG is set (FFH, the end of the extents), JUMP to 4ED9H. 4EBEH comes here.
Save Register Pair HL (the entry's extent) onto the stack. 4ECCH comes here.
4F01H - Free the Surplus Granules
Index Register IX = the FCB, Register Pair HL = the file's last extent in a directory sector at 4200H, Register Pair DE = the number of granules to free, the granule allocation table is in 4D00H and the hash index table in 5100H. Frees granules from the end of the file one at a time, shortening the last extent and, when an extent empties, marking it unused and unlinking a continuation entry that becomes empty. Returns through 4F6FH once the count reaches zero.
Copy the low byte of the count left from Register E into Register A. 4F6DH loops back here.
00H in the file.
Store FFH into the granule byte at (HL) (Register Pair HL = the granule byte): the extent is unused.
DECrement Register E (the count of granules still to free) by 1. 4F32H and 4F3FH come here.
4F6FH - Write the Tables and Rebuild the Filespec
Writes the directory sector, the hash index table and the allocation table back, then turns the FCB back into the filespec text NAME/EXT:D so the caller can read or reopen the file. Returns Register A = 00H.
Fetch the entry locator from byte 07H of the FCB at (IX+07H) (Index Register IX = the FCB) into Register A. 4EECH and 4EEFH jump here.
Fetch a name character from (HL) (Register Pair HL = the entry's name field) into Register A. 4FA7H loops back here.
DECrement Register B and LOOP BACK to 4F9FH until eight characters are copied.
Restore Register Pair HL (the name field) from the stack. 4FA2H comes here.
Fetch an extension character from (HL) (Register Pair HL = the extension field) into Register A. 4FC1H loops back here.
DECrement Register B and LOOP BACK to 4FB9H until three characters are copied.
Load Register A with 3AH, the colon before a drive number. 4FB1H and 4FBCH come here.
00H in the file.
4FD0H - Kill a File (442CH)
Index Register IX = the open FCB. Removes the file: every granule it holds is freed in the allocation table, every directory entry it uses (the primary and any continuation entries) is cleared and its hash index byte zeroed, the tables are written back and the FCB is cleared. Refused with error 25H when the file's access level is 2 or more. Returns Register A = 00H and the Z FLAG, or an error number and the NZ FLAG.
GOSUB to SYS0/SYS's 4AC1H to read the directory sector holding entry Register B into 4200H; Register Pair HL = the entry. 5024H loops back here for a continuation entry.
Fetch the extent's track from (HL) (Register Pair HL = the extent) into Register E. 5003H loops back here.
Copy the entry pointer from Register L into Register A. 4FFDH comes here.
Store Register A (00H) into the FCB at (HL) (Register Pair HL = the FCB). 5036H loops back here.
DECrement Register B and LOOP BACK to 5034H until the FCB is zero.
5039H - Free an Extent's Granules
Register E = the extent's track, Register D = its granule byte (bits 5-7 the first granule, bits 0-4 one less than the count); the allocation table is in 4D00H. Clears the allocation bit of each of the extent's granules, stepping to the next track after the second granule on a track. Registers are preserved.
Save Register Pair AF (Register A = the granule number) onto the stack. 5056H loops back here.
DECrement Register C (the granules left) by 1. 5051H comes here.
AND Register A (the granule number) with 07H. 5049H calls here.
80H in the file (RES 0,B).
5068H - Read the Hash Index Table
Register C = drive. Reads directory sector 1 into 5100H-51FFH. Returns the Z FLAG, or Register A = 16H (HIT READ ERROR) and the NZ FLAG.
5077H - Write the Hash Index Table
Register C = drive. Writes 5100H-51FFH back to directory sector 1 with the FAH data mark. Returns the Z FLAG, or Register A = 17H (HIT WRITE ERROR) and the NZ FLAG.
5086H - Unused
The last load record fills the overlay area to 50FFH with FFH; nothing uses these bytes.
122 bytes of FFH in the file, below the hash index buffer at 5100H. SYS3/SYS never reads or executes them.