TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS18/SYS Disassembled
Page Customization
Page Index
SYS18/SYS
Other Navigation
Description:
SYS18/SYS is the BASIC Direct Statement Executor for NEWDOS/80 v2.0. This system file must be present on the system diskette whenever BASIC is active, as it handles the immediate execution of direct commands (commands entered at the BASIC prompt without a line number) and manages the sophisticated LIST command with its various display modes.
Core Functionality:
The module implements an advanced LIST command dispatcher that supports multiple input modes for flexible program viewing:
- Colon (:) - Lists the entire program starting from line 0
- Up-arrow ([) - Lists the previous line (relative to last listed line)
- Down-arrow (LF) - Lists the next line (relative to last listed line)
- Period (.) or Comma (,) - Continues listing from last position
- At-sign (@) - Lists 13 lines of context around current position
- AUTO modes (^Z, /) - Automatic line numbering for program entry
Screen Management:
The LIST implementation includes sophisticated screen handling that manages display bounds (15 lines maximum per screen), tracks cursor position across 64-column lines with automatic wrapping, and maintains a "last listed line" pointer at memory location 40ECH for seamless continuation commands. The system uses screen control codes (1CH = cursor right, 1FH = cursor home) to prepare the display area before listing program lines.
EDIT Command Support:
Beyond LIST functionality, SYS18 handles the EDIT command (triggered by semicolon or ESC key), which allows interactive line editing of existing BASIC program lines. The EDIT mode provides cursor positioning and character manipulation capabilities for modifying program statements in place.
Integration with BASIC/CMD:
The module works closely with the main BASIC/CMD interpreter, calling ROM routines for actual statement execution and screen output. It uses self-modifying code techniques (storing command characters at 5227H) to maintain state across complex control flow paths, and integrates with BASIC's work pointer (40A7H) and program text area (TXTTAB at 40A4H) to navigate the program structure.
Technical Implementation:
The code demonstrates advanced programming techniques including:
- Linked-list traversal through BASIC program lines using 2-byte forward pointers
- Bidirectional line offset calculations with underflow protection (clamping to line 0)
- Line counting and skip-ahead algorithms for efficient positioning
- Register-based state machines for multi-mode command processing
- Stack manipulation for nested call structures and state preservation
The module occupies approximately 1256 bytes (5200H-56E7H) with substantial NOP padding in the upper range (5650H-56E7H) reserved for future expansion or system compatibility. This padding suggests the module was designed with room for additional features or to maintain specific memory boundaries within the NEWDOS/80 architecture.
Variables:
| Address | Bytes | Purpose |
|---|---|---|
| 5227H | 1 | Self-modifying code: Stored command character for later comparison. Modified by instruction at 522FH to preserve the user's input command (colon, arrows, at-sign, etc.) for subsequent conditional logic. |
| 40A4H | 2 | TXTTAB - BASIC program text start pointer. Points to the first byte of the BASIC program in memory (standard BASIC system variable). |
| 40A7H | 2 | BASIC work pointer. Used by ROM routines and BASIC/CMD for statement processing and expression evaluation. |
| 40ECH | 2 | Last listed line number. Stores the line number of the most recently displayed program line, enabling continuation LIST commands (period, comma, arrows) to resume from the correct position. |
| 4369H | 1 | System flag byte. Bit 5 indicates special system state; when set, triggers alternate processing path through ROM 05D9H with B=F0H. |
| 5272H | Temporary line number storage (to be copied to 40ECH). | |
| 5373H | Saved line pointer (for EDIT or continuation). | |
| 6421H | 1 | Chaining flag. Non-zero value indicates program chaining is active; when set, control passes to ROM routine at 2831H for chain execution. |
Note: SYS18 relies heavily on BASIC system variables and ROM entry points rather than maintaining extensive local storage. The module's design favors stateless operation with minimal memory footprint, using the stack and CPU registers for transient data during command processing.
Routine Overview:
Command Dispatcher (5200H-527AH):
| Address | Purpose |
|---|---|
| 5200H | Entry point - CP A self-test, RET |
| 5202H | Initialize with 0EH output, call ROM 0033H |
| 5207H | Check system flag at 4369H bit 5 for special state |
| 520EH | If bit 5 set, push BC, load BASIC work pointer, call ROM 05D9H with B=F0H |
| 521AH | Main path - call ROM 0049H to get input character |
| 521EH | Check chaining flag at 6421H, jump to ROM 2831H if set |
| 5226H | Initialize L=00H as flag register |
| 5228H | Backtick (60H) converted to at-sign (40H) |
| 522FH | Self-modifying code stores command character at 5227H |
| 5271H | Command character tests |
Command character tests:
| Character | Hex | Meaning | Target | List Offset |
|---|---|---|---|---|
| : | 3AH | List entire program | 5271H → 5280H | Start from line 0, list with -13 offset (show 13 lines context) |
| LF | 0AH | List next line (down) | 527CH → 5280H | Current line + 1 |
| [ | 5BH | List previous line (up) | 527CH → 5280H | Current line - 1 |
| . | 2EH | List continuation | 527CH → 5280H | Current line (continuation from 40ECH) |
| , | 2CH | List continuation | 527CH → 5280H | Current line (continuation from 40ECH) |
| @ | 40H | List @ mode | 527CH → 5280H | Current position, no offset |
| ` | 60H | Converted to @ (40H) | 522CH → 527CH | |
| ; | 3BH | EDIT command | 524FH → 537AH | |
| ESC | 1BH | EDIT command | 524FH → 537AH | |
| ^Z | 1AH | AUTO mode | 5257H → 5280H | |
| / | 2FH | AUTO mode | 5259H → 5280H | |
| OTHER | nnH | Pass to ROM BASIC executor | 5261H |
Edit Command Path (524FH-526EH):
- 524FH: EDIT entry point (for 3BH or 1BH)
- Loads HL from 40A4H (TXTTAB), jumps to 537AH
- Alternate path at 5261H for non-LIST commands
- Pushes 53CBH as return address
- Loads BASIC work pointer from 40A7H
- Sets B=F0H, C=B, pushes HL
- Jumps to ROM 05E3H to execute via standard BASIC
List Command Setup (5271H-527CH):
| Address | Purpose |
|---|---|
| 5271H | Colon LIST - sets DE=0000H (list from beginning) |
| 5274H | Self-check using L register (initially 00H)
|
| 527CH | Load last listed line from 40ECH into DE |
Line Number Scan Loop (5280H-52ACH):
| Address | Purpose |
|---|---|
| 5280H | Load TXTTAB (program start) into HL |
| 5283H | Initialize BC=0000H as line counter |
| 5286H | [LOOP START] Load link pointer (2 bytes at HL) |
| 5288H | OR test for 0000H (end of program) |
| 528AH | If end found, jump to 537AH (exit) |
| 528DH | Skip to line number (HL+3 = high byte) |
| 5290H | Compare line number high byte (D) |
| 5292H | Back to low byte, compare if high matched |
| 5297H | Check carry flag - if current < target, continue |
| 5299H | If current >= target, jump to 52ADH (found range) |
| 529BH | [CONTINUE SCAN] Push HL, follow link pointer |
| 529CH-529FH | Load next line address into HL |
| 52A0H | Check if next line exists (link != 0000H) |
| 52A3H | If end, jump to 52A9H |
| 52A5H | Increment BC (line counter) |
| 52A7H | Loop back to 528EH |
| 52A9H | [END REACHED] Restore HL, pop AF, jump to 52BFH |
Range Adjustment (52ADH-52CDH):
| Address | Purpose |
|---|---|
| 52ADH | Pop DE (restore command), check if exact match |
| 52B1H | Down-arrow (0AH): DE=0001H (+1 line) |
| 52B8H | Up-arrow (5BH): DE=FFFFH (-1 line) |
| 52BFH | Default: DE=0000H (no offset) |
| 52C6H | Colon: DE=FFF3H (-13 lines for @ mode) |
| 52CEH | All paths converge |
Offset Application (52CEH-52FFH):
| Address | Purpose |
|---|---|
| 52CEH | Save AF, swap DE?HL |
| 52D0H | Add BC to HL (apply offset) |
| 52D2H | Check for underflow (high byte = FFH) |
| 52D6H | Clamp to 0000H if underflow |
| 52D9H | Calculate remaining lines (original - skip) |
| 52E1H | Reload TXTTAB, begin skip loop |
| 52E4H | [SKIP LOOP] Follow link pointers BC times |
| 52ECH | Loop back if more to skip |
| 52EEH | Restore remaining line count to BC |
| 52F1H | Restore command character to AF |
| 52F4H | Store command in B for later |
| 52FCH | Final AF pop |
| 52FDH | Load 1CH (cursor right) for screen clear |
| 52FFH | Call 5D66H (output character) |
| 5302H | Continue setup with 1FH |
Screen Management Algorithm:
Row/Column Tracking:
- Register D: Row counter (starts at 1 after line number display)
- Register E: Column counter (0-63, wraps at 64 via BIT 6 test)
- Maximum rows per screen: 15 (0FH)
- Screen width: 64 columns (40H)
Column Wrap Detection:
The code uses a clever optimization at 5330H:
BIT 6,E ; Test bit 6 of column counter
When E reaches 40H (64 decimal), bit 6 becomes set:
- E=3FH (63): bit 6 = 0 (within line)
- E=40H (64): bit 6 = 1 (wrap needed)
This single instruction replaces: CP 40H; JR NC,wrap
Screen Full Algorithm:
- Display line, counting rows used (handle 64-column wrapping)/li>
- Add to accumulated row count (D register)/li>
- Compare to 15 (0FH)/li>
- If >= 15:
- @ command: Exit to 5367H
- Colon command: Reset counters, display next page from 5307H
- If < 15: Continue to next line at 530BH
Disassembly:
5200H - Entry Point and Command Type Dispatcher
SYS18 is the BASIC direct statement executor that processes immediate-mode commands entered at the BASIC prompt. When BASIC encounters a direct command (one without a line number), it loads and calls this module to parse and route the command to the appropriate handler. The entry point validates the environment, checks for system chaining mode, and dispatches to specialized handlers based on command type (LIST variants, EDIT, AUTO, etc.).
[MAIN ENTRY POINT] Entry at 5202H indicates this is the primary entry point for SYS18.
[SYSTEM CHAINING CHECK] Before processing the command, check if the system is in chaining mode (transferring control to another program).
[SPECIAL STATE PATH] If bit 5 of 4369H was set, this indicates a special system state that requires custom handling through the ROM.
[STANDARD COMMAND PROCESSING] Normal entry path for direct commands entered at the BASIC prompt.
[CHAINING MODE CHECK] Check if the system is in program chaining mode (loading another program).
[COMMAND CHARACTER PROCESSING] Extract and normalize the command character for dispatcher routing.
The backtick character (60H) is converted to @ sign (40H) for processing - they are treated as equivalent command prefixes.
[SELF-MODIFICATION SETUP] Store the normalized command character for later comparison in a self-modifying instruction.
[COMMAND TYPE DISPATCHER] Route to appropriate handler based on command character.
[PROGRAM BOUNDARY SETUP] Load the start of the BASIC program for LIST and EDIT commands.
[AUTO COMMAND DISPATCHER] Process AUTO command with optional line number and increment parameters.
[UNKNOWN COMMAND HANDLER] If none of the direct command characters matched, pass the command to the ROM's statement executor.
[LIST WITH NO RANGE] Handle LIST : (colon) command which lists the entire program.
At this point we've fallen through from the @ comparison check. The code continues to check if we need to use the last listed line number stored at 40ECH for continuation listing.
[LIST INITIALIZATION] We now have the starting line number in DE (either 0000H for colon/first-time, FFFFH for AUTO mode, or the last listed line from 40ECH). Next we load the program start pointer and initialize the line counter.
[PROGRAM SCAN LOOP] The following loop scans through the BASIC program to find the starting line number in DE. It counts lines in BC to handle special cases like @ (which lists from line -13).
Not at end of program, so we have a valid line. Check if this line's number matches our target.
High bytes match, so check low byte to see if we have an exact match.
After this comparison, the flags tell us: Z FLAG = exact match, C FLAG = current line < target, NC FLAG = current line >= target.
[CONTINUE FORWARD SCAN] Current line < target, so we need to keep scanning. Increment the line counter and advance to the next line.
Check if this next line exists (link is not 0000H which marks end of program).
Valid next line exists, so increment line counter and continue scanning.
End of program reached while scanning - restore stack and exit search.
52ADH - LIST Range Adjustment for Special Commands
Handles special LIST command modifiers: up-arrow/down-arrow for ±1 line, colon for -13 lines (@ mode), and validates against available lines.
[RANGE FOUND] We've found a starting line >= target. Now adjust based on command type: down-arrow (+1), up-arrow (-1), or @ (-13).
Exact match found. Check if this is a down-arrow command (0AH = line feed).
Not down-arrow. Check for up-arrow (5BH = left bracket).
Not up or down arrow. Set DE to 0 for default LIST, then check for @ special case.
Must be colon command. Set offset to -13 lines (FFF3H) for @ mode backwards listing.
52CEH - Apply Line Offset and Calculate Screen Bounds
Applies the calculated offset (±1, -13, or 0) to the line counter, checks for underflow, and calculates how many lines will fit on screen based on line length and 15-line limit.
[APPLY OFFSET] DE contains the offset to apply to the line counter BC. This adjusts the starting position based on command type.
Underflow detected - tried to go before line 0. Clamp to line 0.
HL now contains the number of lines to skip from program start. Swap registers and calculate how many lines we actually need to skip.
[SKIP TO START LINE] Now skip forward BC lines to reach the actual starting line for the LIST display.
Finished skipping to the starting line. HL now points to the first line we want to LIST. Restore remaining line count and prepare for display loop.
[PREPARE DISPLAY] Call ROM routines to clear screen region and prepare for line-by-line display.
5307H - Main LIST Display Loop
Core listing loop that displays BASIC program lines with sophisticated screen management.
5379H - EXIT/EDIT Entry Point
Alternative exit path for LIST command and entry point for EDIT mode. In the EDIT mode, This section checks if the cursor is positioned within the valid video buffer range (3C00H-3FFFH) when EDIT mode is requested. If the cursor position minus 40H (64 decimal) falls below the video RAM area, the routine exits EDIT mode and returns to BASIC ready state.
[EDIT BUFFER CHECK PASSED - Check for "READY" Command]
The cursor position is valid for EDIT mode. Now check if the user typed the word "READY" to exit or perform special actions.
[LOOP START - Compare Screen Buffer with "READY"]
Loop through 10 characters comparing what's on the screen with the expected "READY" command.
[ALL CHARACTERS MATCHED - "READY" Command Detected]
The user typed "READY" on the line above the cursor. Send cursor positioning codes and return to BASIC.
[EXIT EDIT MODE - Restore BASIC]
Whether the READY check passed or failed, clean up and return to BASIC ready state.
53C1H - "READY" Comparison String Data
This is the data string used for comparison in the EDIT mode check at 53A3H. It contains the text "READY" followed by trailing spaces (total 10 bytes) used to detect if the user typed this command.
53CBH - Return from LIST/EDIT - Update Line Number
This is the common return point from LIST and EDIT commands. It updates the BASIC system variable at 40ECH with the last displayed line number (stored temporarily at 5272H), then performs stack cleanup and returns to the BASIC command processor.
[NUMERIC LINE NUMBER ENTRY]
User entered a line number. Parse it and execute the appropriate action.
[COMMAND DISPATCH - Non-Numeric Input]
Check for special command keywords (RENEW, RENUM, REF, etc.) by scanning the command table.
[COMMAND SCAN LOOP]
Loop through the command table to find a match with user input.
[NO MATCH - Skip to Next Command]
The input didn't match this command entry. Skip to the next command in the table.
[CHARACTER MATCH FOUND - Continue Checking]
One character matched. Continue comparing the rest of the command word.
[COMPLETE COMMAND MATCH - Get Jump Address]
All characters matched. Extract the jump address and check command flags.
[SPECIAL PROCESSING - Clear Input Buffer]
Bit 6 was set, indicating this command requires clearing the input buffer before execution.
[DIRECT COMMAND EXECUTION]
Bit 6 was clear. Execute the command directly without buffer clearing.
[STANDARD PARAMETER PROCESSING]
Parse line number and comma-separated parameters for standard commands.
[PREPARE FOR COMMAND EXECUTION]
All parameters parsed. Set up registers and execute the command handler.
[PREPARE FOR LINE INSERTION]
Calculate buffer offsets and prepare to insert/move BASIC program lines.
[CLEANUP AND RETURN]
Restore saved registers and return to BASIC command processor.
5458H - Special Parameter Command Handler (Bit 5 Set)
This section handles commands that have bit 5 set in their flag byte (from 53FDH), indicating they require special parameter parsing different from standard line-number commands. This is used for commands with complex syntax like line-range specifications or period-based current-line references.
[PERIOD FOUND - Use Current Line]
Period notation used. Get current line number from 40ECH.
[NUMERIC LINE NUMBER]
Parse the numeric line number from input.
[CHECK FOR COMMA SEPARATOR]
Look for comma to see if this is a range specification (start,end).
[COMMA FOUND - Parse End Line Number]
This is a range specification. Parse the second line number.
[VALID RANGE - Clean Stack and Execute]
Both line numbers parsed successfully. Clean up the stack and execute the command with the range.
[COPY LINE CONTENT LOOP]
Copy the BASIC line content to work area until end of line (00H terminator).
[PREPARE FOR COMMAND EXECUTION]
Line copied. Set up registers and call the command handler.
[SPECIAL PROCESSING - Bit 0 Set]
Bit 0 of command flag was set, requiring additional setup before execution.
[FINAL CLEANUP AND RETURN]
Restore all registers and return to BASIC.
54B7H - Command Dispatch Table
This table contains the command keywords (RENEW, RENUM, REF) with their associated flag bytes and jump addresses. Each entry consists of the command name (with bit 7 set on the last character), followed by a flag byte, then a 2-byte jump address. The flag byte controls parameter processing behavior at 5406H and 541BH.
54E8H - "LIST" Command Handler
This is the entry point for the LIST command (single letter "L"). It displays either a line number or text string on the output device.
54EEH - "EDIT" Command Handler
This is the entry point for the EDIT command (single letter "E").
54F3H - "DELETE" Command Handler
This is the entry point for the DELETE command (single letter "D").
54FAH - "AUTO" Command Handler
This is the entry point for the AUTO command (single letter "A"). AUTO enables automatic line numbering mode for entering BASIC programs.
54FFH - DOS System Flag Check and AUTO Processing
This section checks a DOS system flag to determine if chaining is active, then processes AUTO command parameters including output control and file operations.
[CHAINING ACTIVE - Remove Quotes from String]
When chaining is active (typically during CMD"F" execution), remove embedded quotes from strings in BASIC program.
[QUOTE FOUND - Check for Double Quotes]
Found a quote character. Check if it's a doubled quote (escaped quote within string).
[NOT A DOUBLED QUOTE - Convert Character]
This is the closing quote. Convert the character for processing.
[CHECK FOR END OF LINE]
Check if we've reached the end marker or special token.
[PREPARE FOR OUTPUT CONTROL]
Set up for checking output redirection and file operations.
[NORMAL EXIT PATH]
Not end of input. Clean up and return.
[END OF INPUT - Stack Cleanup Loop]
End of input detected (FFH marker found). Clean up stack and prepare for AUTO mode execution.
[AUTO MODE PROCESSING]
Stack cleaned. Now set up for AUTO mode line numbering or special command execution.
[SPECIAL MODE - Value Less Than 20H]
The command byte is less than 32 (space). Process as special command code.
[A WAS 01H - Clear Program and Reset]
The command value was 01H (decremented to 00H). This triggers program clearing.
[ALTERNATE PATH - Value >= 20H]
Command byte is 32 or greater. Use different processing.
555EH - NOP Padding Area (Reserved Space)
From 555EH through 56E7H is filled with NOP (No Operation) instructions. This reserved space of approximately 394 bytes allows for future expansion or modifications without requiring relocation of code that follows. The NOP padding creates a memory boundary and simplifies version updates.