DOSPLUS 3.5 for the Model I - RENUM/CMD Disassembled
Page Customization
Page Index
RENUM/CMD
Other Navigation
Introduction/Summary
DOSPLUS 3.5 RENUM/CMD Disassembly - CMD"RENUM", the Renumberer of a BASIC Program (Model I)
RENUM/CMD is the renumberer of Extended Disk BASIC, CMD"RENUM"; its heading reads RENUM - BASIC program renumberer - 1.7. It is a load module of 5 blocks, 1174 bytes, at 5200H-5695H, with the transfer address 5200H, after the two comment records (the name RENUM and the copyright notice). The Model I and Model III files are identical byte for byte, and so are the two pages apart from their links.
It runs only from Extended Disk BASIC: BASIC/CMD's CMD (5C48H) passes RENUM to CMNDI@ as a DOS command, the DOS loads RENUM/CMD at 5200H and calls it, and RENUM takes BASIC's text pointer off the stack (5212H). It ends at the ROM's READY, after the ROM has cleared the variables, or in one of the ROM's errors; either resets the stack. From the DOS command level it only shows its heading. TBASIC cannot run it, since its CMD runs no DOS commands.
The Statement
CMD"RENUM",nln,inc,sln,eln: the new number of the first line renumbered (10 as loaded), the increment (10), and the first and last lines of the range (0 and 65529); any of them may be left out, keeping its comma when a later one is given (5213H). CMD"RENUM",! checks the line references without renumbering (5220H). Before anything is changed RENUM shows Illegal function call for an increment of 0, a last line below the first, a new first number that is not above every line before the range (5266H), or new numbers that would reach the first line after the range (52A6H); it shows Overflow for a new number above 65529 (52AFH).
The Parts of RENUM/CMD
| Address | Contents |
|---|---|
| 5200H-5282H | The start and the parameters (5200H). |
| 5283H-52DCH | The new numbers, stored in the links (5283H). |
| 52DDH-530BH | The index of 128 line addresses (52DDH). |
| 530CH-535EH | A pass over the program, line by line (530CH). |
| 535FH-53EFH | The statements and the tokens that take line numbers (535FH). |
| 53F0H-5492H | A line reference: found, checked, counted or written (53F0H). |
| 5493H-5505H | The end of a pass: the move for the second pass and the new line numbers (5493H). |
| 5506H-5567H | The end test, the next line, the links, the bytes read and written (5506H, 5517H, 5523H, 5542H, 555CH). |
| 5568H-55AAH | The messages and the errors (5568H, 5599H). |
| 55ABH-5610H | Text output, a number read, a number written (55ABH, 55B4H, 55EBH). |
| 5611H-56AAH | The texts and the variables (5611H). |
How RENUM Works
A first walk over the program (5283H) works out every line's new number and stores it in the line's link, while the line number itself keeps the old number; the walk counts the lines and checks that each link points to the line after it (else Internal error). The end of the program is then marked FFFFH instead of 0000H, since a link may now hold the number 0, and the end test is changed to match (52D6H, 5506H). An index of 128 line addresses, every Nth line, is built in BASIC's input buffer (52DDH), so that a line can be found by a binary search and a short walk (53FFH).
Then come two passes over the text. Each statement is read byte by byte (535FH), spaces and line feeds passed over; a line number is looked for after GOTO, GOSUB and EDIT (a list separated by commas), after RUN, THEN, ELSE and RESUME (one number, then a list as for GOTO), after ERL and the AND, OR or relation that follows it, and after DELETE, LIST and LLIST (with . for the current line and - between two lines). ON ERROR GOTO 0 and RESUME 0 are not references; a label after GOTO is not a number, so labels are left alone, as the manual says. The first pass writes nothing: it shows Syntax error in and the line for a number too large, and Undefined line in and the line for a reference to a line that does not exist, and it adds up how much longer the program gets (5476H). If a message was shown, or for CMD"RENUM",!, the work ends there (5493H) and the links are rebuilt, so the program is as before. Otherwise the program is moved up by its greatest growth plus 256 bytes (Out of memory unless that leaves 86 bytes below the string space, 54A6H) and the second pass writes it back down from TXTTAB with each reference replaced by its new number (5467H). Last, each line's new number is moved from the link into the line number (54ECH), the links are rebuilt (5523H), the ROM clears the variables (550EH) and READY is shown.
Findings
Strings in quotes, REM and DATA are not passed over: only bytes with the values of the tokens count, and BASIC does not tokenize text typed there, but a graphics character with the value of one of the tokens (for example 8DH, GOTO) followed by digits is taken as a reference. The number after AUTO is not a reference. A reference with too many digits shows Syntax error, and the digits from the one that does not fit are then read as a new number (53F3H). The line number in a message is written straight into the display memory at the cursor address 4020H, not through the ROM's output (5586H). The last new number (5698H) is not set before a line after the range is compared with it, so with no line in the range that test uses whatever 5698H held (52A6H). An Illegal function call or Overflow in the first walk, after a line whose new number is 0 (a line 0 before the range, or a new first number 0), rebuilds the links only up to that line: the end test still looks for 0000H there and takes that link as the end of the program, so the lines from there on are lost (5523H).
Differences from the Manual
The manual (Disk BASIC, RENUM, pages 5-46 and 5-47) gives the parameters, their defaults and the ! check as the bytes take them. What it does not say: an increment of 0, a range the wrong way round and a new first number not above the lines before the range are Illegal function call errors, as is the overlap with the lines after the range that the manual mentions; a number above 65529 is Overflow; the messages are Syntax error and Undefined line, each with in and the line, and all of them are shown before RENUM stops without renumbering; the ! check still makes the range tests; the variables are cleared after a renumbering; RENUM needs free memory of the program's growth plus 256 bytes, and 86 more, even when the program does not grow.
Variables
RENUM/CMD Variables
| Address Size | Contents |
|---|---|
| 5689H-568AH 2 bytes | New number nln, 10 as loaded; then the next new number (5689H). |
| 568BH-568CH 2 bytes | Increment inc, 10 as loaded (568BH). |
| 568DH-568EH 2 bytes | First line sln, 0 as loaded (568DH). |
| 568FH-5690H 2 bytes | Last line eln, 65529 as loaded (568FH). |
| 5691H 1 byte | Check flag 21H after ! (5691H). |
| 5692H 1 byte | Pass 00H the first, 01H the second (5692H). |
| 5693H 1 byte | Error flag 01H once a message was shown (5693H). |
| 5694H-5695H 2 bytes | Greatest growth Of the program in the first pass (5694H). |
| 5696H 1 byte | ON flag An ON in the statement (5696H). |
| 5697H 1 byte | Zero flag A 0 is not a reference (5697H). |
| 5698H-5699H 2 bytes | Last new number The number given last (5698H). |
| 569AH-569BH 2 bytes | Growth The change in length so far (569AH). |
| 569CH-569DH 2 bytes | Index entry The next entry to match in the second pass (569CH). |
| 569EH-56A1H 4 bytes | Line places Where the current line is written to and read from (569EH, 56A0H). |
| 56A2H-56A3H 2 bytes | Old line number The line being read, for the messages (56A2H). |
| 56A4H-56A5H 2 bytes | Digit place Where a reference's digits are written (56A4H). |
| 56A6H-56AAH 5 bytes | Work area The digits made by the ROM's 132FH (56A6H). |
Memory Outside RENUM/CMD
| Address Size | Contents |
|---|---|
| 4020H-4021H 2 bytes | Cursor address The line number of a message is written there (5586H). |
| 40A0H-40A1H 2 bytes | String space RENUM keeps 86 bytes below it free (54C2H). |
| 40A4H-40A5H 2 bytes | TXTTAB The start of the program (5286H). |
| 40A7H-40A8H 2 bytes | Input buffer The place of the index, 256 bytes (52EDH). |
| 40F9H-40FAH 2 bytes | VARTAB The end of the program, set again at the end (553EH). |
| 4121H-4122H 2 bytes | Accumulator The integer converted to digits (55ECH). |
Outside Routines
| Address | Contents |
|---|---|
| 4467H | SYS0/SYS: DSPLY@, the heading (520CH). |
| 402DH | SYS0/SYS: EXIT@ (520FH). |
| 1E5AH | ROM: a line number as digits into Register Pair DE (522BH and others). |
| 1B2CH | ROM: find a line (5271H, 5279H). |
| 132FH | ROM: an integer as decimal digits (55F7H). |
| 032AH | ROM: output a character (55AEH, 5593H). |
| 1997H | ROM: Syntax error (5263H). |
| 1E4AH | ROM: Illegal function call (5243H, 526EH, 5280H). |
| 19A2H | ROM: the error routine (55A8H). |
| 1B5DH | ROM: clear the variables (5511H). |
| 1A19H | ROM: READY (5514H). |
Disassembly
5200H - CMD"RENUM"
RENUM/CMD's transfer address. RENUM is the renumberer of BASIC programs, run from Extended Disk BASIC as CMD"RENUM",nln,inc,sln,eln or CMD"RENUM",!: BASIC/CMD's CMD passes RENUM to CMNDI@ as a DOS command, and the DOS loads RENUM/CMD at 5200H and calls it. From the DOS command level (return address 402DH) it only shows its heading. From BASIC it takes the new first line number (5689H, 10 as loaded), the increment (568BH, 10), the first and last line of the range (568DH 0 and 568FH 65529) or the ! of the check alone (5691H), checks them against the program, and renumbers in two passes over the program. It ends at the ROM's READY.
5283H - Number the Lines
The first walk over the program, from TXTTAB. Each line's new number is worked out and stored in its link (the line number itself is kept until the end): a line before the range keeps its number, a line in the range gets the next new number (Overflow above 65529), and a line after the range keeps its number, which must be above the last new number (else Illegal function call: RENUM does not move lines). The walk also counts the lines in Register Pair BC and checks that each link points to the line after it (else Internal error).
52DDH - The Index
Builds a table of 128 line addresses in BASIC's input buffer (the address at 40A7H): with N lines in the program and a step S of N/128 rounded up (Register C), entry k is the address of line k times S, or the end of the program once that is passed. The table lets 53FFH find a line by a binary search before it walks the last few lines.
530CH - A Pass over the Program
Each pass reads every line from Register Pair HL. In the first pass (5692H = 00H) nothing is written: the line references are found and checked, the change in the length of the program is added up (569AH) and the greatest growth is kept (5694H). In the second pass (5692H = 01H) the program has been moved up (54A6H) and every byte read is written again from TXTTAB on at Register Pair BC (5545H), with each line reference replaced by its new number. Register Pair DE is set to 0000H for the length count at the start of each pass.
535FH - The Statements
Reads the text of a line byte by byte (copied in the second pass). Each statement starts with the flags 5696H (an ON seen) and 5697H (a 0 is not a line reference) cleared. The tokens that take line numbers are GOTO, GOSUB and EDIT (a list of numbers separated by commas), RUN, THEN, ELSE and RESUME (a number, then a list as for GOTO), ERL (numbers after AND, OR and the relations), DELETE, LIST and LLIST (a range with . and -), and ON and ERROR set the flags for ON ERROR GOTO. Strings in quotes, REM and DATA are not passed over.
53F0H - A Line Reference
Takes the number at Register Pair HL (55B4H) and looks up the line. A number above 6552 with another digit after it gives the message Syntax error; a 0 after ON ERROR GOTO or RESUME is left alone. The line is found through the index (a binary search) and the lines after the entry found. A line that does not exist gives the message Undefined line. In the first pass the length of the new number is counted; in the second the new number is written over the old one.
5493H - The End of a Pass
After the first pass the work ends if only a check was wanted (!) or a reference was wrong; the line numbers are then as they were. Otherwise the program is moved up by the greatest growth plus 256 bytes (Out of memory if it would come within 86 bytes of the string space at 40A0H), the index entries are moved with it, and the second pass writes it back down from TXTTAB. After the second pass each line's new number is moved from its link into its line number (54ECH). Then the links are rebuilt (5523H), the variables cleared (the ROM's 1B5DH) and READY shown.
5506H - The End Test
The Z FLAG when the word at Register Pair HL is the end mark: 0000H as loaded, FFFFH after 52DAH has stored FFH into the operand at 5507H.
5517H - The Next Line
5517H moves Register Pair HL from a line's link past the link, the line number and the text to the next line; 551AH does the same from the line number's high byte. The text is passed over with CPIR up to its 00H; Register Pair BC is kept.
5523H - Rebuild the Links
Walks the program from TXTTAB by its text (5517H), not by its links, and stores in each link the address of the line after it; the end mark becomes 0000H again and VARTAB is set after it. The end is found by 5506H, so before 52DAH a link that already holds the new number 0 is taken as the end.
5542H - Take a Byte
5542H passes over spaces and line feeds (5552H), then takes the next byte. 5545H takes the byte at Register Pair HL into Register A and moves Register Pair HL on; in the second pass it also writes the byte at Register Pair BC and moves Register Pair BC on. It returns the NC FLAG (and the Z FLAG in the first pass, the NZ FLAG in the second).
555CH - A Digit?
Passes over spaces and line feeds, then looks at the next byte: a digit is not taken and returns the C FLAG; any other byte is taken (5545H) and returned in Register A with the NC FLAG.
5568H - The Messages
5568H shows Syntax error, 556BH Undefined line (entered inside the LD DE,023EH at its bytes 3EH 02H, which read as LD A,02H), each followed by in and the number of the line being read (56A2H), and sets the error flag 5693H so that the program is not renumbered. The number is written straight into the display memory at the cursor address (4020H) and not through the ROM's output, so the cursor does not move over it, and a P for the printer does not apply; a carriage return ends the message.
5599H - The Errors
Four entries, each loading a BASIC error offset into Register B: 5599H Out of memory (0CH), 559CH Illegal function call (08H), 559FH Overflow (0AH), 55A2H Internal error (66H, a disk BASIC error). The entries after the first are each entered inside a LD DE,xx06H instruction, at its 06H xxH bytes, which read as LD B,xxH; from above they only load Register Pair DE. The links are rebuilt (5523H) before the ROM's error routine (19A2H).
55ABH - Show a Text
Shows the text at Register Pair HL up to its 00H through the ROM's 032AH.
55B4H - Take a Number
Takes the decimal digits at Register Pair HL (after spaces and line feeds) into Register Pair DE, copying them in the second pass. 56A4H keeps the place where the digits are written. Each digit is taken off the change in length (569AH). Returns the NC FLAG at the first byte that is not a digit, with Register Pair HL and Register Pair BC set back to that byte; returns the C FLAG, with that digit not taken, when the number is above 6552 and another digit follows.
55EBH - Write a Number
Writes the decimal digits of Register Pair DE at Register Pair BC, without leading zeros (at least one digit), and returns Register E the count of the digits, Register D 00H, Register Pair BC past the digits. The digits are made by the ROM's 132FH in the work area 56A6H.
5611H - The Texts and the Variables
Data. The values 5689H-5695H are in the file; 5696H on is not loaded.