TRS-80 DOS - LDOS 5.3.1 for the Model I - SYS6/SYS Disassembled
Page Customization
Page Index
SYS6/SYS
Overlays in SYS6
Other Navigation
Summary:
LDOS 5.3.1 SYS6/SYS Disassembly - Library A Command Overlay Set (Model I)
SYS6/SYS is the Library A transient command file of LDOS 5.3.1 for the TRS-80 Model I. It is not a single program: it is a partitioned overlay file holding fifteen independent command overlays. Every overlay is assembled to load and run at 5200H, directly above the resident operating system (SYS0/SYS occupies 4000H-4DFFH and the RST 28H dispatcher/overlay loader live inside it). Only one overlay is resident at any moment; the resident overlay loader reads the requested overlay into 5200H, transfers control to it, and the overlay runs to completion and returns to the caller.
SYS6 is reached through the resident supervisor call RST 28H with the request code 88H in register A and the command number in register B. The resident dispatcher at 4BCDH (see the SYS0 disassembly) recognises code 88H as "Library A", calls the overlay loader at 4BF5H to bring the B-th overlay of SYS6 into memory at 5200H, and enters it at its first byte. The companion file SYS7/SYS is Library B (request code 89H) and holds the remaining transient commands. The command-name to (library, number) mapping is performed earlier by the command interpreter SYS1/SYS, which classifies the typed command word and issues the appropriate RST 28H request.
Because all fifteen overlays share the load address 5200H, the addresses in this disassembly repeat from overlay to overlay. Each overlay is documented as its own numbered section below, in the order it appears in the SYS6 file (which is the order of its command number). The entire memory image of every overlay in this page has been verified byte-for-byte against the raw SYS6.SYS load module (the LDOS load records were parsed and each overlay's loaded bytes compared against the listing; 0 mismatches across all fifteen overlays).
SYS6 Overlay Structure Map
The fifteen overlays and their SYS6.SYS file offsets, load range, and function. Each overlay begins with a stack-pointer save (LD (nnnnH),SP) so that it can restore the caller's stack and return, then validates its command line through the resident parameter services before performing its work.
| Overlay | File Offset | Load Range | Command / Function |
|---|---|---|---|
| 1 | 00C7H | 5200H-5603H 1028 bytes | MEMORY High-memory management and the high-memory module directory. Sets and reports HIGH$ (4049H), reserves or releases high memory, and walks the resident high-memory module chain printing each module name, start, end and length. |
| 2 | 04E2H | 5200H-5BE0H 2529 bytes | DIR Directory display. Reads directory records, formats the Filespec / Attrib / LRL / #Recs / EOF / DE / File Size / MOD Date Time columns, computes free space, and supports the invisible, system, date/modified and sort options. |
| 3 | 0EEEH | 5200H-5370H 369 bytes | REMOVE Deletes one or more files. Requires a file spec, displays "Deleting: " for each file, and calls the resident @KILL service. |
| 4 | 106AH | 5200H-52D2H 211 bytes | LIB Displays the Library A command directory ("Library <A>"), the list of command words serviced by SYS6. |
| 5 | 1144H | 5200H-5D00H 1737 bytes | DO The Job Control Language processor. Reads a JCL source file, honours the IF / ELSE / END / SET / RESET / ASSIGN / INCLUDE / QUIT directives, expands parameters, and writes the compiled SYSTEM/JCL file that the resident keyboard driver then replays. |
| 6 | 1838H | 5200H-59DAH 1925 bytes | SPOOL The printer spooler. Allocates or reclaims the spool buffer, starts, pauses, resumes and clears despooling, and reports spooler status. Sub-options MEM, SDISK, N(o disk), PAUSE, RESUME and CLEAR. |
| 7 | 1FE8H | 5200H-5A6DH 2003 bytes | COPY File copy and append. Displays "Copying: " / "Appending: ", checks LRL compatibility, prompts for SOURCE and DESTINATION disk swaps on a single-drive system, and supports the CLONE, STRIP, ECHO and X options. |
| 8 | 27E6H | 5200H-563BH 1084 bytes | LIST Lists the contents of a file to the screen with ASCII, HEX, LINE, REC(ord), NUM(ber) and TAB-expansion options. |
| 9 | 2C39H | 5200H-53A4H 421 bytes | RENAME Renames a file. Requires a file spec, rejects a duplicate name ("Duplicate file name!"), and updates the directory entry. |
| 10 | 2DE9H | 5200H-56DFH 1208 bytes | SYSTEM (status/drives) Reports the system configuration: resident system modules, drive geometry (floppy/rigid, removable/fixed, cylinders, sides, density, step and settle timing, verify), and the BYTEIO / DRIVES / STATUS sub-options. |
| 11 | 32BCH | 5200H-53A1H 418 bytes | LINK Links two character devices so that output to one is also sent to the other. Requires a device spec and refuses to link a routed device. |
| 12 | 3469H | 5200H-54D5H 726 bytes | Command overlay 12 Accepts LRL and DATE parameters (keyword table SO / LRL / DATE) and manages a memory reset; it emits "Can't reset memory, background task(s) exist" when active background tasks block the operation. Valid only at LDOS command level. |
| 13 | 374EH | 5200H-53F3H 500 bytes | ROUTE Routes a character device, including to NIL and with a REWIND option. Requires a device spec and is valid only at LDOS command level. |
| 14 | 394DH | 5A00H-5B43H 324 bytes | Command overlay 14 (device driver/filter) Attaches a driver or filter to a character device (references "DVRFLT"). Requires a file spec and a device spec and is valid only at LDOS command level. |
| 15 | 3A9CH | 5200H-536FH 368 bytes | Command overlay 15 (disk-swap operation) Prompts "Insert SYSTEM disk" and "Insert SOURCE disk" and can report "Command aborted!"; drives a single-drive multi-disk operation and requires a file spec. |
Resident SYS0 Services Used By SYS6
Every overlay reaches back into the resident SYS0 core for its parameter parsing, display, math and directory primitives. These are external references; each is linked to the SYS0 disassembly at its resident address.
| Address | Resident Service |
|---|---|
| 402DH | @EXIT Normal return to the LDOS command level; an overlay jumps here after clearing itself out of high memory or when finished. |
| 4030H | @ABORT Abnormal return to DOS on a fatal command error. |
| 4049H | HIGH$ Resident word holding the current top-of-user-memory address; the MEMORY command reads and rewrites it to reserve or release high memory. |
| 4403H | Resident word holding the top of physical/available memory used as the ceiling when computing free high memory. |
| 4467H | @DSPLY Display a message (HL points to the text) to the video device. |
| 4476H | @PARAM Parse the command line against a parameter descriptor table (DE points to the table); returns NZ on a parameter error. |
| 447BH | @LOGOT Display a carriage-return-terminated string (HL points to the text). |
| 4D76H | Resident routine that stores register pair DE as four hexadecimal ASCII digits at (HL); used to format addresses such as X'nnnn'. |
Cross-Reference Notes
SYS6 is entered from the resident RST 28H dispatcher at 4BCDH in SYS0/SYS in response to request code 88H, and returns to it (or to @EXIT 402DH / @ABORT 4030H). The command interpreter SYS1/SYS decides which SYS6 command number to request. SYS6 itself calls only into the resident SYS0 core (4000H-4DFFH); it does not call SYS7 or any other overlay. Companion command file SYS7/SYS is Library B (request code 89H).
Disassembly - Overlay 1
5200H - Overlay Entry and Command Parameter Parse
Entry point of the MEMORY command overlay. It saves the caller's stack pointer for a clean return, then hands its command tail to the resident @PARAM service to decode the CLEAR, ADD, WORD, BYTE, GO, PRINT and HIGH keywords. Each recognised keyword deposits its value directly into the operand field of an instruction inside this overlay, so the tests that follow read those self-modified operands.
Store the caller's stack pointer into the operand of the LD SP,nnnn instruction at 546BH so the overlay exit can restore the caller's stack exactly. Register SP holds the LDOS command-level stack on entry.
Command Dispatch
The overlay's behaviour is selected entirely by which @PARAM keyword was present. Each keyword deposited its argument into a self-modified operand cell (520EH CLEAR, 523CH ADD, 525FH WORD, 5266H BYTE, 5295H HIGH, 542EH PRINT, 5460H GO), and the tests below branch on those cells.
Load DE with the CLEAR keyword value. The operand at 520EH is 0000H as assembled but is overwritten by @PARAM with the CLEAR argument; DE therefore holds the CLEAR request (nonzero when CLEAR was given).
5224H - CLEAR Routine Template (Relocated to 4200H)
This 23-byte block is not executed in place. The setup above copies it to the resident scratch buffer at 4200H and returns into it. Running there, it zero-fills memory from 5201H up to the current HIGH$ ceiling and exits to DOS, wiping the reserved high-memory region requested by the CLEAR keyword.
523BH - ADD Keyword: Hexadecimal and Decimal Value Display
Reached when CLEAR was not given. If the ADD keyword supplied a value it is echoed back to the operator both ways - as a 4-digit hexadecimal address and as a decimal number - in the form X'dddd' = ddddd ('dddd' => X'dddd'), using the resident hex-format and the local decimal-format helpers.
Load register pair HL with the ADD keyword value. The operand at 523CH is assembled as 0000H and patched by @PARAM with the ADD argument; HL therefore holds the number to be displayed (zero if ADD was not given).
Load register pair DE with the WORD keyword value. The operand at 525FH is patched by @PARAM; DE is nonzero if WORD was requested.
Load register pair DE with the BYTE keyword value. The operand at 5266H is assembled as 00FFH and patched by @PARAM; DE reflects whether BYTE was requested.
5294H - HIGH Keyword: Reserve or Release High Memory
If the HIGH keyword supplied a new HIGH$ value this section validates it against the overlay's own load address and the top of memory, plants a relocatable reserve stub just below the new ceiling, and rewrites the resident HIGH$ word (4049H). If HIGH was not given, control falls through to the high-memory directory display.
Load register pair BC with the HIGH keyword value. The operand at 5295H is patched by @PARAM; BC holds the requested new HIGH$ ceiling (zero if HIGH was not given).
Range Check
A requested HIGH$ must lie above this overlay's load area yet not above the current ceiling; either violation jumps to the Range error entry at 5495H.
52CFH - Confirm HIGH$ and Prepare Directory Display
Compares the resident HIGH$ ceiling (4049H) against the top-of-memory word (4403H). When they are equal (no high memory reserved) it shows the current High = X'xxxx' line; otherwise it proceeds to walk the reserved high-memory module chain.
52E7H - High-Memory Directory: Header and Module Loop
Prints the High Memory Directory heading and then iterates over the resident high-memory module chain. For each linked module it copies the module's name and computes and formats its start address, end address and length into the display line.
5357H - Build the Directory Column-Header Line
Assembles the column-header line (Module / Start Address / End Address / Length) and the HIGH$ = value into the overlay's work area at 5200H, then emits it above the per-module rows.
53A4H - Scan the Resident High-Memory Module Chain
Walks the chain of resident high-memory module headers. Each header is found by its 18H marker byte; the routine reads the forward link and the module name, validates the name characters, and formats each module's extent for display, looping until the chain reaches the top of memory.
Loop End
CPIR either finds the 18H module marker or exhausts the byte count in BC.
53FFH - Helper: Format Register Pair as Hex Address Field
Utility used throughout the directory display. It converts the value in HL to four hexadecimal ASCII digits (via the resident 4D76H formatter) and drops them, wrapped in X'____', into the caller-supplied field.
5411H - Helper: Format Value as Right-Justified Decimal
Utility that converts the binary value in HL to a right-justified, space-padded decimal string of up to five digits at the buffer addressed by DE, using the resident divide-by-ten helper (44C4H).
542AH - Helper: Emit the Work Line and Blank It
Displays the assembled work line at 5200H to the video device (and to the printer when the PRINT keyword was given), then refills the 57-byte work area with spaces ready for the next line.
Load register pair DE with the PRINT keyword value. The operand at 542EH is patched by @PARAM; DE is nonzero when PRINT was requested so output is echoed to the printer.
543FH - Helper: Optional Pause / Wait for a Key
Provides the paged-display pause. It tests a self-modified counter; when a screen is full it waits at the ROM keyboard scan for a key, honouring the BREAK key as an abort back to DOS.
Load register A with 0FH (15), the count of lines per screen. The store below patches the counter cell at 5440H, so this value is decremented on each call.
545FH - Overlay Exit and Caller Stack Restore
The common exit. It optionally jumps through a saved vector, restores the caller's stack pointer that was saved at entry, and returns to the LDOS command level, or aborts to DOS if the system flag demands it.
Load register SP from the operand at 546CH, which was set at entry (5200H) to the caller's stack pointer, restoring the caller's stack for the return.
547AH - Command-Level and System-State Check
Verifies that the command was issued from the LDOS command level and not from within another running program or a background task, refusing the operation and displaying the Can't message otherwise.
As assembled this is LD IX,54DDH (bytes DD 21 DD 54), loading register pair IX with the address of the Range error message so the caller-level rejection can show it. When control instead jumps to 5495H (skipping the DD prefix byte), the same bytes 21 DD 54 read as LD HL,54DDH, loading HL with the Range error message address for the out-of-range HIGH$ path.
Self-Modifying / Overlapping Code
This is the single deliberate overlap in the overlay: the byte at 5494H (DD) is an IX prefix on the fall-through path but is skipped when entered at 5495H, so the following three bytes serve as either LD IX,54DDH or LD HL,54DDH.
54A0H - Parameter Error Handler
Entered when @PARAM rejected the command line. It raises the resident error service with the syntax-error code and returns to DOS.
54A9H - MEMORY Data: Reserved-Block Module-Header Template
The 10-byte resident-module header that the ADD keyword copies to the top of memory to mark the block it has just reserved. Its link and name fields are patched in code before the copy.
Copied into high memory by the ADD routine at 52C5H (LDIR of 000AH bytes). These two bytes are a JR +8 relative jump: when the reserved &-block is later entered as a resident high-memory module, this jump skips the 8-byte module header to the block body.
54B3H - MEMORY Data: Error Messages
The two error strings displayed by the MEMORY overlay: the command-level restriction and the range-error report. Both are carriage-return terminated.
The Can't -- Only valid at LDOS command level text. Its address is loaded into HL at 5491H and displayed by the resident @LOGOT service at 447BH (called at 5498H) when MEMORY is invoked from anywhere other than the LDOS command line.
The Range error text. Its address is loaded into IX at 5494H as the companion message for the same command-level/range error report driven from 5491H-5498H.
54E9H - MEMORY Data: @PARAM Keyword Descriptor Table
The parameter table handed to the resident @PARAM service at 5204H. Each 8-byte entry is a 6-character keyword name followed by the two-byte address of the instruction operand that @PARAM overwrites when that keyword appears. Every keyword is listed twice: spelled in full and as its one-letter abbreviation.
Address passed to the resident @PARAM parser in DE at 5204H. @PARAM scans the command tail; when it matches a keyword it writes the supplied value into the two-byte operand cell named by that entry, self-modifying the instruction that later tests the keyword. This entry is the full keyword HIGH, whose value cell is the LD operand at 5295H.
555AH - MEMORY Data: Value-Display Templates
The two templates the HIGH and ADD keywords use to echo an address in both hexadecimal and decimal. The lower-case placeholder characters are overwritten in code with the formatted digits.
The High = X'xxxx' report line. Printed from 52E1H; the xxxx hexadecimal field at 5565H is overwritten with the current HIGH$ address by 52DBH.
The ADD-keyword value echo, X'dddd' = ddddd ('dddd' => X'dddd'). The first hex field (556DH) and the decimal field (5575H) are filled by 5244H/524CH; the parenthesised echo hex fields (557EH, 5589H) by 5257H/527BH. 5583H is the single-byte format position (selected at 5286H) and 558EH the word format position (selected at 5281H).
558FH - MEMORY Data: Directory Headings and Summary Labels
The title, summary-line labels and column headings the directory display copies into its 5200H work buffer before printing the high-memory module table.
The High Memory Directory title line, copied (0015H = 21 bytes) to the 5200H work buffer by 5357H.
The module-table column headings (Module / Start Address / End Address / Length), copied (003AH = 58 bytes) to the 5200H work buffer by 5398H.
55F4H - MEMORY Data: Fallback Name and Hex-Address Template
The placeholder name used for anonymous modules and the X'____' template used to print a 16-bit address. These occupy the final bytes of the MEMORY overlay (through 5603H).
The <unknown> text, loaded into HL at 53E8H and printed in place of a module name when a high-memory module header carries no printable name.
The X'____' hex-address display template (X' followed by four spaces and a closing quote). The four spaces at 55FFH receive the hex digits produced by the address-format helper at 53FFH; 5408H loads the full string and 5401H the digit field.
Disassembly - Overlay 2 - DIR
5200H - DIR Overlay Entry: Filespec, Drive and Option Parse
Entry of the DIR command overlay, which displays a disk directory. It first saves the caller's stack pointer for a clean return, then parses the command tail: an optional filespec mask (name and extension held in the 5B6AH/5B72H match buffers), an optional drive number, and the option keywords (A, I/INV, S/SYS, P, N, DATE, MOD, SORT) through the resident @PARAM service. Register HL points at the command tail on entry, set up by the resident overlay loader.
Store the caller's stack pointer into the operand of the LD SP,nnnn instruction at 540CH so the overlay exit can restore the caller's stack. Register SP holds the LDOS command-level stack on entry.
Store the drive number (register A) into the operand of the LD C,nn instruction at 52ADH, seeding the per-drive loop so it starts at the requested drive rather than drive 0.
5252H - DIR Setup: Busy-State Check, Sort-Buffer Ceiling and Date Filter
Prepares the global state for the listing. It notes whether the system is busy (which suppresses the in-memory sort buffer), computes the ceiling below HIGH$ into which sorted entries may be gathered, forces non-stop output when the printer option is active, and parses the optional DATE range into the start and end compare values, before falling into the per-drive scan loop.
Load register pair HL with the DATE-argument pointer. This operand at 5274H is patched by @PARAM when the DATE option is given, with the address of the date text; it is 0000H when DATE was not requested.
Load register C with the first drive to scan. This operand at 52AEH was set at 5246H to the requested drive number, or remains 0 to scan from drive 0.
Store 15 (register A) into the line counter at 58F3H, the operand the paged-display routine at 58F2H decrements to time each page pause.
52B4H - Per-Drive Loop: Drive Check, GAT Read, Free-Granule Count and Drive-Type Field
Top of the per-drive scan loop. For the current drive it verifies the drive is ready, loads that drive's Drive Control Table (DCT) into IY, determines whether extended date stamping is enabled for it, reads the Granule Allocation Table (GAT) into the shared buffer, counts the free granules, and builds the drive-type descriptor (floppy single/double density and sides, or hard-disk head count) for the header line. Register C holds the drive number on entry.
533DH - Disk Capacity, Directory Capacity, Disk Name and Header Display
Completes the header line for this drive. It computes the granules-per-cylinder and the total granule capacity, formats it as a kilobyte figure, works out the directory-entry capacity, counts the directory slots in the Hash Index Table (HIT), copies the disk name and creation date out of the GAT sector, then displays the assembled header line and the column-heading separator before dropping into the directory read loop.
Store the directory-entry capacity (register pair HL) into the operand of the LD DE,nnnn instruction at 53A3H, seeding the directory-slot count below.
Load register pair DE with the directory-entry capacity. This operand at 53A4H was set at 5378H; DE is the running directory-slot count.
53DEH - Record Advance, Drive-Loop Exit and Drive-Not-Ready Skip
Advances to the next directory record and, when a directory sector is exhausted, either sorts and flushes the collected entries or moves on. When the last record of the drive is done it either exits (single drive requested) or steps to the next drive. It also holds the common overlay exit and the path taken when a drive is not ready.
Load register A with the single-drive flag. This operand at 53FEH is 0FFH to scan all drives, or the requested drive number when an explicit drive was given at 5241H.
Restore the caller's stack pointer. This operand at 540DH was set from SP at overlay entry (5200H).
542DH - Directory Record Read Loop: Attribute, Name and Date Filters
The heart of the listing. For each directory slot it reads the record, rejects empty, secondary-extent, system, invisible and undated records according to the options in force, matches the file name and extension against the mask, applies the date range filter, and then either collects the record in the sort buffer or displays it immediately. Register B holds the record index and register C the drive number throughout.
Compare register A against the last-read sector marker; the 0FFH operand at 5439H is rewritten below so a directory sector already in the buffer is not read again.
Store this record's in-sector position (register A) into the comparison operand at 5439H, recording which directory sector is now being read.
Load register pair DE with the system-file filter. The operand at 5456H is set nonzero by @PARAM when the S or SYS option is given, and left zero otherwise.
Load register pair DE with the invisible-file filter. The operand at 5464H is set nonzero by @PARAM when the I or INV option is given.
Load register pair DE with the date-stamp filter. The operand at 546CH is set nonzero by @PARAM when the MOD option (date-stamped files only) is given.
Load register A with the partial-match flag. This operand at 549DH holds the - marker (nonzero) when substring matching is active, or zero for an exact match.
Load register pair DE with the sort-collection flag. This operand at 54CFH is nonzero when the SORT option is active and zero otherwise.
5509H - Format One Directory Line: File Name, Extension and Attribute Letters
Helper that formats and prints one directory entry. This first part emits the file name and extension (padded to a fixed column), then the attribute letters S (system), I (invisible), P (protected/access), the modified marker and the plus marker, each shown as its letter when the attribute is set or a hyphen when it is not. Register pair HL addresses the directory record on entry.
Store the protection character (register A) into the operand at 55C7H, where the detail formatter at 55C5H reuses it.
Load register pair DE with the detail-columns flag. This operand at 559AH is nonzero when the A (all detail) or SORT option requests the LRL/records/EOF/size/date columns.
Load register A with the output-pass counter. This operand at 55A2H governs the two-across column layout so entries are emitted in pairs per line.
55C5H - Detail Columns: Access, LRL, Records, EOF, Granules, Size and Modification Date/Time
Fills the detail portion of the line buffer for the A (all) and SORT listings: the access code, the logical record length, the record count, the end-of-file byte, the granule/extent count, the file size in kilobytes, and the modification date and time. It then displays the assembled line. Register pair HL addresses the directory record on entry.
Load register A with the protection character. This operand at 55C7H was set at 5577H to P or -.
Store the LRL (register A) into the operand at 5603H, reused below in the size calculation.
Load register A with the LRL saved at 55E8H (operand 5603H), the divisor for the record-count math.
5709H - File-Size Helpers: Stored Key and Extent Walk
Returns a file's granule/extent count in register pair DE and its size measure in register pair BC. When sorting, the value was pre-computed and stored in the record; otherwise it is computed here by walking the file's extents, following the secondary-extent (FXDE) chain and reading further directory sectors as needed.
Store the secondary record index (register A) into the operand at 574FH, recording which record now occupies the 5D00H buffer.
577CH - Output Helpers: Line, Character, Space and Printer
The low-level output primitives. 577CH displays a whole message and echoes it to the printer under the P option; 5787H emits a space; 5789H sends one character to the video and then, via 578EH, to the printer when the P option is active.
Load register pair DE with the printer-echo flag. This operand at 578FH is nonzero when the P option is active.
5796H - Granules-to-Kilobytes Formatter
Converts a granule count in register pair DE to a kilobyte figure written as decimal at the buffer addressed by register pair HL, returning the tenths digit in register A. It multiplies granules by sectors-per-granule to get sectors, divides by four (256 bytes per sector over 1024 bytes per kilobyte), and maps the fractional sectors to a tenths character.
Store the destination buffer pointer (register pair HL) into the operand at 57ABH used by the LD DE below.
Load register A with the sectors-per-granule value. This operand at 579BH was set at 52E8H from the drive geometry.
Load register pair DE with the destination buffer pointer saved at 5796H (operand 57ABH).
57C2H - Copy File-Name Field with Upper-Case Folding
Copies up to register B characters of a file name or extension from the command line (register pair HL) into the match buffer (register pair DE), folding lower case to upper case, passing the dollar wildcard through unchanged, and stopping at a delimiter. It returns the terminating character in register A.
57DDH - Decode a Directory Date to a Comparable Value
Reads the packed modification date from a directory record (register pair HL at the flags/month byte) and returns a single comparable year/day value in register pair DE, drawing the year either from the record's short field or, when extended dating is enabled for the drive, from the extended-date word.
5806H - Parse a Date Argument and Validate It
Parses an MM/DD/YY date field from the command line (register pair HL), validates the month against 12 and the day against the days-in-month table (allowing for a leap year), packs it into the comparable year/day form in register pair BC, and jumps to the parameter-error handler on any bad value. Helpers 5856H, 586BH and 5881H parse the individual fields.
5856H - Date-Field and Number Parsers
Supporting parsers for the date argument: 5856H reads three separator-delimited numeric fields into consecutive scratch cells; 586BH reads a one- or two-digit decimal number; and 5881H converts a single ASCII digit to binary and reports whether it was a valid digit.
5888H - Decimal Formatters
Right-justified decimal output into a buffer (register pair DE) from a 16-bit value (register pair HL). Entry points select the field width: 5888H and 588CH format up to five digits, 589AH three, and 58A0H two. Leading zeros are shown as the pad character in register A. 58ACH extracts one decimal digit for a given power of ten.
58C7H - Pause/BREAK Check and Keyboard-Flag Reset
Honours a keyboard pause and detects BREAK between listing lines, using the resident keyboard flag KFLAG$ (4423H) and the ROM keyboard scan. 58E8H resets the keyboard flag at the start of the command. The check is skipped unless the command is running at the LDOS command level.
58F2H - Paged-Display Line Counter and Separator
Counts displayed lines and, when a screen is full and pausing is enabled, waits for a key (honouring BREAK to abort and C/space to run non-stop) and reprints the column headings. 5921H prints the column-heading line and a 64-character rule beneath the drive header.
Load register A with the remaining-lines counter. This operand at 58F3H was set to 15 and is decremented per line.
Load register pair DE with the suppress-pause flag. This operand at 58FFH is nonzero to run non-stop (set for printer output or after a C keypress).
5944H - Name-Sort Engine (Shell Sort of Collected Entries)
When the SORT option is active, the matching records were gathered in the high-memory buffer from 5E00H. This routine builds a table of pointers to those records, sorts the pointers by file name and extension using a diminishing-gap (Shell) sort, and then displays the records in sorted order through the line formatter at 5509H.
Load register pair DE with the current gap. This operand at 599EH holds the diminishing sort gap (initialised from the record count on the first pass).
Load register pair HL with the outer index. This operand at 59BAH walks the elements to be gap-inserted.
Load register pair DE with the pass comparison limit. This operand at 5A1FH was set at 59B0H to the record count minus the gap.
5A29H - Error Handlers and Common Exit
The overlay's error exits. 5A29H reports insufficient sort memory as a message, 5A35H raises a parameter error, and 5A37H raises the disk or drive error whose code is already in register A; all set the failure status and jump to the shared exit at 540CH.
On the fall-through this loads register pair IX with 5BA7H and is inert; the message pointer was already set to 5B82H ("Insufficient memory for SORT buffer!") at 5A29H. Entered one byte later at 5A2DH from the date parser (580CH and 5833H), the bytes 21 A7 5B decode as LD HL,5BA7H, selecting the "Bad date format" message.
5A42H - DIR Option Keyword Table (@PARAM)
The parameter descriptor table handed to the resident @PARAM service at 524CH. Each entry is a 6-character space-padded keyword followed by the two-byte address of the operand cell that @PARAM sets when the keyword is present. Full names and one- or three-letter abbreviations share the same cell. A zero byte terminates the table. This is data, not code.
The A keyword sets the detail-columns flag at 559AH so the LRL, #Recs, EOF, DE, File Size and MOD Date/Time columns are shown.
The I keyword sets the invisible-file filter at 5464H so invisible files are listed.
The full INV spelling sets the same invisible-file filter cell 5464H.
The P keyword sets the printer-echo flag at 578FH so the listing is also sent to the printer.
The S keyword sets the system-file filter at 5456H so system files are listed.
The full SYS spelling sets the same system-file filter cell 5456H.
The N keyword sets the suppress-pause flag at 58FFH so the listing runs without stopping each screen.
The DATE keyword places the following date argument's address into 5274H, enabling the modification-date range filter.
The D abbreviation sets the same date-filter cell 5274H.
The MOD keyword sets the date-stamp filter at 546CH so only date-stamped files are listed.
The M abbreviation sets the same date-stamp filter cell 546CH.
The SORT keyword sets the sort-collection flag at 54CFH so entries are gathered and displayed in name order.
The O abbreviation sets the same sort-collection cell 54CFH.
5AABH - Column Heading, Access-Code Table and Display Templates
The static text the listing copies into its work buffers: the detail-column heading line, the two-character access-abbreviation table indexed by access level, the drive-header summary template and the per-file detail-line template. This is data, not code.
The ETX-terminated (03H) heading line printed by the separator routine at 5926H when the detail columns are shown.
Eight two-character access codes indexed by the file's access level (record attribute low 3 bits), copied to the line at 55D3H.
The ETX-terminated drive summary line. The lower-case placeholders (drive digit, pack name/date, cylinders/heads, free and total kilobytes, free and total directory slots) are overwritten in code before display.
The ETX-terminated per-file detail line. The placeholders (access code, LRL, record count, EOF, granule/extent count, size, and modification date/time) are filled by the formatter at 55C5H.
5B6AH - Match Buffer, Days-per-Month, Messages and Month Names
The remaining data: the name/extension match buffer built during command parsing, the days-per-month validation table, the two error messages, the three-letter month-name table used to format dates, and the record-count overflow marker. This is data, not code, and occupies the final bytes of the DIR overlay through 5BE0H.
Twelve spaces (name 8, extension 3, plus a guard) into which 57C2H copies the filespec mask; each directory entry's name is compared against this at 547EH.
The maximum day for each month, January through December (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31). The February entry at 5B77H is incremented to 29 in a leap year at 581FH during date validation.
The carriage-return-terminated message displayed by the error handler at 5A29H when the sort buffer will not fit.
The carriage-return-terminated message for a malformed DATE argument (reached via the parameter-error path from 5A2DH).
Twelve three-character month names indexed by month at 569CH to format the modification date.
The five asterisks copied into the record-count field at 5624H when the record count exceeds the display width. A zero pad byte at 5BE0H ends the overlay image.
Disassembly - Overlay 3 - REMOVE
5200H - REMOVE Command: Entry and File Loop
Entry of the REMOVE command overlay. It saves the caller's stack pointer, polls the keyboard so a BREAK can interrupt a wildcard removal, and steps through the command line one file specification at a time, killing each matching file or device.
Store the caller's stack pointer into the operand of the LD SP,nnnn instruction at 521FH so the overlay exit can restore the caller's stack. Register SP holds the LDOS command-level stack on entry.
Main Loop
The removal loop re-enters here (from 52FFH) to process the next specification with a forced success status, and at 5209H (from 524CH/527BH) to carry a resident-service error into the error handler at 5341H.
521CH - Overlay Exit and Caller Stack Restore
The common exit. It restores the caller's stack pointer saved at entry and returns to the LDOS command level, or aborts to DOS when the system flag requires it.
Load register SP from the operand at 5220H, set at entry to the caller's stack pointer, restoring the caller's stack for the return.
522EH - Process One File Specification
Parses a single file or device specification with the resident @FSPEC service, builds the name for display, and removes it. A logical device (leading asterisk) is handled by the device path; a disk file is opened and then killed through the resident @KILL service, with the Deleting: name line shown for each file.
527DH - Helper: Display the Deleting Line
Displays the Deleting: prefix followed by the name of the file being removed, preserving the caller's DE pointer.
5286H - Remove a Logical Device
Handles a specification that names a logical device rather than a disk file. It locates the matching device control block in the resident device chain, validates that it may be removed, and unlinks it.
Store the stride (register A) into the operand at 52E9H, setting the increment used by the chain-walk instruction below.
ADD the stride (operand at 52E9H, set to 08H above) to register A to index the next control block.
5302H - Helper: Zero an 8-Byte Field
Fills eight bytes at (HL) with zero, used to clear a device control block field before it is rebuilt.
530AH - Helper: Copy a Name Skipping Spaces and the Drive Colon
Copies characters of a file specification into the display buffer, skipping embedded spaces and stopping the drive-suffix scan at the colon, so the reported name is clean.
531FH - Helper: Poll the Keyboard for Pause and BREAK
Polls the resident keyboard flag; when the pause key is active it waits, and it recognises BREAK so a long wildcard removal can be interrupted.
5341H - Error Handler
Raises the resident @ERROR service with the error code in register A and exits with a failure status.
534CH - File Spec Required Message
Displays the File spec required message when the command was entered with no file specification, then exits with a failure status.
5354H - REMOVE Data: Messages
The two message strings used by the REMOVE command: the missing-specification error and the per-file Deleting: prefix.
The File spec required text, carriage-return terminated (0DH), displayed by 534FH when no specification was given.
The Deleting: prefix (with trailing space), displayed at 5281H ahead of each file or device name as it is removed.
Disassembly - Overlay 4 - LIB
5200H - LIB Command: Entry Vectors
Entry of the LIB command overlay. The first two words are jump vectors: the loader enters at 5200H and jumps to the directory display at 5222H. The short routine that follows homes and clears the screen (and optionally routes output) and returns the success status.
5222H - Display the Library A and Library B Command Directories
Prints the Library heading and lists the resident command-name table at 4EBDH in four columns. The table holds every transient command word; bit 6 of each entry's flag byte selects the library, so this routine lists the Library A names first, then relabels the heading to <B> and lists the Library B names.
Store 42H (ASCII B) at (HL)=52D0H, changing the heading from Library <A> to Library <B> for the second pass.
Library Selector
Both passes read the same resident table at 4EBDH; bit 6 of each entry's flag byte (entry+7) chooses the library, so the Library A pass prints the bit-6-clear entries and the Library B pass prints the bit-6-set entries.
52BFH - Helper: Emit a Run of Spaces
Small utility that writes register B spaces to the display through the ROM character output, used to indent and align the command-name columns.
52C7H - LIB Data: Directory Heading
The single carriage-return-terminated string the LIB command prints as the title of the command directory.
The Library <A> directory heading. Its address is loaded into HL at 5222H (and again at 5273H) and printed at the top of the LIB command listing to label the Library A command set serviced by SYS6.
Disassembly - Overlay 5 - DO
5200H - DO Overlay Entry: Parse JCL Filespec, Open Source and Create Compiled File
Entry of the DO command overlay, the Job Control Language processor. It saves the caller's stack, recognises the leading *, = and $ forms, parses the JCL source filespec (applying the default /JCL extension) and opens it, finds an available drive for the compiled output, and creates the SYSTEM/JCL file that the resident keyboard driver will later replay. Register pair HL points at the command tail on entry.
Store the caller's stack pointer into the operand of the LD SP,nnnn at 5305H so the overlay exit can restore the caller's stack. Register SP holds the LDOS command-level stack on entry.
Store the $ character into the quiet-mode flag operand at 52C0H, so the run does not echo each JCL line to the display.
525FH - Command-Tail Scan: Parameters and Keyin Prompt
Scans the remainder of the DO command line for the parameter assignments and the optional keyboard prompt. A left parenthesis introduces a parameter definition; a semicolon prompts the operator for a line of keyboard input that is logged to the compiled file. When the command tail ends (carriage return) it hands over to the JCL compilation pass.
52A5H - Close the Compiled File, Patch @EXIT and Launch the JCL
Reached when compilation finishes. It unwinds any remaining include nesting, closes the compiled SYSTEM/JCL file and, unless quiet mode was requested, reopens it, arms the resident @EXIT vector with the JCL launch stub, and issues the supervisor request that begins replaying the compiled job through the keyboard driver.
Load register A with the quiet-mode flag. This operand at 52C0H holds the $ character when the DO command was prefixed with $ to suppress screen echo, or zero otherwise.
Restore the caller's stack pointer. This operand at 5306H was set from SP at overlay entry (5200H).
5314H - Reuse-Filespec and Resume Entry Setups
Handles the two special command forms. The = form parses a fresh filespec but skips the leading spaces so the previous drive context is reused; the * form resumes an already-active job. The shared helper at 5330H seeds the compiled-output FCB from its template.
533CH - Parameter List Parse and Label/Compile Control
Parses the parenthesised parameter list on the DO command, entering each name=value pair into the symbol table (or capturing a name to search for a matching label). When the parameters are done it locates the requested label in the source and begins the line-by-line compilation pass.
Load register A with the parse-mode flag. This operand at 5343H is zero to define parameters and nonzero when capturing a name to match against a label.
53C0H - Compile One Source Line: Copy with %Hex and #Parameter Escapes
Compiles the current source line at 59D8H into the output line buffer at 5200H. Characters are copied through, but % introduces a two-digit hexadecimal byte, # introduces a #name# parameter substitution, // at the start marks a JCL directive, and @ ends the compilation. A doubled %% or ## is the literal character.
544EH - Nesting Check, Error Prefix, Directive Dispatch, Source Reader and Line Writer
A cluster of compile-time services: 544EH tests whether IF nesting is balanced, 545AH prints the "Line nnnnn --" prefix and the invalid-format message, 546FH dispatches a // directive through the two keyword tables, 549DH reads the next source line and 54CEH writes a compiled line to the output file (skipping output while inside a false IF block).
Load register pair HL with the current source line number. This operand at 545EH is incremented for every line read at 549DH.
Load register pair HL with the message address. This operand at 546AH is normally the Invalid JCL format message (58C4H) but is patched to the Line too long message (5839H) at 54C0H.
Store the Line too long message address (register pair HL) into the operand at 546AH so the error printer at 5469H reports it.
54FAH - Directive Keyword Tables
The two keyword tables the directive dispatcher searches. The block table lists the always-processed directives IF, ELSE and END; the action table lists SET, RESET, ASSIGN, INCLUDE and QUIT, which run only when no enclosing IF is false. Each entry is a space-padded name followed by the two-byte handler address; a zero byte ends each table. This is data, not code.
The IF keyword and the address of its handler at 5543H.
The ELSE keyword and the address of its handler at 556BH.
The END keyword and the address of its handler at 5576H.
The SET keyword and the address of its handler at 55A5H.
The RESET keyword and the address of its handler at 55B4H.
The ASSIGN keyword and the address of its handler at 55C6H.
The INCLUDE keyword and the address of its handler at 55DFH.
The QUIT keyword and the address of its handler at 5614H.
5543H - IF, ELSE, END Handlers and the Condition Evaluator
The block-control directives. IF evaluates its condition (a parameter name, optionally negated with - and combined with &) and pushes a true/false state; ELSE inverts the current state; END pops it. The condition state stack lives at 59AA and above, with 59A8H pointing at the current level.
5620H - Symbol Scanners, Store, Lookup and Table-Compare Engine
The symbol-table machinery. 5620H scans a parameter name and 562BH a value into work buffers; 5667H is the shared token scanner; 56CDH and 56DFH copy the name and value into a table entry; 56EAH looks a name up in the symbol table at 5D00H; 56FBH and 5704H look a directive name up in the keyword tables; and 5716H is the table-compare engine they all share.
Store the remaining count into the operand at 56C9H, tracking how much of the field is still unused for the trailing-space fill.
Store the toggled literal-mode flag into the operand at 567BH read below.
Subtract the label-flag operand at 568EH from register A (patched below to record a label was seen).
Load register A with the unused-count flag at the 56C9H operand; nonzero when no name characters were stored.
5766H - Decimal Formatter, Delimiter/Upper-Case Helpers and Error Dispatcher
The remaining code: 5766H writes a right-justified 5-digit line number, 577FH tests for a space or comma delimiter, 5785H folds a letter to upper case, and 578FH onward reports the JCL errors. The message dispatcher at 5798H uses a chain of DD-prefixed loads so that entering one byte later selects a different message pointer.
Overlapping Code
The rows from 5798H to 57B2H are a seven-way message selector. Falling in at 5798H sets HL to the File spec required message and the following DD-prefixed loads are inert. Entering one byte later, at the address inside each DD-prefixed load, skips the DD prefix so the bytes read as LD HL,nnnn and select a different message: 579CH the nested-INCLUDEs message, 57A0H symbol-string-too-long, 57A4H procedure-not-found, 57A8H too-many-Proc-labels, 57ACH can't-create, 57B0H multiply-defined. All paths fall through to the display at 57B3H.
580DH - Launch Stubs, Filename Template and Error Messages
The data area (ORG 580DH). It holds the launch stubs copied over the resident @EXIT and @ERROR vectors, the SYSTEM/JCL filename template and default extension, the nine error messages, the include-nesting base pointer, the IF-condition state pointer and the "Line nnnnn --" error prefix. This is data, not code.
Copied over the resident @EXIT vector at 402DH (52F9H). It issues RST 28H request 0ADH then 0BDH so that exiting the launched job returns into the JCL launcher.
Copied over the resident @ERROR vector at 4409H (52DAH). It pushes AF then issues RST 28H request 96H (@ERROR) so a JCL error is reported through the standard error path.
The SYSTEM/JCL compiled-file name copied into the job FCB at 5330H. The drive suffix at 5823H is patched with the chosen drive at 524DH. The JCL portion at 581FH also serves as the default extension applied by @FEXT.
Displayed by the error dispatcher entry at 5798H.
Selected by patching the 546AH operand when a source line exceeds 64 characters.
Displayed via the 57A0H entry when a parameter value exceeds 32 characters.
Displayed via the 57A4H entry when a requested label is not present.
Displayed via the 57A8H entry when more than one label marker is seen.
Displayed via the 57ACH entry when the compiled output file cannot be created.
Displayed via the 57B0H entry for a duplicate or undefined parameter.
The default message displayed by the 5469H error printer after the Line nnnnn -- prefix.
Displayed via the 579CH entry when the INCLUDE nesting stack is full.
The top of the saved-FCB nesting stack; initialised to 5908H (empty) and advanced by INCLUDE.
59A8H points at the current condition-state slot (base 59AAH); the byte at 59AAH is the state (zero = active/true, nonzero = output suppressed).
The error-line prefix; the five xxxxx at 59CFH are overwritten with the current line number by the formatter at 5766H before the message is shown.
Disassembly - Overlay 6 - SPOOL
5200H - SPOOL Command Entry and Re-open of an Installed Spooler
Entry of the SPOOL command overlay. It first checks the resident pointer at 4DF0H/4DF1H that records whether a spooler is already installed. If one is installed, its saved parameters are copied into this overlay's work cells and the option table pointer is switched to the reduced keyword set, so an active spooler can only be paused, resumed, cleared or turned off. If no spooler is installed yet, control drops through to the command-level guard.
Store the caller's stack pointer into the operand of the LD SP,nnnn instruction at 5638H, so the overlay exit can restore the caller's stack. Register SP holds the LDOS command-level stack on entry.
Store the resident spooler module base (register pair HL) into the operand of the LD HL,nnnn instruction at 55AEH, which the CLEAR-queue handler uses to reach the module.
Store 5803H (register pair HL) into the operand of the LD DE,nnnn instruction at 52C6H, replacing the full option-table pointer 57E3H so an already-active spooler accepts only the OFF, PAUSE, RESUME and CLEAR keywords.
523FH - Command-Level and Busy-State Guard
Reached only when no spooler is installed. SPOOL may be installed only from LDOS Ready with no user program resident and no busy background task, so this block refuses the command if a program occupies the @EXIT return vector or if the SYS1 busy flag is set.
5259H - Parse the Output Device or Spool Filespec
Determines what the spooler will intercept. The command tail is parsed by the resident @FSPEC service into a local file control block at 57B8H. When no operand or a bare device is given, the default printer device *PR is used; a device operand builds a matching device/SPL spool filename, and a disk filespec is copied to the runtime control block.
Default Printer Device Helper
The four-instruction subroutine at 5278H copies the default device spec into the working FCB.
Copy Drive Suffix
A colon was found; copy the :d drive text onto the end of the spool name.
52C6H - Decode the Option Keywords and Dispatch Sub-commands
The resident @PARAM service scans the command tail against this overlay's keyword table. Each keyword deposits its value into the operand field of an instruction below. The four flag keywords (OFF/N, RESUME/R, PAUSE/P, CLEAR/C) leave an FFH marker that the INC E tests detect, dispatching to the matching sub-command handler; MEM and DISK leave numeric values in cells 538EH and 5356H used by the install path.
Load register pair DE with the OFF/N flag cell at 52D0H, which @PARAM sets to 00FFH when the OFF or N keyword was given (otherwise 0000H).
Load register pair DE with the RESUME/R flag cell at 52D7H, set to 00FFH by @PARAM when the RESUME or R keyword was given.
Load register pair DE with the PAUSE/P flag cell at 52DEH, set to 00FFH by @PARAM when the PAUSE or P keyword was given.
Load register pair DE with the CLEAR/C flag cell at 52E5H, set to 00FFH by @PARAM when the CLEAR or C keyword was given.
52EBH - Reject a Duplicate Install and Locate the Output Driver
No sub-command keyword was given, so this is a request to install the spooler. The routine refuses if a spooler is already active, refuses if the keyboard/device driver (KI/DVR) is not present, then finds the device control block for the output device and follows any route chain to the real driver.
Follow Route Chain
If the located device is routed, walk the link fields to the ultimate device control block.
5337H - Size the Buffer and Pre-allocate the Spool Disk File
Records the computed buffer size, then decides between a memory-only spooler and a disk-backed one. When a spool-to-disk drive was requested the routine creates the /SPL overflow file through @INIT, pre-extends it to the required record count with @POSN/@WRITE, and marks its directory entry so the allocation is retained.
5394H - Reserve High Memory, Build the Spooler Module and Go Operational
The final install stage. It validates the requested size against the top of memory, computes the byte length of the circular spool buffer, lowers HIGH$ to carve the module out of high memory, zero-fills and threads the buffer queue, copies the SPOOL module header, patches the resident despool routine's pointer operands, adds the despool routine as interrupt task slot 9, hooks the KI keyboard-service task (@KITSK at 4300H) so disk-overflow data can be refilled outside interrupt time, and marks the spooler installed and enabled before jumping to the success message.
Build Queue Slot Table
Thread the fixed-size queue slots so each slot links to the next.
Load register pair DE with the slot-count operand at 53EFH, which was set to the record count at 5366H.
Store the control-block address (register pair HL) into the operand at 5865H of the resident queue-write routine.
Store the control-block address (register pair HL) into the operand at 5911H of the resident despool routine.
Store the control-block address (register pair HL) into the operand at 5950H of the resident disk-refill routine.
Store the queue-slot table address (register pair HL) into the operand at 5946H of the resident disk-refill routine.
Load register pair HL with the buffer-size limit; the operand at 5442H/5443H was written at 5337H (LD (5442H),HL), so HL points into the driver/buffer area from which the original driver vector is fetched.
Store the original driver entry (register pair BC) into the operand at 592FH of the resident despool routine so it can still reach the real device.
Store the original driver entry (register pair BC) into the operand at 590AH of the resident despool routine.
Store the saved @KITSK opcode byte (register A) into the operand at 593FH of the resident routine so the previous KI-task handler still runs.
Store the saved @KITSK target (register pair HL) into the operand at 5940H of the resident routine so the prior KI-task handler is preserved.
Store the queue-write entry (register pair HL) into the operand at 592CH of the resident despool routine.
Store that entry address (register pair HL) into the operand at 585FH of the resident queue-write routine.
Store that entry address (register pair HL) into the operand at 589BH of the resident despool routine.
Store that entry address (register pair HL) into the operand at 593DH of the resident despool routine.
Store that entry address (register pair HL) into the operand at 5875H of the resident routine.
Store that entry address (register pair HL) into the operand at 5897H of the resident routine.
Store that entry address (register pair HL) into the operand at 58F9H of the resident routine.
Store that entry address (register pair HL) into the operand at 597AH of the resident routine.
550FH - PAUSE and RESUME Sub-commands
Two small handlers reached when the spooler is already installed. PAUSE clears the despool-enable bit so queued output stops printing; RESUME sets it so printing continues. Each first checks that a spooler is installed and reports the outcome by jumping into the status-message selector.
5539H - OFF: Remove the Spooler and Reclaim Its Memory
Reached by the OFF or N keyword. It marks the spooler uninstalled, restores the original output-driver hook from the resident driver table, removes the despool interrupt task, and if the module still sits at the top of memory hands its space back to HIGH$. It then re-executes a Reset command against the freed device to unlink its driver.
Restore the caller's stack pointer from 5639H, the operand written on entry at 5200H.
55A7H - CLEAR: Empty the Spool Queue
Reached by the CLEAR or C keyword. It reaches into the resident spooler control block, zeroes every queue slot, and resets the queue head, tail and byte-count pointers so any buffered output is discarded while the spooler stays installed.
Load register pair HL with the module base; the operand at 55AFH was set at 521AH when an installed spooler was re-opened.
Zero Queue Slots
Walk the four-byte slots, clearing the first two bytes of each, until a slot whose fourth byte is FFH (the end marker) is reached.
55F1H - Find a Device Control Block by Name
A helper that searches the resident device chains for a control block whose two-character name matches register pair DE. It scans the KI, DO and PR device control blocks starting at 4015H, then the auxiliary JL, SI and SO blocks at 43C0H. It returns register A zero (Z flag) with HL pointing at the block on a match, or error code 08H on exhaustion.
5617H - Status Message Selector and Common Exit
A single tail that displays one of six status messages and returns. The six entry points overlap by design: each begins a three-byte LD IX,nnnn instruction, and a jump that lands one byte in skips the DD prefix so the same bytes decode as LD HL,nnnn, selecting that entry's message. The chosen message is shown through @LOGOT, then the overlay restores the caller's stack and returns, or aborts if it was not entered at command level.
Deliberate Instruction Overlap
On the fall-through at 5617H register pair HL is set to 5664H (SPOOL buffer cleared) and the following LD IX instructions are inert. Jumping to 561BH, 561FH, 5623H, 5627H, 562BH or 562FH skips a DD prefix so the same bytes load HL with 568FH, 5679H, 56F8H, 56BCH, 56A6H or 56D6H instead.
On the fall-through this loads register pair IX (inert). Entered at 561BH it decodes as LD HL,568FH, selecting the message Despooling now resumed.
On the fall-through this loads register pair IX (inert). Entered at 561FH it decodes as LD HL,5679H, selecting the message Despooling now paused.
On the fall-through this loads register pair IX (inert). Entered at 5623H it decodes as LD HL,56F8H, selecting the message Spooler is now operational.
On the fall-through this loads register pair IX (inert). Entered at 5627H it decodes as LD HL,56BCH, selecting the message Spooler is already active.
On the fall-through this loads register pair IX (inert). Entered at 562BH it decodes as LD HL,56A6H, selecting the message Spooler is not active.
On the fall-through this loads register pair IX (inert). Entered at 562FH it decodes as LD HL,56D6H, selecting the message Spooler already active but paused.
Restore the caller's stack pointer; the operand at 5639H was written on entry at 5200H. This is the overlay's common exit.
5647H - Error Reporting and Refusal Messages
The failure tails. A parameter error loads code 2CH; resident-service failures enter with their own code already in register A; both pass through @ERROR. The refusal tail displays one of three messages through @LOGOT using the same DD-prefix overlap trick, then exits with a failure status.
On the fall-through this loads register pair IX (inert). Entered at 5654H it decodes as LD HL,5745H, selecting the message Request exceeds available memory!.
On the fall-through this loads register pair IX (inert). Entered at 5658H it decodes as LD HL,5787H, selecting the message Can't -- Valid only at LDOS Command level!.
5664H - Spooler Status, Outcome and Refusal Messages
The carriage-return-terminated text the handlers display through the resident @LOGOT service at 447BH. The status tail at 5617H and the refusal tail at 5650H select among these by loading the message address into register pair HL; none is a branch target, so the addresses are plain text here.
Shown by the CLEAR handler once the queue has been emptied.
Shown by the PAUSE handler when despooling was running and is now stopped.
Shown by the RESUME handler when despooling was paused and is now running.
Shown by any handler that finds bit 0 of the flag byte at 441FH clear (no spooler installed).
Shown by RESUME or install when despooling was already enabled.
Shown by the PAUSE handler when despooling was already paused.
Shown after a fresh install completes.
Shown by OFF when the module is not at the top of memory and its space cannot be returned to HIGH$ (4049H).
Shown by OFF when the module was at the top and HIGH$ (4049H) has been raised over it.
Shown when the requested buffer is larger than the free high memory.
Shown when bit 3 of the flag byte at 441FH is clear (the KI keyboard device driver is not present).
Shown when SPOOL is invoked with a program resident or a task busy.
The word Reset and a trailing space. The OFF/reclaim path at 5598H appends the device name left in the FCB at 57B8H and the carriage return planted at 57BBH, then re-executes the whole line through the command-execute entry at 4451H to reset the device driver the spooler had hooked.
57D8H - Filename Templates and the Option Keyword Table
Two small filename templates followed by the @PARAM descriptor table the parse stage passes to the resident @PARAM service at 4476H (in DE, from 52C6H). Each 8-byte table entry is a six-character space-padded keyword and a two-byte pointer to the operand cell @PARAM writes when that keyword is present. The reduced table an installed spooler uses begins at the OFF entry (5803H).
Full keyword MEM. @PARAM writes the requested buffer memory size into cell 538EH.
Abbreviation M for MEM; same value cell 538EH.
Full keyword DISK (spool to disk). @PARAM writes the drive number into cell 5356H.
Abbreviation D for DISK; same value cell 5356H.
Full keyword OFF (remove the spooler). @PARAM writes 00FFH into flag cell 52D0H; the INC E test at 52CFH then dispatches to 5539H. First entry of the reduced table an installed spooler uses.
Alias N for OFF; same flag cell 52D0H.
Full keyword PAUSE. @PARAM writes 00FFH into flag cell 52DEH; the INC E test at 52DDH dispatches to 550FH.
Abbreviation P for PAUSE; same flag cell 52DEH.
Full keyword RESUME. @PARAM writes 00FFH into flag cell 52D7H; the INC E test at 52D6H dispatches to 5524H.
Abbreviation R for RESUME; same flag cell 52D7H.
Full keyword CLEAR. @PARAM writes 00FFH into flag cell 52E5H; the INC E test at 52E4H dispatches to 55A7H.
Abbreviation C for CLEAR; same flag cell 52E5H.
5844H - SPOOL Resident Module Header and Descriptor Workspace
The header of the relocatable high-memory module. The install stage copies 016BH bytes from 5844H into the reserved module with the LDIR at 54C9H, so this header and the two routines that follow it run at their high-memory address, not here. The ten bytes at 584EH are the module descriptor scratch IY addresses while the module is being built.
Module chain link field. Patched at 53C7H (LD (5846H),HL) with the module base so the block links into the resident high-memory module chain.
Ten uninitialised bytes (not loaded from the file). Register pair IY addresses this area during the build: +00/+01 module base, +02/+03 reserved ceiling, +04/+05 buffer size, +06/+07 spool-to-disk drive, +08/+09 the module task-entry link.
5858H - Resident Spooler Routine: Capture a Character into the Queue
The first relocatable routine of the module (it runs at its high-memory address after relocation; the addresses shown are the template addresses). This is the spooler half of the two-process design: it stores each captured output character into the circular queue, and when a queue page fills it either triggers the despooler or, for a disk-backed spooler, writes the full page out to the /SPL file through @POSN and @WRITE. Register pair IX addresses the control block at 59AFH; the LD IX operand cells and the CALL targets were patched to their high-memory values by the install stage.
Point register pair IX at the spooler control block; the operand at 5865H was patched to the module's high-memory control block by the install stage.
58F6H - Despool Interrupt Task Entry
The two-byte landing that @ADTSK was given as the module task entry (module+00B2H) at 54F3H. These bytes are not loaded from the file; on each real-time-clock tick execution passes through here and falls into the despool core at 58F8H.
Two reserved bytes (not loaded from the file) forming the module task entry at module+00B2H. On each clock tick execution enters here and falls into the despool core at 58F8H below.
58F8H - Resident Spooler Routine: Despool Interrupt Task and Disk Refill
The despooler half of the module. The despool core is installed as interrupt task slot 9 (via @ADTSK at 54F3H) and, on each real-time-clock tick, sends one queued character to the printer through the saved printer driver. Because a sector transfer cannot run inside the interrupt, disk-backed data is refilled by the routine at 5942H, which is reached from the @KITSK keyboard hook on each keyboard poll. As above these run at the module's high-memory address; the LD IX operands and the CALL 0000H vectors were patched by the install stage.
GOSUB the saved printer driver; the operand at 590AH was patched by the install stage with the original PRDCB$ driver vector. It returns NZ if the printer is not ready.
Point register pair IX at the control block; the operand at 5911H was patched to the high-memory control block.
Load register pair IX from cell 5907H, patched by the install stage with the device driver-table pointer.
GOSUB the original device driver to print the character in register C; the operand at 592FH was patched with the saved driver entry.
Three template bytes overwritten at 5459H and 545CH with the saved @KITSK opcode (from 4300H) and target (from 4301H); at run time this is the JP that chains the previous keyboard-service handler after the spooler's.
Point register pair IX at the control block; the operand at 5950H was patched to the high-memory control block.
59AFH - Spooler Control Block, Queue Image and Module End
The 44-byte spooler control block and queue image the install stage assembles here (at 59AFH) before copying it into the module with the LDIR at 542DH. It is not loaded from the file; its fields are the queue write pointer (+20/+21), despool read pointer (+22/+23), slot-table pointer (+24/+25), queue head (+26/+27), disk read chain (+28/+29) and saved-head (+2A/+2B) that the two routines above index through register pair IX. The two loaded bytes at 59D9H close the module.
Forty-two bytes of spooler control block and queue-slot workspace built by the install stage (the pointer fields at 59CFH-59D7H are written at 53D7H-541AH; the disk-active flag sits at 59D2H). Copied into the high-memory module by the LDIR at 542DH.
Disassembly - Overlay 7 - COPY/APPEND
5200H - COPY / APPEND Overlay Entry Dispatch
First byte of Library A command overlay 7, loaded at 5200H by the resident overlay loader at 4BF5H when the resident RST 28H dispatcher (4BCDH) decodes request code 88H with the command number for COPY. The overlay carries two command bodies that share one exit and one common subroutine library: the COPY body at 52B1H and the APPEND body at 5203H. The first byte jumps straight to the COPY body, stepping over the APPEND body that follows.
5203H - APPEND Command Entry, Spec Parse and Setup
Entry of the APPEND command. APPEND concatenates the source file onto the end of an existing destination file. It saves the caller stack, retargets the progress banner to "Appending: ", parses the source and destination file specifications, parses the APPEND option keywords, positions the destination to its current end of file, and then joins the shared copy engine.
Store the caller stack pointer (register SP, holding the LDOS command-level stack on entry) into the operand of the LD SP,nnnn instruction at 5489H, so the overlay exit at 5489H can restore the caller stack. The two-byte operand cell is 548AH.
Store 5845H (register pair BC, the "Appending: " literal address) into the operand cell 56A4H, which is the address operand of the LD HL,nnnn instruction at 56A3H inside the banner-display routine 56A1H. This makes the shared banner routine print "Appending: " for APPEND instead of its default "Copying: " (583BH).
Store the destination directory flag byte (register A, just returned by 56BDH) into the operand cell 5260H, which is the immediate operand of the LD B,nn instruction at 525FH. The XOR B at 5261H later re-reads this saved byte to detect whether the destination attributes changed.
Load register B with the destination directory flag byte that was patched into the operand cell 5260H at 5247H. The 00H shown is the initial listing value; at run time B holds the destination file's attribute byte.
Load register pair DE from the operand cell 5269H. The 0000H shown is the listing value; the STRIP option, when supplied, patches this operand so DE carries a non-zero record count. It selects whether the file's final partial sector is trimmed.
52B1H - COPY Command Entry, Spec Parse and Drive Setup
Entry of the COPY command, reached from the overlay's first byte at 5200H. COPY duplicates a source file or device to a destination file or device. It saves the caller stack, parses the source and destination specifications and the COPY option keywords, guards against running inside a JCL DO stream, extracts the destination drive digit into the disk-swap prompt strings, and prepares the directory information used to detect same-disk copies.
Store the caller stack pointer (register SP, the LDOS command-level stack on entry) into the operand cell 548AH, the operand of the LD SP,nnnn exit instruction at 5489H, so the overlay can restore the caller stack when it finishes.
Load register pair DE from the operand cell 52D4H. The 0000H shown is the listing value; the X option (single-drive copy with disk-swap prompts) patches this operand non-zero. The low byte 52D4H is later read as the single-drive flag by the prompt routines at 570CH, 571EH and 5740H.
LOOP BACK to 52F8H to examine the next specification character while searching for the ':' drive delimiter.
Store the ASCII drive digit (register A) into 5938H, the drive-number position inside the "Insert SOURCE disk in drive :0..." prompt string at 5919H, so the prompt names the correct drive.
Store the same ASCII drive digit (register A) into 5971H, the drive-number position inside the "Insert DESTINATION disk in drive :0..." prompt string at 594DH.
533DH - Disk Copy Preparation: Open, LRL Check, Same-Disk Guard
Common disk-to-disk preparation reached by both the ordinary and single-drive COPY paths. It opens the source, records the source directory attributes and logical record length, prompts for and reads the destination disk's identity, guards against copying a disk onto itself, pre-extends the destination to the source length, and rewinds the source ready for the block-copy engine.
53DCH - Block Copy Engine: Full-Memory Read/Write Loop
The high-speed disk-to-disk copy loop shared by COPY and APPEND. It reads the source file into the large buffer that runs from 5B00H up to HIGH$ (as many 256-byte records as fit), then writes that whole block to the destination, and repeats until the source reaches end of file. Filling all free memory each pass minimises the number of disk-swap prompts on a single-drive copy.
GOSUB to 571EH to issue the "Insert SOURCE disk" prompt (a no-op unless the single-drive flag at 52D4H is set), then verify the mounted disk before each read pass.
Store the current buffer address (register pair HL) into the source FCB+03H buffer-pointer field at 5989H, so the next @READ deposits its 256-byte record at this address.
Compare register A (the current buffer page) against the buffer ceiling. The 60H shown is the default; the operand at 53FBH is patched by 54B8H to the high byte of HIGH$ (4049H), so the read buffer extends across all free memory from 5B00H up to HIGH$. The Z flag is set when the buffer is full.
If the NZ flag is set (buffer not yet full), LOOP BACK to 53E2H to read another record into the next buffer slot.
Store the current buffer address (register pair HL) into the destination FCB+03H buffer-pointer field at 59DDH, so the next @WRITE takes its 256-byte record from this address.
Compare register A (the current buffer page) against the buffer ceiling. The 60H shown is the default; the operand at 5413H is patched by 54B8H to the high byte of HIGH$, so the whole read buffer is written back. The Z flag is set when the block has been fully written.
If the NZ flag is set (more records remain in the block), LOOP BACK to 5404H to write the next record.
5418H - End of File: Final Block, Directory EOF Update and Exit
Reached when the source read reports end of file. It flushes the last partial buffer to the destination, copies the source's exact end-of-file offset into the destination directory record, writes that record back, then closes the file and falls into the common overlay exit that restores the caller stack and returns (or aborts if not at command level).
Load register pair DE from the operand cell 544BH/544CH (cleared to 0000H at 5208H/520BH by APPEND, left as 0FFFFH otherwise). It carries the update-timestamp value the CLONE option may patch; the test below decides whether to stamp the directory record.
Restore the caller stack pointer. The 0000H shown is the listing value; the operand cell 548AH was patched at 5203H/52B1H with the caller SP, so register SP is reloaded with the LDOS command-level stack. The DD-overlap-style shared error tail at 5835H also jumps here with register pair HL non-zero to mark an error exit.
5498H - Final Partial Block Flush Helper
Called at end of file to write out whatever records were read into the block buffer during the last, incomplete read pass. Register H on entry holds the buffer page one past the last record read; the routine writes 5B00H up to that page to the destination.
Compare register A (the buffer page) against the buffer ceiling. The 60H shown is the default; the operand at 549DH is patched by 54B8H to the high byte of HIGH$. If the buffer is exactly full the block was already written by the main loop and the Z flag is set.
Store the current buffer address (register pair HL) into the destination FCB+03H buffer-pointer field at 59DDH so @WRITE takes its record from here.
If the NZ flag is set (records remain), LOOP BACK to 54A6H to write the next record of the final block.
54B8H - Busy-Flag Check and Copy-Buffer Ceiling Patch
Called at the start of both command bodies. Unless a background task marks the system busy, it computes the top page of free memory from HIGH$ and patches that ceiling into the three copy-loop limit comparisons, so the block-copy buffer stretches from 5B00H up to HIGH$. It then clears the pause/scroll bits in KFLAG$.
Store the ceiling page (register A) into the operand cell 53FBH, the compare value of the CP 60H at 53FAH in the block-read loop, so reads fill memory up to HIGH$.
Store the ceiling page (register A) into the operand cell 5413H, the compare value of the CP 60H at 5412H in the block-write loop, so the whole block is written back.
Store the ceiling page (register A) into the operand cell 549DH, the compare value of the CP 60H at 549CH in the final-block flush helper, so the partial-block test uses the same ceiling.
54D4H - Destination Pre-Extend Helper
Given a target record count in register pair BC, positions the destination file to record BC-1 and writes one E5H-filled record there. This forces the file system to allocate all the disk space the copy will need before any data is written, so a full disk is detected up front rather than after a partial copy.
54F4H - Character Copy Loop (Device and Byte-Serial Transfers)
Reached when either the source or destination is a * device, so fixed-record block copying cannot be used. It opens both endpoints, shows the progress banner, then transfers one byte at a time from source to destination, echoing to the display when the ECHO option is active and checking for BREAK, until end of file.
Point register pair DE at the source FCB at 5986H to fetch the next byte.
If the Z flag is set (no byte yet), LOOP BACK to 5533H to check BREAK and poll the device again.
Load register pair DE from the operand cell 5545H. The 0000H shown is the default; the ECHO option patches the high byte to 0FFH so that INC D below sets the Z flag and each transferred byte is echoed to the screen.
5564H - Command-Tail Token Copy and Uppercase
Copies a name token from the command line at (HL) into the buffer at (DE), folding lowercase letters to uppercase and stopping at a carriage return, space or open parenthesis. Entry 5564H additionally carriage-return-terminates the copied token; it is used to complete a defaulted destination specification.
Advance the source pointer (register pair HL) past a leading space while skipping whitespace before the token.
If the Z flag is set (a leading space), LOOP BACK to 556BH to skip it and examine the next character.
Load register A with the next token character at (HL).
DECrement register B (the remaining length) and LOOP BACK to 5577H if not zero, copying the next character until 32 have been copied.
558EH - Destination Filespec Validation
Confirms the destination specification at 59DAH is a usable file name: it rejects an empty destination or one that begins with a digit (reporting "Destination spec required"), then scans the specification for its '/' extension and '.' delimiters, inserting a drive prefix where needed via the helper below.
55B6H - Delimiter Scan and Character Insert Helpers
Two cooperating helpers used by the validator above. 55B7H scans the specification for the delimiter character in register B, and 55DEH/55EAH shift characters forward to insert a drive digit at the correct spot so a specification given as name:d becomes the canonical form.
Advance the scan pointer (register pair DE) to the next specification character.
If the CARRY flag is set (a digit), LOOP BACK to 55B6H to scan the next character.
Load register A with the character at the reference pointer (HL).
If the NZ flag is set (not yet the delimiter), LOOP BACK to 55CCH to scan the next character.
Load register C with the character currently at (HL) so it can be displaced by the inserted character.
If the NZ flag is set (more characters to shift), LOOP BACK to 55EDH to displace the next character.
55FEH - Build Working Filespec and Open File
Copies the specification at (DE) into the working area 59A6H, folding in the extension, appending a ':' drive placeholder (whose position it records for the drive-digit patch), then opens the file with @OPEN. On a successful open it verifies the drive and the file's protection level, refusing (error 25 "file access denied") a file whose access is too restricted to copy. Register A on entry is the open-mode byte; register B is the record length.
Load register A with the current specification character at (DE).
If the NZ flag is set (still within the name), LOOP BACK to 5604H to copy the next character.
Store the drive-digit slot address (register pair HL) into the operand cell 5687H, the operand of the LD (nnnn),A instruction at 5686H inside 5679H, so that routine can later poke the actual drive digit into this specification.
5679H - Drive-Digit Patch, Spec Display Copy and Progress Banner
Three display-side helpers. 5679H pokes an opened file's real drive number into the working specification. 568AH and 5690H copy that specification into the source or destination display buffer. 56A1H prints the progress banner "Copying: source to destination" (or "Appending:").
Store the ASCII drive digit (register A) into the specification drive slot. The 0000H shown is the listing value; the operand cell 5687H was patched at 562AH with the drive-slot address in the working specification at 59A6H, so the digit lands in the displayed spec.
Point register pair HL at 583BH, the "Copying: " literal. The address operand at 56A4H is patched to 5845H ("Appending: ") by the APPEND entry, so this call prints the correct verb.
56BDH - Directory Attribute and Date-Field Readers
Two helpers that index the file's directory entry inside the resident sector buffer at 4200H using the directory position in FCB+07H. 56BDH returns the entry's attribute byte; 56CCH copies the entry's date and access fields into the 5A1EH template used to stamp the copied file.
56E9H - BREAK/Pause Check and Single-Drive Disk-Swap Prompts
56E9H handles the keyboard during a transfer: it honours a PAUSE and reports BREAK. 570CH, 571EH and 5740H are the three disk-swap prompts, each a no-op unless the X single-drive flag at 52D4H is set: they display "Insert SYSTEM / SOURCE / DESTINATION disk" and, for the source and destination, re-read the mounted disk's identity and re-prompt if the wrong disk was inserted.
PAUSE is active. Reload register A with KFLAG$ at 4423H to re-test BREAK while paused.
If the Z flag is set (the hold key), LOOP BACK to 56FAH to remain paused.
Load register A with the current drive number. The 00H shown is the listing value; the immediate operand cell is 5712H, which also holds the copy's drive number written at 5309H, so register A receives that drive number.
Save register pair HL on the stack across the source-disk prompt and verification.
If the NZ flag is set (the wrong disk was inserted), LOOP BACK to 571EH to prompt for the SOURCE disk again.
Save register pair HL on the stack across the destination-disk prompt and verification.
If the NZ flag is set (the wrong disk was inserted), LOOP BACK to 5740H to prompt for the DESTINATION disk again.
5762H - Identity Compare, Paged Prompt Wait, KFLAG Clear and Abort
5762H compares B bytes of two disk identities. 576EH displays a swap prompt and flashes it while waiting for a keypress, honouring PAUSE and aborting on BREAK. 57B0H clears the KFLAG$ control bits, and 57B9H reports "Transfer aborted" before aborting to @ABORT.
Load register A with the current byte of the expected identity at (DE).
DECrement register B (remaining bytes) and LOOP BACK to 5762H if not zero, comparing the next identity byte.
GOSUB to 57B0H to clear the KFLAG$ bits before each display of the flashing prompt.
LOOP BACK to 577EH to redisplay and re-flash the prompt until a key is pressed.
Load register A with KFLAG$ at 4423H to test BREAK and PAUSE while the timing loop runs.
If the NZ flag is set (time remaining), LOOP BACK to 5794H to keep scanning during this flash phase.
GOSUB to the ROM keyboard-scan routine at 002BH to read the pressed key into register A.
If the NZ flag is set (key still held), LOOP BACK to 57A5H to wait for release.
57C5H - Resident Checkpoints, Device Test, Dating Bit, GAT Read and Open Entries
Small utilities used across the overlay: three RST 28H overlay pre-loads issued before a single-drive copy starts swapping diskettes; a test for a device endpoint; the per-drive extended-dating bit test (self-modified into a BIT instruction); the GAT-sector read; and the four entry points that set the open mode before calling the filespec-build-and-open routine. The three pre-loads are SEPARATE two-instruction stubs packed nose to tail, not a sequence: 531FH calls 57C5H, 53C3H calls 57C8H and 5424H calls 57CBH, and because the dispatcher at 4BCDH discards the address the RST pushed, each stub returns to the caller of that stub and needs no RET of its own.
Add 08H to register A. Each 08H step advances the bit-select field of the BIT opcode by one bit position.
DECrement register B and LOOP BACK to 57E0H until the opcode selects the drive's bit; register A ends holding CB-prefix opcode 47H+8n = BIT n,A for drive n.
Store the constructed opcode (register A) into the operand cell 57EBH, the second byte of the CB-prefixed instruction at 57EAH, turning it into BIT drive,A so it tests this drive's bit.
Test the drive's bit in register A (the dating flags). The listing shows the unpatched CB 00; at run time the operand at 57EBH was rewritten to BIT drive,A, so the Z flag reflects whether this drive uses extended dating.
5810H - Error Reporting and Overlapped Message Selector
The common failure tail. 5810H reports a numeric error code through @ERROR; 5816H is an alternate entry for the fixed "parameter error" code. 581FH-5831H is an overlapped block of LD HL,message instructions: each of the five error entry points lands on a different LD HL, while the interleaved DD prefixes turn the non-selected loads into harmless LD IX instructions, so entering at a given address selects exactly one message before the shared @LOGOT display.
As reached by fall-through this loads register pair BC with 2C3EH (harmless). Entered instead at 5816H, the two bytes 3E 2C read as LD A,2CH, placing error code 2CH (44 decimal, "parameter error") into register A; the JP NZ,5816H parameter-error exits use this entry.
The five instructions from 581FH to 5831H form one overlapped message-selector table. Each error exit jumps to a different address within it; the byte landed on begins an LD HL,message instruction, and any DD prefixes ahead of it are consumed as the opcode of a do-nothing LD IX. All paths converge on the @LOGOT display at 5832H.
583BH - Message and Prompt String Data
The overlay's text: the two progress-banner verbs (03H-terminated for @DSPLY), the error and status messages (0DH-terminated for @LOGOT), and the three single-drive disk-swap prompts (framed by video control codes 1DH/1EH, 03H-terminated, with the drive digit at 5938H and 5971H patched at run time).
5986H - Work Areas, Buffers and Reserved Cells
The overlay's uninitialised RAM work areas (the two file control blocks, the specification build and display buffers, and the disk-identity and directory-stamp scratch), interrupted only by the initialised four-byte " to " banner joiner at 59C6H. These addresses hold no loaded bytes; the contents shown are established at run time.
| Address Range | Purpose |
|---|---|
| 5986H-59A5H 32 bytes | Source File Control Block. +00 flags (bit7 = disk file); +03/04 record-buffer pointer (5989H, set before each @READ); +06 drive (598CH); +07 directory position (598DH); +08 EOF byte offset (598EH); +0C/0D ending record number (5992H). |
| 59A6H-59B5H 16 bytes | Working filespec assembly area built by 55FEH as NAME/EXT:d terminated by 03H; the drive-digit slot is recorded at 5687H for the 5679H patch. |
| 59B6H-59C5H 16 bytes | Source specification display buffer, printed by the banner after the verb. |
| 59C6H-59C9H 4 bytes | Initialised " to " banner joiner (loaded data); it runs on into the adjacent destination display buffer so one @DSPLY prints " to <dest>". |
| 59CAH-59D9H 16 bytes | Destination specification display buffer, printed by the banner after " to ". |
| 59DAH-59F9H 32 bytes | Destination File Control Block. +03 record-buffer pointer (59DDH); +06 drive (59E0H); +08 EOF byte offset (59E2H); +09 record-position flag (59E3H); +0C/0D ending record number (59E6H). |
| 59FAH-5A0BH 18 bytes | Saved SOURCE disk identity (name and date), captured from the GAT for the single-drive same-disk guard. |
| 5A0CH-5A1DH 18 bytes | Saved DESTINATION disk identity (name and date). |
| 5A1EH-5A24H 7 bytes | CLONE date/attribute template filled from the source directory entry by 56CCH and stamped into the destination directory record at 5459H/5462H. |
5A25H - COPY and APPEND Option Keyword Table
One @PARAM keyword table shared by the two commands. COPY parses it from the top (5A25H), accepting LRL, CLONE and X (and the single-letter abbreviations); APPEND parses the same table from 5A4DH, so it accepts only STRIP and ECHO. Each entry is a six-character space-padded keyword followed by the two-byte address of the self-modified operand cell that receives the value; a 00H byte at 5A6DH terminates.
Disassembly - Overlay 8 - LIST
5200H - Overlay Entry: Reset Keyboard Flags and Scan the Command Tail for Parameters
Entry of the LIST command overlay (Library A command 8, dispatched by RST 28H code 88H). It saves the caller's stack pointer for the exit, clears the resident keyboard status flags, then scans the command line for the parameter-list open parenthesis so any options can be parsed before the file is opened.
Store the caller's stack pointer (register SP, which on entry holds the LDOS command-level stack) into the operand of the LD SP,nnnn instruction at 538AH, so the overlay exit can restore the caller's stack.
Load register A with the command-line character at (HL) while scanning for the parameter-list open parenthesis.
5214H - Parse the Parameter List and Apply the Compressed-Display Toggle
The parameter list is parsed by the resident @PARAM service against the local keyword table at 55C2H. Each supplied value is stored by @PARAM into a self-modified operand cell inside the overlay. This block then resolves the C (compressed hexadecimal display) switch, whose default is on.
522FH - Parse the Filespec, Apply the Default /TXT Extension and Open the File
The filespec is parsed into a File Control Block, a device specification is rejected, a backup copy of the FCB is taken, the default extension /TXT is applied and the file is opened. If /TXT is not found the original blank-extension specification is restored and the open is retried, matching the documented search order.
Load register A with the filespec character at (HL) while skipping leading blanks.
527EH - Establish the Logical Record Length and the TAB Stop
With the file open, IX is pointed at the FCB. The logical record length is taken from the LRL parameter if given, otherwise from the file's directory entry, and written into the FCB. The TAB stop is defaulted to 8 and range-checked to 1-32.
52B6H - Select the Output Device and the HEX or ASCII Listing Mode
The P switch chooses the printer or video Device Control Block and forces non-stop mode for the printer. The HEX switch then routes to the hexadecimal listing; otherwise the ASCII paging constants are set up (15 lines per page in this DOS 5 build) and self-modifying patches disable the screen clear used only by the hexadecimal pager.
52EFH - ASCII Listing: Skip Forward to the Starting LINE
When the LINE parameter asks the listing to start beyond the first line, the file is read a byte at a time and carriage returns are counted until the requested number of lines has been skipped.
GOSUB to the ROM byte-input routine at 0013H to read the next file byte (FCB in register pair DE) into register A.
5309H - ASCII Display Loop: Line Numbering, Tab Expansion and Character Output
The main ASCII loop. At the head of each line the five-digit line number is formatted and, when NUM is active, sent to the output device. Each character is then optionally high-bit stripped (unless ASCII8 was given), tab characters are expanded to the next stop, and the character is displayed. A carriage return returns to the line head; end of file finishes the listing.
Point register pair DE at 564CH, the open file's FCB, to read the first character of the next line.
Character Processing Loop
Entered at 5331H for the second and later characters of a line (from 5375H), and fallen into at 532FH for the first character. The rotate that follows works with the high-bit test to strip or keep bit 7 of the character.
Overlap
The fall-through path executes SRL A at 5339H (stripping the high bit) and then LD E,0FH here at 533BH. When ASCII8 is active, the jump at 5337H (JR NZ,533CH) instead lands on the operand byte 0FH at 533CH, which executes as RRCA and undoes the earlier RLCA at 5331H, keeping all eight bits of the character. The anchor for 533CH resolves to this 533BH row.
SUBtract the tab width (register C) from the column (register A) to reduce it modulo the tab width.
Load register A with 20H, an ASCII space, for the tab expansion.
5387H - Overlay Exit and Command-Level Check
Common exit. Register pair HL carries the status word (0000H for success, 0FFFFH for an error). The caller's stack is restored from the operand patched at entry. A clean status returns to the RST 28H dispatcher; an error status aborts the job through @ABORT when not at the LDOS command level.
Restore the caller's stack pointer from the operand at 538BH, patched at entry (5200H) with the caller's SP; register SP now addresses the LDOS command-level stack.
5399H - HEX Listing: Position to the Starting Record and Read a 16-Byte Line
The hexadecimal listing. The file is positioned to the REC starting record, then for each record the header aaaa:bb = is built and displayed and up to 16 raw bytes are read into the line buffer, each emitted as two hexadecimal digits with the grouping spacing selected by the C switch.
Clear register A to zero to reset the intra-record byte offset for a new record line.
Load register A with the current byte offset from the self-modified operand at 53BCH for the header bb field.
Point register pair DE at 564CH, the open file's FCB, for the next byte read.
5406H - HEX Listing: Format the ASCII Sidebar of the Record Line
After the hexadecimal bytes of a line are emitted, the matching ASCII sidebar is laid out. Three layouts are supported: compressed video (the DOS 5 default), separate two-line video (C=OFF), and printer. Each pads the sidebar so the characters align under their hexadecimal columns, showing a period for any non-displayable byte.
Load register A with the next raw byte from the line buffer at (HL).
Load register A with the next raw byte from the line buffer at (HL).
547DH - HEX Listing: Close the Record Line and Advance to the Next Record
The record line is closed, the terminating status is checked, a page-pause test is run, and the loop either continues the current record (if it holds more than sixteen bytes) or advances to the next record.
54A8H - Output Helpers: Space, Printable-Character Filter and Hexadecimal Digit
Small shared routines used by both listing modes: emit a single space, convert a raw byte to a printable ASCII character (period for non-printables) and emit it, and print a byte as two hexadecimal ASCII digits using the DAA nibble-conversion method.
Compare the raw byte (register A) against 20H (space); bytes below 20H are non-printable control codes.
Save the byte (register AF) whose two hexadecimal digits will be printed.
54C9H - Character Output with Column Tracking and End-of-Line Paging
The single point through which every displayed character passes. It sends the character to the selected device, tracks the 64-column position, and at end of line runs the page-pause logic: printer output never pauses, non-stop mode never pauses, otherwise the page line counter is decremented and a full page waits for a key.
Load register pair DE with the output Device Control Block address from the operand at 54CAH, set at 52CFH to the video DCB (401DH) or printer DCB (4025H).
Overlap
The ordinary-character path at 54E4H (JR NZ,54E7H) jumps into the 00H operand byte of the LD (HL),00H instruction here, executing it as a NOP so the column counter is left unchanged; only a genuine end-of-line character falls into the counter reset at 54E6H. The anchor for 54E7H resolves to this 54E6H row.
Push the continuation address (register pair DE); in ASCII mode this PUSH is patched to a NOP at 52DCH, paired with the NOP at 551EH.
Load register A with the current page line-countdown from the operand at 54FCH (initialised to 15 for ASCII, 16 for HEX).
GOSUB to the ROM clear-line routine at 01C9H for the next page; in ASCII mode the opcode here is patched at 52ECH to LD DE,01C9H, suppressing the clear.
Discard the pushed continuation address (popped into register pair AF); in ASCII mode this POP is patched to a NOP at 52DFH, paired with the NOP at 54F4H.
5525H - Pause and BREAK Key Handling and the Keyboard-Flag Reset
Checks the resident keyboard flags for a pause or BREAK request and, while paused, polls the keyboard until released. The tail of this block (entered at 5548H, also called at entry) clears the resident keyboard status flags.
Load register A from the resident system flag byte SFLAG$ at 430FH.
Paused. Load register A from KFLAG$ at 4423H to re-poll the flags.
Reset Keyboard Flags
This tail is also the routine called at 5204H during entry: it clears the low three status bits of KFLAG$ so a stale BREAK or pause from a previous command does not affect the listing.
5559H - Five-Digit Decimal Formatter
Renders the value in register pair HL as a right-justified, blank-filled five-digit decimal number into the caller-supplied field, using the resident @DIV service to extract each digit.
Load register B with 05H, the width of the decimal field (five digits) to be blank-filled.
Store a space (register A) into the field at (DE).
Load register A with 0AH (10), the divisor for extracting the next decimal digit.
5572H - Advance an ASCII Decimal Counter Field
Increments a decimal counter held as ASCII digits in memory, propagating the carry leftward. Entered at 5572H it steps over the five-digit line-number field; entered at 5573H it steps over the four-digit record-number field.
Entered at 5572H for the five-digit line-number field: INCrement register pair HL toward the least-significant digit (four increments in total).
Load register A with the current digit character at (HL).
5583H - Error Exits
The error paths. A parameter error is reported through @ERROR; a bad or missing filespec displays the File spec required message through @LOGOT. All paths load the error status and jump to the common exit.
Load register A with 2CH (error code 44, parameter error).
Point register pair HL at 5598H, the File spec required message text.
5598H - Data: Message, Display Templates and the Default Extension
The non-executable data at the tail of the overlay: the error message shown for a bad filespec, the line-number and hexadecimal-header display templates that the code fills in and sends to the output device, and the default /TXT extension applied when the filespec omits one.
55C2H - Data: @PARAM Keyword Descriptor Table
The parameter table consulted by @PARAM at 5217H. Each entry is eight bytes: a six-character space-padded keyword followed by the two-byte (low, high) address of the self-modified operand cell that receives the parsed value. Switch keywords deposit an on/off flag; value keywords deposit a number. A 00H byte terminates the table.
Disassembly - Overlay 9 - RENAME
5200H - RENAME Overlay Entry: Parse filespec1
Entry of the RENAME command overlay (Library A command 9, dispatched by RST 28H code 88H). It saves the caller's stack pointer for the exit and parses the first file specification (the existing file) into the filespec1 buffer with the resident @FSPEC service, rejecting a device specification.
Store the caller's stack pointer (register SP, which on entry holds the LDOS command-level stack) into the operand of the LD SP,nnnn instruction at 52C1H, so the overlay exit can restore the caller's stack.
5213H - Parse filespec2 and Apply the Dynamic Defaults
The second specification (the new name) is parsed into the filespec2 buffer. Where filespec2 omits the filename, extension or password, those parts default to filespec1's, matching the manual's dynamic-default rule (for example RENAME TEST/DAT TO REAL yields REAL/DAT). An empty filespec2 raises "Rename it to what?".
5235H - Open filespec1 and Check Access
filespec1 is opened to confirm it exists and to obtain its directory location, and its access level is checked so a protected file cannot be renamed.
5247H - Require filespec2 to Match the filespec1 Drive
The drive of filespec2 must equal that of filespec1. The buffer is scanned for a drivespec: if present it is compared, and a mismatch aborts; if absent, filespec1's drive is inserted.
Load register A with the next filespec2 character at (HL) and advance the pointer.
5272H - Reject a Duplicate: filespec2 Must Not Already Exist
filespec2 is opened; it is expected to fail with file-not-found. If it opens successfully the new name already exists and "Duplicate file name!" is issued.
5288H - Rewrite the Directory Entry with the New Name
The directory record of filespec1 is read, its eleven-byte name and extension field is overwritten with the new name, and the record is written back. The new name is taken from 51EAH, the packed name work area belonging to SYS2/SYS: the duplicate-check open at 5279H loaded SYS2/SYS at 4E00H and left filespec2's name packed there when it failed to find the file, which is exactly the form the directory field needs.
52A7H - Update the Hash Index Table
Renaming changes the file's name hash, so its Hash Index Table byte must be changed to match. RENAME does that work itself, using two entry points in the SYS2/SYS image that is still resident beneath this overlay after the duplicate-check open: 51BDH reads the Hash Index Table sector into the shared buffer at 4200H and 51BEH writes it back. The new hash byte in between comes from the filename-hash service, which is reached as RST 28H request code 0D4H through the trampoline at 52D0H.
52BEH - Overlay Exit and Command-Level Check
Common exit. Register pair HL carries the status word (0000H success, 0FFFFH error). The caller's stack is restored from the operand patched at entry; a clean status returns to the RST 28H dispatcher, an error aborts through @ABORT when not at the LDOS command level.
Restore the caller's stack pointer from the operand at 52C2H, patched at entry (5200H) with the caller's SP; register SP now addresses the LDOS command-level stack.
52D0H - Filename-Hash Service Trampoline (RST 28H Code 0D4H)
A three-byte trampoline that loads the rename-service request code and issues RST 28H. The resident dispatcher discards the RST's own return address, so control resumes at the caller of this routine.
RST 28H Return Convention
The resident RST 28H dispatcher discards the return address the RST instruction pushes, so after the 0D4H service completes control returns to the instruction after CALL 52D0H, not to 52D3H.
52D3H - Helper: Copy a Blank-Delimited Word
Copies the next blank-delimited word from the source at (HL) into the buffer at (DE), folding lowercase letters to uppercase and stopping at a carriage return or an open parenthesis. Used to absorb the optional TO word when @FSPEC could not parse filespec2 directly.
Load register A with the source character at (HL).
Load register A with the current source character at (HL).
52F0H - Helper: Apply filespec1 Defaults to filespec2
Drives the dynamic-default merge: if filespec2 has no filename it takes filespec1's, and the extension (introduced by /) and password (introduced by .) each default to filespec1's when filespec2 omits them.
5303H - Helper: Scan filespec2 Past a Field Delimiter
Advances through filespec2 while the characters are letters or digits, looking for the delimiter passed in register B; if the delimiter is found it is stepped over, otherwise control passes to the field-locator for filespec1.
Load register A with the current filespec2 character at (DE).
5318H - Helper: Locate the Matching Field in filespec1
Scans filespec1 for the same delimiter (register B); if found, the field is spliced into filespec2 so the default is applied.
Load register A with the current filespec1 character at (HL) and advance.
532BH - Helper: Splice a filespec1 Field into filespec2
Copies the filename or default field character by character from filespec1 into filespec2, shifting the existing filespec2 characters to make room.
Load register C with the filespec2 character at (HL) that is about to be displaced.
534BH - Error Exits
The error paths. A drive mismatch, an access failure and the various service errors are reported through @ERROR; the three message paths ("File spec required!", "Rename it to what?", "Duplicate file name!") are displayed through @LOGOT. All load the error status and jump to the common exit.
Overlap
By fall-through this loads register pair IX with 537CH (unused). Entered at 5358H (from 5226H) the DD prefix is skipped and the bytes 21 7C 53 read as LD HL,537CH, selecting the "Rename it to what?" message. The anchor for 5358H resolves to this 5357H row.
Overlap
By fall-through this loads register pair IX with 538FH (unused). Entered at 535CH (from 527CH) the DD prefix is skipped and the bytes 21 8F 53 read as LD HL,538FH, selecting the "Duplicate file name!" message. The anchor for 535CH resolves to this 535BH row.
5368H - Data: RENAME Messages
The three carriage-return-terminated messages displayed through @LOGOT by the error paths. The disassembler renders this region as bogus instructions; it is decoded here straight from the SYS6.SYS binary.
Disassembly - Overlay 10 - SYSTEM (status/drives)
5200H - Overlay Entry, @PARAM Option Parse and Section Dispatch
Entry of the SYSTEM command overlay, which reports the system configuration. It saves the caller's stack, parses the keyword options with the resident @PARAM service (DRIVES/D, BYTEIO/B, STATUS/S, plus the N nonstop and P printer modifiers), clears the keyboard flags, and dispatches to whichever of the three display sections were requested.
Store the caller's stack pointer (register SP, which on entry holds the LDOS command-level stack) into the operand of the LD SP,nnnn instruction at 5519H, so the overlay exit at 5519H can restore this exact stack.
Load register pair HL with the DRIVES-option flag from the operand cell at 5218H; @PARAM sets this cell non-zero when the DRIVES (or D) keyword is present, and leaves it 0000H otherwise.
521FH - DRIVES Option: Per-Drive Loop Head, Drive-Table Check and Disk-Name Field
For each of the eight logical drives, fetches the Drive Code Table (DCT) entry, skips drives that are not configured, reads the disk name from the drive's Granule Allocation Table (GAT) sector (or substitutes No Disk when the drive is not ready), and begins the drive line with the drive number, write-protect indicator and bracketed disk name.
Save register pair BC (register C = the current logical drive number 0-7) on the stack across the GETDCT call and the display work.
Store the zero in register A into 5270H, the operand of the LD A,nn at 526FH; this byte accumulates the drive-ready/write-protect status used later at 526FH.
Store the rotated status (register A) into 5270H, the operand of the LD A,nn at 526FH, so the write-protect indicator built at 526FH reflects this drive's status.
Load register A from the operand at 5270H, the drive-ready/write-protect status byte stored at entry by 5223H/5237H.
5296H - DRIVES Option: Disk Size, Drive Type, Cylinders, Density, Sides, Step and Settle
Completes the per-drive line from the DCT flag and configuration bytes: the drive size in inches, the Floppy or Rigid type and physical unit number, the cylinder count, and then either the removable/fixed status (rigid) or the density, side count, step rate and head-settle delay (floppy).
535DH - DRIVES Option: Advance to the Next Drive
Restores the loop counter, advances to the next logical drive and repeats until all eight have been reported.
5365H - BYTEIO Option: Resident Device I/O Routing Map
Walks the resident device control block (DCB) tables (the KI/DO/PR table at 4015H and the auxiliary JL/SI/SO table at 43C0H) and, for each active device, prints its name, its input/output direction marker and where its byte I/O is linked, routed or driven from.
Load register pair HL with the BYTEIO-option flag from the operand cell at 5366H; @PARAM sets this cell non-zero when the BYTEIO (or B) keyword is present.
Load register A with the type/flag byte at the start of the current DCB at (HL); a value of 00H marks an unused device slot.
INCrement register L so register pair HL addresses DCB byte +1, the low byte of the linked-device pointer.
53D4H - BYTEIO Option: Routed (Nil) and Linked Device Formatting
Handles the two special routing cases: a device routed to nothing (Nil) or to a disk file (whose name is expanded by @FNAME), and the continuation of a device that is linked to another named device.
Load register A with the buffer byte at (DE) while scanning forward for the 03H terminator that @FNAME wrote.
53FCH - Device Direction-Marker Builder
Builds the routing-direction marker for a device from its flag byte: a leading and trailing space around an equals sign, with a less-than sign added for an input device and a greater-than sign for an output device.
541BH - Three-Digit Decimal Formatter (Cylinder Count)
Formats a 16-bit value (the cylinder count) as up to three ASCII decimal digits with leading-zero suppression, writing them into a caller-supplied field.
542FH - Decimal Digit-Extraction Helper
Extracts a single decimal digit by repeated subtraction of a power-of-ten divisor, suppressing a leading zero by writing the caller's pad character instead.
INCrement register D, counting how many times the divisor (register pair BC) fits into the value.
544AH - Device-Name Field Builder
Appends an asterisk followed by a device's two-character name (from DCB bytes +6 and +7) to the work buffer.
545AH - STATUS Option: Installed Filter List and System Speed
Displays the Options line: the smooth-scroll flag, the eight system filters that are installed (decoded from a packed name list against a resident flag byte) and the current CPU speed (Fast or Slow).
Load register pair HL with the STATUS-option flag from the operand cell at 545BH; @PARAM sets this cell non-zero when the STATUS (or S) keyword is present.
Restore register AF from the stack so register A again holds the (progressively rotated) filter-installed flag byte for the current bit.
Load register A with the current character of the filter name at (HL).
Load register A with the current character of the skipped filter name at (HL).
54B8H - STATUS Option: Verify Flag and High-Memory Module List
Appends the Verify indicator when disk write-with-verify is enabled, then lists the numbered high-memory system modules that are currently resident.
Load register A with the first byte of the current module entry at (HL); a zero byte marks the end of the module list.
INCrement register D, counting how many tens are in the module number.
5516H - Overlay Exit and Command-Level Check
Common exit path. Restores the caller's stack and returns to the RST 28H dispatcher on a normal exit, or aborts the job through @ABORT when an error occurred outside the LDOS command level.
Restore the caller's stack pointer from the operand at 551AH, patched at entry (5200H) with the caller's SP; register SP now again addresses the LDOS command-level stack.
5528H - Buffer-Display and Character-Output Helpers
Local helpers used throughout the overlay: one displays a terminated string on the screen (echoing to the printer when the P option is active) and one prints a single character (also echoed to the printer).
Load register pair DE from the operand at 553BH; this word is the printer-echo flag (non-zero when the P option requested printer output), read here to decide whether to echo the character to the printer.
5542H - New-Line, Pause and BREAK Helpers
Ends a display line and, unless output is suppressed, counts screen lines to pause a full page and to honour the BREAK and pause keys.
Load register pair DE from the operand at 554CH; this word is the pause-suppression flag copied from 553BH at entry (non-zero when printer output or the N nonstop option is active), read here to decide whether screen paging is skipped.
Store the decremented count (register A) into 5552H, the operand of the LD A,0EH at 5551H, so the remaining-lines counter persists between calls.
Store the reset count (register A) into 5552H, the operand of the LD A,0EH at 5551H, restarting the lines-per-page counter.
Load register A with the resident keyboard flag byte KFLAG$ at 4423H again to re-test BREAK while paused.
5596H - BREAK-Line and Parameter-Error Paths
The BREAK termination path and the @PARAM parameter-error path, both of which set the error return before falling into the common exit.
55AAH - Message, Label and Lookup-Table Data
The overlay's string pool: the No Disk placeholder, the Options and drive-geometry labels, the packed filter-name word list, the two-character step-rate lookup table and the device-routing markers. All display strings are terminated by 03H for @DSPLY.
The 12-byte template (through 55B5H) block-copied to the disk-name buffer at 42D0H by 5257H when a drive is not ready; 42D0H-42D7H become the name No Disk, 42D8H the closing bracket.
Eight system-filter names read at 547BH-5497H, one per bit of the resident flag byte 441FH (bit 0 Spool, bit 1 Type, bit 2 JKL, bit 3 PR, bit 4 KI, bit 5 MiniDOS, bit 6 KSM, bit 7 Graphic). The final character of each name carries bit 7 set as the end-of-word marker; the spaces shown here separate the decoded words only.
Eight two-character step-rate values indexed at 5328H by the reshuffled stepping-rate bits of DCT+03H: " 6", "12", "20", "40", " 3", " 6", "10", "15" (milliseconds).
566EH - Work Buffer and @PARAM Keyword Descriptor Table
The RAM work buffer where each drive and device line is assembled (not part of the loaded image), the Verify label, and the @PARAM keyword descriptor table that maps each option keyword to the self-modified flag cell it sets.
A 40-byte RAM scratch area (not present in the overlay image) into which each device routing line and drive line is built by the code at 5374H and 53B8H before display.
Disassembly - Overlay 11 - LINK
5200H - LINK Command: Entry, Command-Level Check and Device-Spec Parse
Entry of the LINK command overlay, which links two character devices so that output to the first is also passed to the second. It saves the caller's stack, confirms the command was issued at the LDOS command level, and parses the two device specifications (each must name a device, introduced by the asterisk character 2AH) with the resident @FSPEC service.
Store the caller's stack pointer into the operand of the LD SP,nnnn instruction at 52B8H so the overlay exit can restore the caller's stack. Register SP holds the LDOS command-level stack on entry.
Store the first device name (register pair DE) into the operand at 52CEH, the name field inside the link-driver stub template.
Store the first device name (register pair DE) into the operand at 539DH, the LKxxxx module-name template.
524EH - Validate the Devices and Build the Link Driver
Locates both device control blocks, refuses a device that is already routed, captures the first device's existing driver vector, allocates space (reserving high memory when needed) and copies the relocatable link-driver stub into it, patching the new driver in front of the first device.
Store the second device name (register pair DE) into the operand at 52D0H, the second name field inside the link-driver stub template.
Store the second device name (register pair DE) into the operand at 539FH, the LKxxxx module-name template.
Store the second device's control-block pointer (register pair HL) into the operand at 52DEH inside the stub's output path.
Store the second device's control-block pointer (register pair HL) into the operand at 52EBH inside the stub's input path.
Store the first device's driver address (register pair HL) into the operand at 52D7H, the output-path call inside the stub.
Store the first device's driver address (register pair HL) into the operand at 52E6H, the input-path call inside the stub.
Store the returned module address (register pair DE) into the operand at 52C9H, the stub's module link field.
Store the current HIGH$ (register pair HL) into the operand at 52C9H as the stub's link field.
52B5H - Overlay Exit and Caller Stack Restore
Restores the caller's stack pointer saved at entry and returns to the LDOS command level, or aborts to DOS when the system flag requires it.
Load register SP from the operand at 52B9H, set at entry to the caller's stack pointer, restoring the caller's stack for the return.
52C7H - LINK Data: Relocatable Link-Driver Stub Template
The 41-byte link-driver stub copied into the allocated area by the block move at 52AEH. It is a small character driver: on an output call it passes the byte to the first device's original driver and then to the second (linked) device; the operands shown as 0000H are self-modified before the copy with the two device driver addresses and control blocks.
JR +9 (18 09) that skips the module header when the relocated stub is entered.
Two bytes forming the forward link in the resident module chain.
The link module name: a length byte (06H) and the text LK followed by the two-character device name field at 52CEH-52CFH, which is self-modified from the first device name by the store at 5240H (and 52D0H-52D1H by 5258H).
The stub's output routine. It saves registers, calls the first device's original driver at the operand patched into 52D7H (by 5282H), then prepares the second device's control block at the operand patched into 52DEH (by 5266H).
Calls the ROM @PUT routine (001BH) to send the byte to the linked second device, then returns.
Calls the first device's driver at the operand patched into 52E6H (by 5285H); on a non-zero result it prepares the second device's control block (operand at 52EBH, patched by 5269H) and jumps to the ROM @GET routine (0013H).
52F0H - Helper: Find a Device Control Block by Name
Searches the resident device control block chains (the KIDCB$ block at 4015H and the auxiliary chain at 43C0H) for a control block whose two-character name matches register pair DE, returning its address in HL or the device-not-found error.
5316H - Helper: Obtain the Link-Module Control Block
Issues a resident supervisor call to obtain the control block for the new link module and returns the pointer taken from its +02/+03 field.
5326H - Error Handler and Message Dispatch
Reports a numeric error through @ERROR, and provides the three refusal messages (routed device, device spec required, command-level only). The three message entries share overlapping bytes so that one of three addresses is loaded into HL depending on the entry point.
As assembled this is LD IX,535CH (bytes DD 21 5C 53). When control jumps to 5331H (skipping the DD prefix byte), the bytes 21 5C 53 read as LD HL,535CH, loading the Device spec required message address for that entry.
As assembled this is LD IX,5371H (bytes DD 21 71 53). When control jumps to 5335H (skipping the DD prefix byte), the bytes 21 71 53 read as LD HL,5371H, loading the Can't -- Only valid at LDOS command level message address for that entry.
5341H - LINK Data: Messages and Module Name Template
The refusal messages and the link-module display-name template.
The Can't Link a Routed Device text, carriage-return terminated, addressed at 5341H by the entry at 532DH.
The Device spec required text, carriage-return terminated, addressed at 535CH by the overlapping entry at 5331H.
The Can't -- Only valid at LDOS command level text, carriage-return terminated, addressed at 5371H by the overlapping entry at 5335H.
The LKxxxx display-name template (LK plus a four-character field) and its 00H terminator, used to name the installed link module.
Disassembly - Overlay 12 - Command Overlay 12
5200H - Overlay Entry: Save Base-Driver Vectors, Parse Options and Argument
Entry of command overlay 12. It saves the caller's stack, captures the resident base-driver addresses of the KI, DO and PR devices into the local reset template, scans the command line for a parameter list, parses the LRL and DATE options with @PARAM, and parses the file or device argument with @FSPEC to choose one of three actions: reset a device, reset system memory, or set a file's directory attributes.
Store the caller's stack pointer (register SP, holding the LDOS command-level stack on entry) into the operand of the LD SP,nnnn at 5281H, so the overlay exit can restore this stack.
Store the KI base-driver address (register pair HL) into 542EH, the driver-address field of the local KI reset-template DCB, so the template restores the current base driver.
Store the DO base-driver address (register pair HL) into 5436H, the driver-address field of the local DO reset-template DCB.
Store the PR base-driver address (register pair HL) into 543EH, the driver-address field of the local PR reset-template DCB.
Load register A with the command-line character at (HL) while scanning for a parameter list or the end of the line.
5240H - Device Reset: Locate the DCB and Restore its Base Template
When the argument names a device, finds its control block, follows any link chain to the base device and closes a routed file, then overwrites the resident DCB with its 8-byte base template and performs the device-specific reset action (clear filters, reinitialize the keyboard, or clear the screen).
527EH - Common Exit and Command-Level Check
Shared exit path. Restores the caller's stack and returns to the RST 28H dispatcher on a normal exit, or aborts through @ABORT when an error occurred outside the LDOS command level.
Restore the caller's stack pointer from the operand at 5282H, patched at entry (5200H) with the caller's SP; register SP now again addresses the LDOS command-level stack.
5290H - Memory Reset: Command-Level and Background-Task Checks
The no-argument path resets all of system memory. It first refuses the reset unless it is running at the LDOS command level with no active background task, displaying the appropriate message, and clears the keyboard and printer filters.
52B0H - Memory Reset: Reset Every Device and Scan High Memory
Walks both device tables resetting each device to its base and closing any routed files, then scans the high-memory module table and refuses the reset if any module sits in protected memory above HIGH$.
Save register pair HL (the current DCB pointer) on the stack across the link-chain walk.
Load register E with the low byte of the current module's start address at (HL).
52DCH - Memory Reset: Restore Resident Vectors, HIGH$ and Default DCBs
Rebuilds the base system: disarms resident hooks and interception routines, empties the high-memory module chain, clears resident work areas, refreshes the drive code tables, restores HIGH$ to the top of memory and reinstalls the default device control blocks.
Store zero (register A) at (HL) in the 43D8H work area.
5374H - Disk File: Set the LRL and DATE Directory Attributes
When the argument names a disk file, opens it, checks the update access level, reads its directory entry and applies the requested logical record length and date, then writes the directory record back.
Load register pair DE with the LRL value from the operand at 5394H; @PARAM writes the requested logical record length here, leaving 0FF00H (high byte FFH) when no LRL keyword was given.
Load register pair DE with the DATE value from the operand at 539DH; @PARAM writes the requested date here (or 0FFFFH for the keyword alone), leaving 0FF00H when no DATE keyword was given.
53C1H - Link-Chain Walk and Routed-File Close Helper
Follows a device's link chain to its base control block and, if the base routes output to a disk file, copies that file's control block to a work area and closes it.
Test bit 4 of the DCB type byte at (HL), which is set when this device is linked to another device.
53DDH - Error and Command-Level Refusal Paths
The shared @ERROR reporting path and the command-level refusal path that displays the Valid only at LDOS command level message, both ending in the error exit.
53F0H - Find Device Control Block by Name
Searches the resident KI/DO/PR table and the auxiliary JL/SI/SO table for a device control block whose two-character name matches the requested device, returning its address or a device-not-available error.
Point register pair HL at 4015H, the first resident device control block, to search for the named device.
Save register pair HL (the current DCB pointer) on the stack across the name comparison.
5416H - Filter-Flag Reset Helpers
Two small helpers that clear device filter bits in the resident flag byte 441FH and reinitialize the keyboard driver.
542AH - Control Sequence, Default DCB Templates and @PARAM Table
The screen home-and-clear control sequence, the six 8-byte base device control block templates used to restore KI, DO, PR, JL, SI and SO to their default drivers, and the @PARAM keyword descriptor table for the LRL and DATE options.
The home-cursor (1CH) and clear-to-end-of-frame (1FH) video control codes, displayed at 527BH when the display device (DO) is reset. Byte 542AH is also overwritten with 03H at 5339H on the refused-reset path.
Device type byte of the base keyboard control block copied to 4015H at 5350H.
Device type byte of the base display control block copied to 401DH at 5350H.
Device type byte of the base printer control block copied to 4025H at 5350H.
Device type byte of the base JL control block copied to 43C0H at 5365H.
Device type byte of the base SI control block copied to 43C8H at 5365H.
Device type byte of the base SO control block copied to 43D0H at 5365H.
547EH - Refusal Messages
The two carriage-return-terminated refusal messages displayed through the resident 447BH service.
Displayed at 53E7H when the command is refused because a nested job or intercept is active or it was not issued at the LDOS command level.
Displayed at 5334H when the memory reset is refused because a background task is running or a resident module occupies protected memory above HIGH$.
Disassembly - Overlay 13 - ROUTE
5200H - Overlay Entry: Parse the Source Device and Options
Entry of the ROUTE command overlay, which sends all output of one device to another device or to a disk file. It saves the caller's stack, parses the source device specification with @FSPEC, parses the NIL and REWIND options with @PARAM, records the source device name in the routing-module name, and branches to the NIL handler when NIL was given.
Store the caller's stack pointer (register SP, holding the LDOS command-level stack on entry) into the operand of the LD SP,nnnn at 527DH, so the overlay exit can restore this stack.
Load register pair BC with the NIL flag from the operand at 5223H; @PARAM sets it non-zero when the NIL keyword was given, leaving 0000H otherwise.
522AH - Parse the Destination and Dispatch by Route Type
Parses the destination specification. A device destination is routed device-to-device (rejecting a device routed to itself); a disk-file destination is routed through a high-memory file module.
5255H - Install the Route into the Source Device and Exit
Marks the source device as routed, stores the destination address into the source control block link pointer and the destination name into the device-name field the DEVICE command displays, then returns to the dispatcher (or aborts below command level on an error).
Restore the caller's stack pointer from the operand at 527EH, patched at entry (5200H) with the caller's SP; register SP now again addresses the LDOS command-level stack.
528CH - Route to a Disk File: Locate or Allocate the High-Memory Module
Looks up an existing routing module for the device, or checks the command level, opens the destination file (positioning to its end for append unless REWIND was given), reserves memory below HIGH$ and builds the module header and file control block, then links the device to it.
Store zero into 52E5H, the operand of the OR nn at 52E4H, so the HIGH$ reservation below is skipped when reusing an existing module.
Load register pair BC with the REWIND flag from the operand at 52CDH; @PARAM sets it non-zero when REWIND was requested, leaving 0000H otherwise.
OR register A with the operand at 52E5H (0FFH for a new module, patched to 00H at 529DH when reusing an existing one) to decide whether HIGH$ must be lowered.
5303H - Locate and Validate the Source Device Helper
Finds the source device's control block (allocating a free slot for a new user device), returning a no-device-space error if none is free, and closes any file the device is already routed to.
531CH - NIL Route Helper
Routes the source device to nothing: returns its control block to the base state and restores its own name.
532DH - Routing-Module Lookup and Byte-Pair Store Helpers
Issues the resident routing-module lookup and a small two-byte store used to write a link pointer or device name into a control block.
5334H - Close a Routed File and the @ERROR Path
Follows a device link chain to its base and closes any disk file it routes to, and provides the shared @ERROR reporting entry.
Test bit 4 of the DCB type byte at (HL), which is set when this device is linked or routed to another device.
On the close-failure fall-through these bytes decode as LD BC,2C3EH, a filler load left in register pair BC. Entered at 5351H from 5217H and 523BH, the same bytes decode as LD A,2CH, loading the parameter-error code 2CH before the shared @ERROR call below.
535AH - Refusal and Error-Message Display
Displays the command-level refusal message or the Device spec required message, using a single display call reached through two overlapping instruction entries, then sets the error return.
On the fall-through path these bytes decode as LD IX,53BBH (harmless here). Entered at 535EH from 5230H and 524CH, the same bytes (skipping the DD prefix) decode as LD HL,53BBH, pointing register pair HL at the Device spec required! message so the shared display below shows it.
536AH - Find Device Control Block by Name
Searches the resident KI/DO/PR table and the auxiliary JL/SI/SO table for a control block whose two-character name matches the requested device.
Point register pair HL at 4015H, the first resident device control block, to search for a device by name.
Save register pair HL (the current DCB pointer) on the stack across the name comparison.
5390H - Messages, @PARAM Table and Routing-Module Header Template
The two refusal messages, the @PARAM keyword descriptor table for the NIL and REWIND options, and the 9-byte header template used to build a routing module in high memory.
Displayed at 5361H (reached at 535AH) when the route is refused because a nested job is active or the command was not issued at the LDOS command level.
Displayed at 5361H when reached through the overlapping entry at 535EH, when a device specification is missing, malformed or names the same device twice.
The high-memory module marker (18H) and link byte, copied to the new module at 52F5H.
Disassembly - Overlay 14 - Device Driver/Filter (ORG 5A00H)
5A00H - Overlay Entry: Command-Level Check, Spec Parse and Driver/Filter Install
Entry of the driver/filter install command overlay (loaded at 5A00H, not 5200H). It refuses to execute unless it is running at the LDOS command level with no active background task, parses the target device and the driver/filter file, applies the DVR or FLT default extension, locates or creates the device, loads the file and transfers control into the loaded module's initialization code.
Store the mode flag (register A) into 5A84H, the operand of the LD A,nn at 5A83H, so the mode is available to the tests at 5A47H and 5A83H.
Store the caller's stack pointer (register SP, the LDOS command-level stack on entry) into the operand of the LD SP,nnnn at 5AE0H, so the error-exit path can restore this stack.
Load register A from the operand at 5A84H, the driver/filter mode flag stored at entry.
5A9CH - Default Extension Strings
The three-character default file extensions applied by @FEXT at 5A53H, chosen by the mode flag: DVR for a device driver, FLT for a filter.
5AA2H - Find Device Control Block by Name
Searches the resident KI/DO/PR table and the auxiliary JL/SI/SO table for a control block whose two-character name matches the requested device (or an empty slot when searching with a zero name).
Point register pair HL at 4015H, the first resident device control block, to search for a device by name.
Save register pair HL (the current DCB pointer) on the stack across the name comparison.
5AC8H - Error, Overlapping Message Dispatch and Exit
The shared @ERROR path, the three-way message selection reached through two overlapping instructions, and the exit that restores the caller's stack or aborts below command level.
On the fall-through these bytes decode as LD IX,5B19H. Entered at 5AD3H from 5A18H and 5A20H, the same bytes (skipping the DD prefix) decode as LD HL,5B19H, selecting the Can't -- Valid only at LDOS command level! message.
On the fall-through these bytes decode as LD IX,5AEFH. Entered at 5AD7H from 5A3DH and 5A43H, the same bytes decode as LD HL,5AEFH, selecting the File spec required! message.
Restore the caller's stack pointer from the operand at 5AE1H, patched at entry (5A05H) with the caller's SP; register SP now again addresses the LDOS command-level stack.
5AEFH - Refusal Messages
The three carriage-return-terminated messages displayed through the resident 447BH service, selected by the overlapping instructions at 5ACFH-5AD7H.
Displayed when the driver/filter file specification is missing or names a device (reached through the entry at 5AD7H).
Displayed when the target device specification is missing or malformed (reached at 5ACFH).
Displayed when the command is refused because a nested job is active or it was not issued at the LDOS command level (reached through the entry at 5AD3H).
Disassembly - Overlay 15 - Single-Drive Command Loader
5200H - Entry Vectors: Run or Load the Command File
Entry of the single-drive command-loader overlay. The main entry runs the program; an alternate entry loads it. Both parse the command line first and, when the load-only X option is given, prompt the user to swap disks.
Load register A from the X-option flag at 52BDH (the operand of the LD DE at 52BCH); @PARAM sets it non-zero when the X load-only option was given.
5222H - Flashing Disk-Swap Prompt and Keyboard Wait
Displays a disk-swap prompt, flashing it on and off, and waits for the user to press a key (or BREAK to abort), debouncing the keyboard.
GOSUB to 5267H to clear the low three control bits of the keyboard flag KFLAG$ (4423H) before waiting.
GOSUB to the resident @DSPLY service at 4467H to display the prompt string at register pair HL (up to its 03H terminator).
Load register A with the keyboard flag byte KFLAG$ at 4423H to test for BREAK or a pending key.
GOSUB to the ROM keyboard-scan routine at 002BH to read the key (register A returns it, or zero once released).
5270H - Command-Aborted Path
Displays the Command aborted message and the Insert SYSTEM disk prompt, then aborts through @ABORT.
527CH - Main Entry: Parse then Run or Load
The overlay's primary entry: parses the command line and either runs the program with @RUN or, for the X option, loads it and prompts for the system disk.
Load register A from the X-option flag at 52BDH (the operand of the LD DE at 52BCH); it is non-zero when the X load-only option was given.
5293H - Parse the Command Line, Option and Program Filespec
Saves the stack for exit, parses the X option with @PARAM, skips a leading space, parses the program filespec with @FSPEC into the resident FCB, applies the default CMD extension, and prompts for the source disk when the X option is present.
Store the caller's stack pointer (register SP, the LDOS command-level stack) into the operand of the LD SP,nnnn at 52F3H, so the overlay exit can restore this stack.
Load register pair DE from the operand at 52BDH; this is the X-option flag (non-zero when the load-only option was given), and it selects whether a source-disk swap is prompted for.
52C9H - Drive Service and File Load Helper
Issues a resident supervisor call, and loads the program file (marking the load in progress) with error reporting.
On the load-failure fall-through these bytes decode as LD BC,2C3EH, a filler load (register A already holds the load error code). Entered at 52E1H from 529DH, the same bytes decode as LD A,2CH, the parameter-error code, before the shared @ERROR call at 52E3H.
52F0H - Overlay Exit
Restores the caller's stack and returns to the RST 28H dispatcher, or aborts through @ABORT when an error occurred outside the command level.
Restore the caller's stack pointer from the operand at 52F4H, patched at 5293H with the caller's SP; register SP now again addresses the LDOS command-level stack.
5302H - Messages, Prompts, @PARAM Table and Extension
The error message, the two flashing disk-swap prompts (framed by video control codes), the Command aborted message, the @PARAM keyword table for the X option and the default CMD extension.
Displayed at 52EDH when the program filespec is missing, malformed or names a device.
Displayed by the flashing-prompt routine at 5235H (pointed to at 521AH) asking the user to reinsert the system disk on a single-drive machine.
Displayed by the flashing-prompt routine (pointed to at 52C1H) asking the user to insert the source disk when the X option is given.
Displayed at 5273H when the user presses BREAK at a disk-swap prompt.