TRS-80 DOS - LDOS 5.3.1 for the Model I - BASIC/OV3 Disassembled
Page Customization
Page Index
BASIC/OV3
Other Navigation
Summary:
LDOS 5.3.1 BASIC/OV3 Disassembly - LBASIC Error Dictionary, Array Sort, Chained Load and Line Edit (Model I)
BASIC/OV3 is the one LBASIC overlay that has to be on the disk whenever DOS version 5 BASIC is running. The other three are loaded on demand by a single CMD statement and replace LBASIC's own image while they run; BASIC/OV3 is a subroutine library that LBASIC calls back into repeatedly, and the MISOSYS BASIC Reference Manual says plainly that it must always be present when programming in BASIC. It carries six services behind one entry point: the long error message dictionary that turns a Level II error number into English text, the translator that maps an LDOS error number onto a BASIC one, the CMD"O" string array sort, the machinery that keeps the variables alive across a chained load, and the two DOS version 5 single-key program line edit commands, M and C.
The overlay is a single LDOS load module of 1229 bytes: one type 1FH copyright record carrying "Copyright 1991 MISOSYS, Inc., All rights reserved", five type 01H load records and a type 02H transfer record. The image is contiguous at 4E00H-5281H, 1154 bytes with no gaps, and the transfer address is 4E00H. Alone among the four BASIC overlays it loads at 4E00H rather than 5200H, which is what lets it be a subroutine rather than a program: 4E00H-51FFH is the numbered SYS overlay area, free while a /CMD program is running, and BASIC/CMD has already emptied it by copying its two RAM hook images out to 4152H and 4000H during start-up. The top of the image, 5200H-5281H, does overlap BASIC/CMD's own banner, message and parameter table block, which is safe because none of that data is referenced once BASIC has started.
Entry is always at 4E00H with a FUNCTION SELECTOR in the alternate accumulator. The caller does LD A,n followed by EX AF,AF' before calling BASIC/CMD's loader at 54B6H, because the loader needs the primary accumulator for OVRLY$ and for the @LOAD error code. The first two instructions of the overlay write 01H into OVRLY$ at 430EH, and it is that byte the loader tests: when it already holds 01H the overlay is entered with no disk access at all. The overlay issues no RST 28H supervisor request of its own and calls no resident LDOS routine; every external call it makes is to a Level II ROM entry point, and the only LDOS cell it touches is OVRLY$.
The error dictionary is built the same way SYS4 builds the DOS error dictionary, and the resemblance is close enough to be deliberate. Messages are not stored as strings. A dictionary of seventy-seven English words holds each word once, with bit 7 set on its final character; an index table holds one entry per message, each entry a run of word numbers with bit 7 set on the last; and the expander walks both tables counting bit-7 bytes, so neither table needs offsets. Forty-nine messages are built from 428 bytes of dictionary and 127 bytes of index. The finished text is assembled into a buffer at 5414H, inside the block of BASIC/CMD start-up code that runs once and is never re-entered, which is the same space-reclaiming trick BASIC/CMD uses for its keyboard line buffer at 5309H and its DOS vector save area at 540AH.
File Format and Load Map
| Record | Contents |
|---|---|
| Type 1FH 49 bytes | Copyright comment record, "Copyright 1991 MISOSYS, Inc., All rights reserved". Not executable and not loaded. |
| Type 01H 5 records | Load records for 4E00H, 4F00H, 5000H and 5100H of 256 bytes each and 5200H of 130 bytes, giving a contiguous image at 4E00H-5281H, 1154 bytes with no gaps and no byte loaded twice. |
| Type 02H 2 bytes | Transfer address record, 4E00H. There are no type 07H patch records, so no LDOS /FIX patch has been applied to this copy. |
Memory Map
| Address Range | Purpose |
|---|---|
| 4E00H-4E1AH 27 bytes | Entry point, OVRLY$ marker and the six-way function selector dispatcher. |
| 4E1BH-4E6AH 80 bytes | Selector 01H, expand a BASIC error number into its full message text. |
| 4E6BH-4E7FH 21 bytes | Selector 02H, translate an LDOS error number into a BASIC error and enter the ROM error handler. |
| 4E80H-4F18H 153 bytes | Selector 03H, the CMD"O" string array sort. Argument parsing at 4E80H, the gap loop at 4E95H, the comparison and exchange at 4EADH. |
| 4F19H-4FD5H 189 bytes | Selector 04H, retain the variables across a chained load. Simple variables at 4F19H, arrays at 4F3FH, the string relocator at 4F6AH, the block park at 4F99H. |
| 4FD6H-502CH 87 bytes | Selectors 05H and 06H, the M and C program line edit commands, sharing one body through the overlapping entry at 4FD6H and 4FD7H. |
| 502DH-5056H 42 bytes | Data. LDOS error number to BASIC error value table, one byte per LDOS error number 0 to 41. |
| 5057H-50D5H 127 bytes | Data. Message index table, 49 entries of word numbers with bit 7 set on the last of each. |
| 50D6H-5281H 428 bytes | Data. Word dictionary, a marker byte followed by 77 words with bit 7 set on the final character of each. |
Function Selectors
| Selector | Entry | Called From | Service |
|---|---|---|---|
| 01H | 4E1BH | BASIC/CMD 5A42H | Expand A Basic Error Number Register L holds the ROM error value, twice the documented BASIC error code. Returns Register Pair HL pointing at the assembled message text at 5414H, which the caller displays with ROM STROUT at 28A7H. |
| 02H | 4E6BH | BASIC/CMD 644FH | Translate An Ldos Error Number Register L holds the LDOS error number, already masked to 0 to 63 by the CMD string shell. Saves it in 65F7H for CMD"E", looks the BASIC error value up in the table at 502DH and jumps to the ROM error entry at 19A2H. Does not return. |
| 03H | 4E80H | BASIC/CMD 5834H | Sort A String Array CMD"O",numelem,firstelem. Register Pair HL points at the BASIC text after the closing quotation mark. A Shell sort with the gap starting at half the element count, exchanging three-byte string descriptors rather than string text. |
| 04H | 4F19H | BASIC/CMD 5EB0H | Retain The Variables Across A Chained Load Reached from RUN"filespec",V and LOAD"filespec",V. Voids DEF FN definitions, lifts string constants out of the program into string space, parks the whole variable block below the stack, lowers STKTOP to protect it, fills in the five operand cells 5F5EH, 5F65H, 5F71H, 5F7EH and 5F84H in BASIC/CMD and writes 0D6H to the chain state byte 65F4H. |
| 05H | 4FD6H | BASIC/CMD 6459H | Move A Program Line M n1,n2. Untokenizes line n1 into the line input buffer, re-enters it as line n2, then deletes line n1 by way of a temporary diversion of the Disk BASIC keyboard line input slot at 41AFH. |
| 06H | 4FD7H | BASIC/CMD 6459H | Copy A Program Line C n1,n2. The same body as selector 05H without the deletion. 4FD7H is the second byte of the instruction at 4FD6H, so one two-byte sequence provides both entries. |
Self-Modifying Code and Work Cells
| Address Range | Purpose |
|---|---|
| 4EA0H-4EA1H 2 bytes | Operand of the LD HL,0000H at 4E9FH. Written at 4E85H with the CMD"O" element count. Read once per sort pass to work out the number of comparison positions. |
| 4EAEH-4EAFH 2 bytes | Operand of the LD HL,0000H at 4EADH. The CURRENT ELEMENT POSITION of the sort pass. Zeroed at 4EAAH, incremented at 4F0BH. |
| 4EB4H-4EB5H 2 bytes | Operand of the LD HL,0000H at 4EB3H. The WORKING POSITION of the sift-down loop. Seeded from the current position at 4EB0H and stepped down one gap at a time at 4EFDH. |
| 4EBBH-4EBCH 2 bytes | Operand of the LD DE,0000H at 4EBAH. The address of the first element's string descriptor, written at 4E8FH from the value ROM PTRGET returned for the firstelem argument. |
| 4F0FH-4F10H 2 bytes | Operand of the LD DE,0000H at 4F0EH. The pass length, element count less gap, written at 4EA4H each time the gap is halved. |
| 5023H-5024H 2 bytes | Operand of the LD DE,0000H at 5022H. The source line number of an M command, written at 4FE3H and read back only on the move path after the new line has been entered. |
| 5414H up to 30 bytes | Not in this overlay. The message assembly buffer, inside BASIC/CMD's once-only start-up code between the MEM range check and the sign-on banner. BASIC/CMD's filespec builder at 62A1H stages filenames in the same place; the two uses never overlap because a message is assembled and printed immediately. |
| 65F7H 1 byte | Not in this overlay. BASIC/CMD's LAST DOS ERROR cell. Selector 02H at 4E6CH is its only writer; BASIC/CMD's CMD"E" handler at 584AH is its only reader. |
| 65F4H 1 byte | Not in this overlay. BASIC/CMD's chain state byte. Selector 04H at 4FD2H is the only place the value 0D6H, meaning a chained load with variables is in progress, is ever written. |
| 5F5EH, 5F65H, 5F71H, 5F7EH, 5F84H 2 bytes each | Not in this overlay. The five 16-bit operand cells in BASIC/CMD's chained-load fixup at 5F54H. All five ship as 0000H in the BASIC/CMD image and no instruction in BASIC/CMD writes any of them; selector 04H at 4F9CH, 4FBDH, 4FA4H, 4FC3H and 4FC9H is their only source. |
| 41B0H-41B1H 2 bytes | Not in this overlay. The operand of the JP in the Disk BASIC vector table slot at 41AFH, the ROM keyboard line input exit. Selector 05H points it at 501AH at 5012H and puts BASIC/CMD's 5BD1H back at 501DH. |
Major Routines
| Address | Name and Purpose |
|---|---|
| 4E00H | Overlay Entry And Selector Dispatcher Entry: function selector in the alternate accumulator. Writes 01H to OVRLY$ 430EH, brings the selector into Register A with EX AF,AF' and dispatches on 01H to 06H by successive DEC A tests. |
| 4E1BH | Expand A Basic Error Number Entry: Register L is the ROM error value. Exit: Register Pair HL points at the assembled text at 5414H, zero terminated, first letter capitalized. Registers A, B, DE and HL are used. |
| 4E36H | Index Table Entry Skipper Entry: Register B is the entry number, Register Pair HL is 5057H. Exit: Register Pair HL points at the first word number of the wanted message. Counts complete entries by their bit-7 terminators. |
| 4E4AH | Dictionary Word Skipper Entry: Register B is the word number, Register Pair HL is 50D6H. Exit: Register Pair HL points at the first character of the wanted word. The same counting trick as 4E36H. |
| 4E6BH | Translate An Ldos Error Number Entry: Register L is the LDOS error number. Records it in 65F7H, clamps it to 41, indexes the table at 502DH and jumps to ROM 19A2H with the BASIC error value in Register E. Does not return. |
| 4E80H | Cmd O Argument Parser Entry: Register Pair HL is at the BASIC text after the CMD string. Requires a comma, evaluates the element count through ROM INTID2 at 1E46H, requires a second comma and locates the first element through ROM PTRGET at 260DH, planting both results in self-modified operands. |
| 4E95H | Sort Gap Loop Halves the gap in Register Pair BC, works out the pass length and resets the element position. Returns to the caller of the CMD statement when the gap reaches zero. |
| 4EADH | Sort Compare And Exchange Compares the descriptors at the working position and one gap above it, character by character over the shorter length and then by length, and exchanges the three-byte descriptors if they are out of ascending order. An exchange sifts the element down another gap. |
| 4F19H | Chained Load, Simple Variable Pass Walks VARTAB to ARYTAB. Voids the definition pointer of every DEF FN entry and passes every string descriptor to 4F6AH. |
| 4F3FH | Chained Load, Array Pass Walks ARYTAB to STREND. Steps whole numeric arrays in one addition and passes every element of a string array to 4F6AH. |
| 4F6AH | Move One String Body Into String Space Entry: Register Pair HL at a three-byte descriptor, Register Pair DE at the top of the region being scanned. Copies the text through ROM GETSPA at 28BFH and rewrites the descriptor only when the text lies between TXTTAB and that ceiling. Exit: Register Pair HL advanced by three, Register Pair DE unchanged. |
| 4F99H | Park The Variable Block Moves VARTAB to STREND up to the stack pointer less 128 with LDDR, raises Out of memory through ROM 197AH if it will not fit, lowers STKTOP to protect it and fills in the five BASIC/CMD operand cells and the chain state byte. |
| 4FD6H | Move And Copy A Program Line Parses two line numbers, requires the first to exist and the second not to, untokenizes the first through ROM BUFLIN at 2B7EH and re-enters it under the second number. The move path additionally deletes the original through ROM DELETE at 2BCAH. |
Cross-Reference Notes
BASIC/OV3 is called only by BASIC/CMD, and always through BASIC/CMD's loader at 54B6H. The six call sites are 5A42H (long error messages, selector 01H), 644FH (DOS error translation, selector 02H), 5834H (CMD"O", selector 03H), 5EB0H (RUN and LOAD with the V option, selector 04H) and 6459H twice, through the one-letter abbreviation table at 656BH where M carries selector 05H and C carries 06H. Because selector 02H ends by jumping to the ROM error entry itself, the JP 19A2H at BASIC/CMD 6456H that follows that call is never reached.
The overlay makes no RST 28H supervisor request and calls no resident LDOS routine. OVRLY$ at 430EH is the only LDOS cell it touches, and it is written once, at 4E02H, as the resident marker BASIC/CMD's loader tests. Everything else it reads or writes below 4200H is a Level II BASIC RAM cell: STKTOP 40A0H, TXTTAB 40A4H, FRETOP 40D6H, VARTAB 40F9H, ARYTAB 40FBH, STREND 40FDH and the Disk BASIC vector table slot operand at 41B0H.
The Level II ROM entry points it uses are the error entries 1997H, 197AH, 19A2H, 1E4AH and 1ED9H, the line number parser LINSPC 1E4FH, the positive integer evaluator INTID2 1E46H, the line finder FNDLIN 1B2CH, the variable locator PTRGET 260DH, the string space allocator GETSPA 28BFH and the untokenizer BUFLIN 2B7EH, plus the RST 08H, RST 10H and RST 18H hooks at 4000H, 4003H and 4006H, which LBASIC has already pointed at the ROM or at its own replacements.
Two of the ROM entries are taken part way into a routine rather than at its front door, and both are worth knowing about in their own right. EDITRT at 2FEBH is the common exit of the EDIT command: it reloads Register Pair HL from BUFPNT at 40A7H, returns at once if the Z FLAG says there is no line number, and otherwise sets the CARRY FLAG to mark a line number as already collected and jumps to EDENT at 1A98H, which tokenizes the buffer and inserts it as the line numbered in Register Pair DE. That is the whole of how a line is entered without being typed. 2BCAH is three instructions into DELETE, past the range scan SCNLIN at 1B10H and the POP DE that follows it, and expects Register Pair BC pointing at the first line of the range with Register Pair DE holding the last line NUMBER of the range; because FNDLIN preserves Register Pair DE, one call to FNDLIN sets up both and produces a range of one line.
Three cells inside BASIC/CMD's image are written from here and nowhere else: the chain state byte 65F4H when it holds 0D6H, the last DOS error byte 65F7H, and the five operand cells of the chained-load fixup at 5F54H. The message assembly buffer at 5414H and the line input buffer reached through BUFPNT 40A7H are both shared with BASIC/CMD, and in both cases the sharing is safe because the BASIC/CMD code that occupies those addresses runs only once, during start-up.
Disassembly:
4E00H - Overlay Entry Point and Function Selector Dispatcher
BASIC/OV3 is a SUBROUTINE overlay, not a program. BASIC/CMD loads it at 4E00H through the loader at 54B6H and enters it with a RET, so the overlay is reached with BASIC/CMD's own return address on the stack and every selector path here ends by returning to it. The function selector is carried in the ALTERNATE accumulator because the loader needs the primary accumulator for OVRLY$ and for the @LOAD error code, so the first thing the dispatcher does after marking itself resident is EX AF,AF' to bring the selector into Register A. Six selectors are implemented.
Selector Summary
01H expand a BASIC error number (called from BASIC/CMD 5A42H, the long error message handler). 02H translate an LDOS error number (called from BASIC/CMD 644FH, the DOS error translator). 03H sort a string array (called from BASIC/CMD 5834H, the CMD"O" handler). 04H retain variables across a chained load (called from BASIC/CMD 5EB0H, the RUN"filespec",V and LOAD"filespec",V path). 05H move a program line and 06H copy a program line (both called from BASIC/CMD 6459H, the READY prompt line collector, through the abbreviation table at 656BH where the letters M and C carry the selector values 05H and 06H).
4E1BH - Selector 01H: Expand a BASIC Error Number into Message Text
Level II BASIC in ROM prints two-letter error abbreviations. LBASIC replaces that with full English text by hooking the ROM error path, and this routine is the dictionary lookup behind it. Register L arrives holding the ROM error value, which is twice the documented BASIC error code. The routine converts that value to an index, walks the message index table at 5057H to the matching entry, then walks the word dictionary at 50D6H once per word number in the entry, copying the words into a buffer with single spaces between them. It returns Register Pair HL pointing at the assembled text so the caller can hand it to the ROM string printer STROUT at 28A7H.
Fetch one byte of the message index table into Register A from the address in Register Pair HL, which walks forward from 5057H.
On exit Register Pair HL points at the first word number of the wanted message.
Fetch the next WORD NUMBER of this message into Register A from the address in Register Pair HL, which points into the message index table entry selected above.
Fetch one dictionary character into Register A from the address in Register Pair HL.
On exit Register Pair HL points at the first character of the wanted dictionary word.
Fetch one character of the wanted word into Register A from the address in Register Pair HL.
4E6BH - Selector 02H: Translate an LDOS Error Number into a BASIC Error
When a disk operation fails, LDOS returns an error number of its own that has no meaning to Level II BASIC. This routine records that number for later inspection by CMD"E" and then converts it into a Level II error value through the 42-entry lookup table at 502DH, entering the ROM error handler with the result. It never returns.
4E80H - Selector 03H: CMD"O" String Array Sort, Argument Parsing
CMD"O",numelem,firstelem sorts a singly dimensioned string array in place. The manual states that the sort starts at the element given and covers the number of elements given, and that the count must not run past the end of the array; nothing in this code checks that, so the caller carries the responsibility. BASIC/CMD reaches here with a JP rather than a CALL, from the CMD"O" stub at 5834H, so this routine's RET returns to whatever called the CMD statement handler. On entry Register Pair HL points at the BASIC text immediately after the closing quotation mark of the CMD string.
Store the element count (Register Pair DE, just evaluated) into 4EA0H, which is the 16-bit operand of the LD HL,0000H instruction at 4E9FH. The listing shows the assembled 0000H; at run time that instruction loads Register Pair HL with the element count so the outer gap loop can work out how many comparison positions each pass has.
Store the address of the first element's string descriptor (Register Pair DE, returned by PTRGET) into 4EBBH, which is the 16-bit operand of the LD DE,0000H instruction at 4EBAH. The listing shows the assembled 0000H; at run time that instruction supplies the base address that every element offset is measured from.
4E95H - CMD"O" Sort: Halve the Gap and Test for Completion
The sort is a Shell sort. The gap starts at half the element count and is halved on every pass; when it reaches zero the array is ordered and the routine returns. This block is the top of the outer loop, re-entered from 4F16H after every complete pass.
Shift Register B, the high byte of the current gap in Register Pair BC, right one place with a zero shifted into bit 7. The bit shifted out goes to the CARRY FLAG so that it can be brought into the low byte next. On the first pass Register Pair BC holds the element count.
Load Register Pair HL with the ELEMENT COUNT. The operand at 4EA0H is shown as 0000H in the listing and is written at 4E85H with the value of numelem parsed from the CMD"O" statement.
Store that pass length (Register Pair HL) into 4F0FH, the 16-bit operand of the LD DE,0000H instruction at 4F0EH. The listing shows the assembled 0000H; at run time that instruction reloads the pass length so the inner loop at 4F07H can tell when the pass is finished.
Store zero (Register Pair HL) into 4EAEH, the 16-bit operand of the LD HL,0000H instruction at 4EADH. That instruction is the head of the pass loop and 4EAEH is therefore the CURRENT ELEMENT POSITION counter, held inside the instruction that reads it rather than in a separate cell.
4EADH - CMD"O" Sort: Compare and Exchange
One position of one pass. The element at the current position and the element a gap above it are compared as strings, and if they are out of order their three-byte descriptors are exchanged and the comparison is repeated a gap lower down, which is what turns a plain gapped exchange into a proper Shell sort. Level II holds a string variable as a three-byte descriptor of length followed by text address, so exchanging descriptors reorders the array without moving any string text.
Self-Modifying Code
Load Register Pair HL with the CURRENT ELEMENT POSITION. The operand at 4EAEH is shown as 0000H in the listing, is zeroed at 4EAAH when the pass begins and is incremented at 4F07H after every position.
Copy the current element position (Register Pair HL) into 4EB4H, the 16-bit operand of the LD HL,0000H instruction at 4EB3H. 4EB4H is the WORKING POSITION, which starts at the current position and is stepped down by one gap at a time at 4EFBH each time an exchange is made.
Self-Modifying Code
Load Register Pair HL with the WORKING POSITION from the operand at 4EB4H, shown as 0000H in the listing and maintained at 4EB0H and 4EFDH. This is the head of the sift-down loop.
Load Register Pair DE with the ADDRESS OF THE FIRST ELEMENT'S DESCRIPTOR. The operand at 4EBBH is shown as 0000H in the listing and is written at 4E8FH with the value PTRGET returned for the firstelem argument.
Fetch one character of the PARTNER string into Register A from the address in Register Pair DE.
Falling out means the shorter string is a prefix of the longer one.
Fetch one byte of the partner element's descriptor, at the address in Register Pair HL, into Register C as temporary storage for the exchange.
Store the reduced working position (Register Pair HL) back into 4EB4H, the operand of the LD HL,0000H instruction at 4EB3H, so that the sift-down loop reads it on its next turn.
Store the advanced element position (Register Pair HL) back into 4EAEH, the operand of the LD HL,0000H instruction at 4EADH, which is the head of the pass loop.
Load Register Pair DE with the PASS LENGTH, the element count less the gap. The operand at 4F0FH is shown as 0000H in the listing and is written at 4EA4H each time the gap is halved.
4F19H - Selector 04H: Retain the Variables Across a Chained Load, Simple Variables
RUN"filespec",V and LOAD"filespec",V load a new program but keep the current variables. BASIC/CMD calls this selector from 5EB0H after the filespec has been parsed and BEFORE the ROM NEW at 5EC5H wipes the variable area, and everything the later fixup code at 5F54H needs is set up here, because nothing in BASIC/CMD writes any of it. The work is in three stages. First the simple variables are walked, function definitions are voided and any string whose text still lives inside the program is copied into string space so that it survives the load. Then the arrays are walked for the same reason. Finally the whole variable block is moved up under the stack and the five operand cells in BASIC/CMD are filled in. This block is the first stage.
Add the size of the previous variable's value (Register Pair BC) to the walk pointer in Register Pair HL, so that Register Pair HL points at the next simple variable entry. A Level II simple variable is a type byte, two name characters and then the value, and the three header bytes are stepped over one at a time below.
4F3FH - Chained Load: Walk the Arrays
The array table runs from ARYTAB to STREND. Each array is a type byte, two name characters, a two-byte block length, a dimension count, one two-byte size per dimension and then the elements. Only string arrays need attention, and for those every element descriptor is passed to the same relocator the simple variables used.
Call the ROM comparison routine DCOMPR through the RST 18H hook at 4006H, comparing Register Pair HL (the array walk pointer) with Register Pair DE (STREND at 40FDH). The Z FLAG is set when they are equal.
GOSUB to 4F6AH to examine the string descriptor at the address in Register Pair HL and copy its text into string space if the text lives inside the program. The routine leaves Register Pair HL pointing at the next descriptor.
4F6AH - Chained Load: Move One String Body into String Space
A Level II string variable is a three-byte descriptor of length followed by text address, and the text itself may live in one of two places. A string assigned from a quoted constant points straight into the program text, which costs nothing while that program is loaded but is worthless once it has been replaced. A string built at run time already lives in string space at the top of memory and needs no attention. This routine tells the two apart by two address comparisons and copies only the first kind, rewriting the descriptor to point at the new copy. Entry is with Register Pair HL at the descriptor and Register Pair DE at the top of the region being scanned. Exit is always with Register Pair HL advanced by three, so the caller can walk straight on.
4F99H - Chained Load: Park the Variable Block and Seed the BASIC/CMD Operand Cells
Every string that had to be rescued has been rescued, so the whole variable block from VARTAB to STREND can now be lifted out of the way and the load allowed to proceed. The block is moved to sit just below the stack, STKTOP is lowered to protect it, and the five 16-bit operand cells that BASIC/CMD's fixup code at 5F54H reads are filled in. Those five cells ship as 0000H in the BASIC/CMD image and NO instruction in BASIC/CMD ever writes them, so this is their only source. The chain-state byte 65F4H is set to 0D6H last, and that is likewise the only place in either module the value 0D6H is written.
4FD6H - Selectors 05H and 06H: the M and C Program Line Edit Commands
The two single-key edit commands that DOS version 5 LBASIC keeps in this overlay. C n1,n2 duplicates line n1 as a new line n2, and M n1,n2 does the same and then deletes n1. Line n1 must exist and line n2 must not. BASIC/CMD's READY prompt line collector at 6459H recognises the letters through its abbreviation table at 656BH, where M carries the selector value 05H and C carries 06H, and the manual notes that both commands clear the variables and close open files, which is a consequence of the line being re-entered through the ordinary tokenizer. The two selectors share one body: the difference is a single flag pushed at 4FD8H and tested at 500DH. Both entries lean on the ROM twice over. The new line is entered by handing the untokenized text to EDITRT at 2FEBH, the exit the EDIT command itself uses, and for a move the old line is removed by jumping into the DELETE body at 2BCAH with a one-line range already set up. Neither borrowed entry point is the routine's own front door, which is why the register conditions are spelled out on each row.
Overlapping Entry Points
4FD6H and 4FD7H occupy the same two bytes, F6 AF. Entered at 4FD6H the pair is the single instruction OR 0AFH; entered one byte later at 4FD7H the AF byte is executed on its own as XOR A. Both entries then fall into the common body at 4FD8H, carrying the NZ FLAG for a move and the Z FLAG for a copy. The address 4FD7H therefore has two valid readings, as the operand of the instruction at 4FD6H and as an instruction in its own right, and the disassembly above shows both.
Store the SOURCE line number (Register Pair DE) into 5023H, the 16-bit operand of the LD DE,0000H instruction at 5022H. The listing shows the assembled 0000H. 5022H is only reached on the move path, where the source line has to be found a second time so that it can be deleted, and this is how its number is carried across the re-entry into the tokenizer.
Reached through the Disk BASIC keyboard line input slot at 41AFH after the ROM has entered the new line. Point Register Pair HL at 5BD1H, BASIC/CMD's own keyboard line input routine, so that the diverted vector can be put back.
Load Register Pair DE with the SOURCE line number. The operand at 5023H is shown as 0000H in the listing and was written at 4FE3H with the first of the two line numbers parsed from the command.
JUMP to the Level II ROM Syntax error entry at 1997H. Reached from 4FDAH, 4FE1H, 4FFAH and 4FFEH, that is whenever the command line does not consist of two non-zero line numbers separated by a comma.
502DH - Data: LDOS Error Number to BASIC Error Value Table
Forty-two bytes, one per LDOS error number from 0 at 502DH to 41 at 5056H. Each byte is the value the Level II ROM error handler expects in Register E, which is twice the documented BASIC error code. LDOS distinguishes far more failures than BASIC has messages for, so the table is heavily many-to-one: twenty-one different LDOS numbers all report Disk I/O error, which is exactly why the manual recommends CMD"E" for the real reason. Selector 02H at 4E6BH is the only reader.
Overlapping Code And Data
The byte at 502DH has two valid readings. It is the high byte of the operand of the JP 1997H instruction at 502BH, the Syntax error exit of the M and C edit commands, and it is also entry 0 of the table below, the one addressed when the LDOS error number is zero. The address is therefore shown once at 502BH as part of the jump and once here as a table entry. The table base loaded at 4E6FH is 502DH, so the sharing is deliberate and saves one byte.
5057H - Data: Message Index Table
Forty-nine entries, 5057H to 50D5H. Each entry is a run of word numbers into the dictionary at 50D6H, with bit 7 set on the last of them, and the entries are laid out so that the entry number is the BASIC error code plus one for the ROM range and the code less twenty-four for the disk range. The expander at 4E36H reaches the entry it wants by counting bit-7 bytes, so the entries can be any length and no offset table is needed. This is the same three-table scheme SYS4 uses for the DOS error dictionary.
50D6H - Data: Word Dictionary
Seventy-seven English words plus a leading marker byte, 50D6H to 5281H, and the last data in the file. Each word is stored once in plain ASCII with bit 7 set on its final character, and messages are built by naming the words rather than by repeating them: "out" and "of" are each stored once and used by four messages, "file" by nine. Case is stored as written, so GOSUB, RESUME and FIELD keep their capitals while everything else is lowercase and gets its initial capital from the RES 5,(HL) at 4E68H.