TRS-80 DOS – TRSDOS v1.3 – SYS13/SYS Disassembled

General:

SYS13/SYS handles the CMD “J”, CMD “O”, and CMD “X” functions.

CMD”J” converts a calendar date to julian.

The format is CMD”J”,s,d. S is the source date and D is the variable to contain the converted date.

CMD”O” sorts an array.

The format is CMD”O”,exp,array(start). exp is the number of elements.

CMD”X” is a cross reference utility.

The format is CMD”X”,target.



Disassembly:

 
ORG 4E00H
“START”
4E00
AND 0F0H
MASK off the SYSTEM NUMBER from the byte passed to this OVERLAY by masking against F0H (1111 0000). This has the effect of turning off bits 3, 2, 1, 0, leaving only bits 7, 6, 5, 4 active.
4E02
CP 80H
Compare the remainder of Register A against 80H, which would be the SORT function call. If the masked value is 80H, then …
4E04
JR Z,4E13H
     [4E13H]
… JUMP to 4E13H.
4E06
CP 90H
Compare the remainder of Register A against 90H, which would be the JULIAN DATE CONVERSION function call. If the masked value is 90H, then …
4E08
JP Z,4EE3H
     [4EE3H]
… JUMP to 4EE3H.
4E0B
CP 0A0H
Compare the remainder of Register A against A0H, which would be the CROSS REFERENCE function call. If the masked value is A0H, then …
4E0D
JP Z,5102H
     [5102H]
… JUMP to 5102H.
4E10
JP 1E4AH
   [1E4AH]
If none of those functions were called, then return to BASIC with a “?FC ERROR” via a JUMP to 1E4AH.

4E13H – “SORT” Routine Main Routine. On Entry BASIC1 = Number of variables to sort and BASIC2 = VARPTR for the variables to sort.

“SORT”
4E13
LD HL,(BASIC2)
Fetch the VARPTR pointer from memory location 4274H and store it into Register Pair HL.
4E16
LD (VARPTR),HL
Store the VARPTR pointer into memory location 4EE1H.
4E19
LD HL,(BASIC1)
Fetch the NUMBER OF VARIABLES from memory location 4272H and store it into Register Pair HL.
4E1C
4E1F
LD (NUMB0),HL
LD (NUMB1),HL
Store the NUMBER OF VARIABLES into 4ED5H and 4EDFH.
“LAB2”
4E22
LD DE,(NUMB1)
Fetch the NUMBER OF VARIABLES from 4EDFH and store it into Register Pair DE.
4E26
SRL E
Shift the contents of Register E right one bit position with bit 0 moved to the carry flag and a zero is put into bit 7, so 76543210[x] becomes 07654321[0].
4E28
XOR A
Set Register A to ZERO and clear all Flags.
4E29
SRL D
Shift the contents of Register D right one bit position with bit 0 moved to the carry flag and a zero is put into bit 7, so 76543210[x] becomes 07654321[0].
4E2B
JR NC,LAB3
      [4E2FH]
If Bit 0 of Register D wasn’t a 0, the NC FLAG will be set, so JUMP to 4E2FH.
4E2D
SET 7,E
If Bit 0 of Register D was a 0, SET (i.e., set as 1) BIT 7 of Register E (the one bit which was set to 0 via the SRL).
“”
4E2F
LD (NUMB1),DE
Store the modified/rotated NUMBER OF VARIABLES held in Register Pair DE into memory location 4EDFH.
4E33
4E33
LD A,D
OR E
Since the Z-80 cannot test Register Pair DE against zero, the common trick is to set Register A to equal to Register D, and then OR A against Register E. Only if both Register D and Register E were zero can the Z FLAG be set.
4E35
RET Z
If we were given 0 variables to sort, RETurn to the caller.
4E36
LD HL,(NUMB0)
Otherwise, fetch the original NUMBER OF VARIABLES from memory location 4ED5H and store it into Register Pair HL.
4E39
SBC HL,DE
Subtract the modified/shifted NUMBER OF VARIABLES (held in DE) from the original NUMBER OF VARIABLES (held in Register Pair HL).
4E3B
LD (LAB15),HL
Store that difference into memory location 4EDBH.
4E3E
LD HL,0000H
Let Register Pair HL equal 0000H.
4E41
LD (LAB14),HL
Store a 0000H into memory location 4ED9H.
“LAB4”
4E44
LD HL,(LAB14)
Fetch the value held in memory location 4ED9H (which will be 0000H on a pass through) and store it into Register Pair HL.
4E47
LD (LAB13),HL
Store the value held in Register Pair HL (which will be 0000H on a pass through) into memory location 4ED7H.
“LAB5”
4E4A
LD HL,(LAB13)
Fetch the value held in memory location 4ED7H (which will be 0000H on a pass through) and store it into Register Pair HL.
4E4D
LD DE,(NUMB1)
Fetch the value held in memory location 4EDFH and store it into Register Pair DE.
4E51
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E52
LD (LAB16),HL
Store the value held in Register Pair HL into memory location 4EDDH.
4E55
EX DE,HL
Let DE = HL. We don’t care what was in DE at the time of this EXchange because HL will be overwritten.

The next few instructions set HL = DE * 3

4E56
LD HL,0000H
Let Register Pair HL equal 0000H.
4E59
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E5A
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E5B
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E5C
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
4E5D
LD DE,(LAB13)
Fetch the value held in memory location 4ED7H and store it into Register Pair DE.

The next few instructions set HL = DE * 3

4E61
LD HL,0000H
Let Register Pair HL equal 0000H.
4E64
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E65
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E66
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4E67
LD BC,(VARPTR)
Fetch the value held in memory location 4EE1H and store it into Register Pair BC.
4E6B
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC.
4E6C
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4E6D
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
4E6E
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC.
4E6F
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
4E70
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
4E71
LD C,00H
Let Register C equal 00H.
4E73
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A.
4E74
LD B,A
Copy the contents of Register A into Register B.
4E75
LD A,(DE)
Fetch the value held in the memory location pointed to by Register Pair DE and store it into Register A.
4E76
CP B
Compare the value held in Register A against the value held in Register B. Results:
  • If Register A equals the value held in Register B, the Z FLAG is set.
  • If A < B/ 160/, the CARRY FLAG will be set.
  • if A >= B/ 160/, the NO CARRY FLAG will be set.
4E77
JR NC,LAB6
      [4E7CH]
If the NC FLAG (No Carry) has been set, JUMP to 4E7CH.
4E79
LD C,01H
Let Register C equal 01H.
4E7B
LD B,A
Copy the contents of Register A into Register B.
“LAB6”
4E7C
XOR A
Set Register A to ZERO and clear all Flags.
4E7D
OR B
OR Register B against Register A. The results are stored in Register A.
4E7E
JR Z,LAB8
     [4E99H]
If the Z FLAG (Zero) has been set, JUMP to 4E99H.
4E80
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
4E81
INC DE
INCrement the value stored in Register Pair DE by 1.
4E82
INC HL
INCrement the value stored in Register Pair HL by 1.
4E83
LD C,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register C.
4E84
INC HL
INCrement the value stored in Register Pair HL by 1.
4E85
LD B,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register B.
4E86
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
4E87
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
4E88
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4E89
LD C,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register C.
4E8A
INC HL
INCrement the value stored in Register Pair HL by 1.
4E8B
LD B,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register B.
4E8C
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
4E8D
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
4E8E
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
“LAB7”
4E8F
LD A,(DE)
Top of a DJNZ loop. Fetch the value held in the memory location pointed to by Register Pair DE and store it into Register A.
4E90
SUB (HL)
LET Register A = Register A – Register Pair HL.
4E91
JR C,LAB9
     [4E9DH]
If the C FLAG (Carry) has been set, JUMP to 4E9DH.
4E93
JR NZ,LAB11
      [4EBCH]
If the NZ FLAG (Not Zero) has been set, JUMP to 4EBCH.
4E95
INC DE
INCrement the value stored in Register Pair DE by 1.
4E96
INC HL
INCrement the value stored in Register Pair HL by 1.
4E97
DJNZ LAB7
     [4E8FH]
LOOP back to 4E8FH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
“LAB8”
4E99
BIT 0,C
Test Bit Number 0 of Register C. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
4E9B
JR NZ,LAB11
      [4EBCH]
If the NZ FLAG (Not Zero) has been set, JUMP to 4EBCH.
“LAB9”
4E9D
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
4E9E
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
4E9F
LD B,03H
Let Register B equal 03H.
“LAB10”
4EA1
LD C,(HL)
Top of a DJNZ loop. Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register C.
4EA2
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4EA3
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A.
4EA4
LD (HL),C
Store the value held in Register C into the memory location pointed to by Register Pair HL.
4EA5
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4EA6
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL.
4EA7
INC HL
INCrement the value stored in Register Pair HL by 1.
4EA8
INC DE
INCrement the value stored in Register Pair DE by 1.
4EA9
DJNZ LAB10
     [4EA1H]
LOOP back to 4EA1H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
4EAB
LD DE,(NUMB1)
Fetch the value held in memory location 4EDFH and store it into Register Pair DE.
4EAF
LD HL,(LAB13)
Fetch the value held in memory location 4ED7H and store it into Register Pair HL.
4EB2
XOR A
Set Register A to ZERO and clear all Flags.
4EB3
SBC HL,DE
Subtracts the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
4EB5
LD (LAB13),HL
Store the value held in Register Pair HL into memory location 4ED7H.
4EB8
JR NC,LAB5
      [4E4AH]
If the NC FLAG (No Carry) has been set, JUMP to 4E4AH.
4EBA
JR LAB12
   [4EBEH]
JUMP to 4EBEH.

4EBCH – “SORT” Routine Main Routine.

“LAB11”
4EBC
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
4EBD
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
“LAB12”
4EBE
LD HL,(LAB14)
Fetch the value held in memory location 4ED9H and store it into Register Pair HL.
4EC1
LD DE,0001H
Let Register Pair DE equal 0001H.
4EC4
XOR A
Set Register A to ZERO and clear all Flags.
4EC5
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4EC6
LD (LAB14),HL
Store the value held in Register Pair HL into memory location 4ED9H.
4EC9
LD DE,(LAB15)
Fetch the value held in memory location 4EDBH and store it into Register Pair DE.
4ECD
SBC HL,DE
Subtracts the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
4ECF
JP C,LAB4
     [4E44H]
If the C FLAG (Carry) has been set, JUMP to 4E44H.
4ED2
JP LAB2
   [4E22H]
JUMP to 4E22H.

4ED5H – “SORT” Routine Byte Storage Area.

“NUMB0”
4ED5
DEFS 2
2 Bytes of Storage
“LAB13”
4ED7
DEFS 2
2 Bytes of Storage
“LAB14”
4ED9
DEFS 2
2 Bytes of Storage
“LAB15”
4EDA
DEFS 2
2 Bytes of Storage
“LAB16”
4EDC
DEFS 2
2 Bytes of Storage
“NUMB1”
4EDE
DEFS 2
2 Bytes of Storage
“VARPTR”
4EE0
DEFS 2
2 Bytes of Storage

4EE3H – Julian Date Conversion Routine Entry Point.

“RETJUL”
4EE3
LD HL,(BASIC1)
Fetch the text pointer (held in memory location 4272H) and store it into Register Pair HL.
4EE6
4EE7
RST 08H
2C
RST 08H is used to look for expected characters (in this case, a ,) in a string and then return with (HL) pointing to the next non-blank character.

It is a COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call.

If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A register and HL incremented by one. If the two characters do not match, a syntax error message is given.
4EE8
CALL FRMEVL
     [2337H]
Call the Model III ROM Routine to evaluate a BASIC expression at 2337H. This routine evaluates a BASIC expression pointed to by the HL and stores the result in the ACC. The expression must be terminated with zero byte, comma, right bracket or colon. After execution, HL will point to the delimiter and, in the case of string expressions, the ACC will contain the address of the first of three bytes that contain string length and string address..
4EEB
PUSH HL
Save the text pointer (held in Register Pair HL after that CALL) to the top of the stack.
4EEC
CALL FRESTR
     [29D7H]
Call the Model III ROM Routine at 29D7H to get a string’s VARPTR and put it in HL and the string’s length into Register A.
4EEF
LD A,(HL)
Fetch the byte count of the string into Register A.
4EF0
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
4EF1
JP Z,1E4AH
     [1E4AH]
If string length is 0, then return to BASIC with a “?FC ERROR” via a JUMP to 1E4AH.
4EF4
INC HL
INCrement the value stored in Register Pair HL by 1 so that HL will now point to the LSB of the RAM ADDRESS of the string.
4EF5
LD E,(HL)
Fetch the LSB of the RAM LOCATION OF THE STRING into Register E.
4EF6
INC HL
INCrement the value stored in Register Pair HL by 1 so that HL will now point to the MSB of the RAM ADDRESS of the string.
4EF7
LD H,(HL)
Fetch the MSB of the RAM LOCATION OF THE STRING into Register H.
4EF8
LD L,E
Copy the LSB of the RAM LOCATION OF THE STRING (held in Register E) into Register L so that HL now points to the RAM ADDRESS of the string.
4EF9
LD A,(HL)
Fetch the character at the RAM LOCATION OF THE STRING and store it into Register A.
4EFA
CP 2DH
Compare the value held in Register A against 2DH (ASCII: ). If that character is a then …
4EFC
JP Z,RETDAT
     [4F92H]
… the user wants to convert JULIAN to GREGORIAN. JUMP to 4F92H.
4EFF
CALL GETNX1
     [50BCH]
Otherwise, the user wants to covert a GREGORIAN date to JULIAN. Start via a GOSUB to 50BCH to fetch the user-supplied MONTH.
4F02
CP 0DH
Compare the user-supplied month (held in Register A) against 0DH (Decimal: 13). If the user supplied month >= 13, then we have an invalid month so …
4F04
JP NC,1997H
      [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4F07
LD (MT),A
Store the user-supplied month (held in Register A) into memory location 5588H.
4F0A
CALL GETNXT
     [50BAH]
GOSUB to 50BAH to fetch the user-supplied DAY.
4F0D
CP 20H
Compare the user-supplied day (held in Register A) against 20H (Decimal: 32). If the user-supplied month >= 32, then we have an invalid day so …
4F0F
JP NC,1997H
      [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4F12
LD (DY),A
Store the user-supplied day (held in Register A) into memory location 5589H.
4F15
CALL GETNXT
     [50BAH]
GOSUB to 50BAH to fetch the user-supplied YEAR.
4F18
CP 64H
Compare the user-supplied year (held in Register A) against 64H (Decimal: 100). If the user-supplied year >= 100, then we have an invalid year so …
4F1A
JP NC,1997H
      [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4F1D
LD (YR),A
Store the value held in Register A into memory location 5587H.
4F20
PUSH HL
Save the text pointer (held in Register Pair HL) to the top of the stack.
4F21
AND 03H
Test for a leap year. First, MASK the value of Register A against 03H (0000 0011) to leave only bits 1 and 0 active.
4F23
LD D,00H
Set up for a counter by initializing Register D to 00H.
4F25
LD IX,0000H
Set up for an accumulator by initializing Special Index Register IX to 0000H.
4F29
JR NZ,RETJU1
      [4F34H]
If AND caused Register A to be 00, then this was not a leap year, so skip over the leap year adjustment by JUMPing to 4F34H.
4F2B
LD A,(MT)
Fetch the month (held in memory location 5588H) and store it into Register A.
4F2E
CP 03H
Compare the month (held in Register A) against 03H. If the month is < 3 (so either January or February) …
4F30
JR C,RETJU1
     [4F34H]
… skip over the leap year adjustment by JUMPing to 4F34H.
4F32
INC IX
If we’re here, then we need to account for the leap year by adding a single day, so INCrement the value stored in Special Index Register IX by 1.
“RETJU1”
4F34
LD HL,0269H
Let Register Pair HL equal 0269H, which is the Model III ROM location which starts off the length of each of the 12 months (1F 1C 1F 1E 1F 1E 1F 1F 1E 1F 1E 1F).
4F37
LD A,(MT)
Fetch the month from memory location 5588H and store it into Register A.
4F3A
LD B,A
Copy the month into Register B.
4F3B
DEC B
DECrement the value stored in Register B by 1 to correct for 1’s offset.
4F3C
JR Z,4F45H
     [4F45H]
If the month was January, then the DEC caused the Z FLAG to trigger, so HL is already pointing to the right entry (January at 0269H). Skip over the month length lookup and JUMP directly to 4F45H.
“RETJU2”
4F3E
LD A,(HL)
Top of a DJNZ loop. Fetch the number of day in the month pointed to by HL into Register A.
4F3F
INC HL
INCrement HL to the next month.
4F40
LD E,A
Copy the prior fetched number days in the month (held in Register A) into Register E.
4F41
ADD IX,DE
LET Register Pair IX = Register Pair IX + Register DE (i.e., the day counter).
4F43
DJNZ 4F3EH
     [4F3EH]
LOOP back to 4F3EH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
“RETJU3”
4F45
LD A,(5589H)
Fetch the user-supplied day (held in memory location 5589H) and store it into Register A.
4F48
LD E,A
Copy the day (held in Register A) into Register E.
4F49
ADD IX,DE
Determine the JULIAN DATE (in hex) by setting Register Pair IX = Register Pair IX + the user supplied date (held in Register DE).
4F4B
4F4D
PUSH IX
POP HL
Let Register Pair HL = the JULIAN DATE (held in Special Index Register IX).
4F4E
CALL EDITM
     [50E6H]
Convert the hex JULIAN DATE to ASCII and edit the spaces via a GOSUB to 50E6H.
4F51
LD HL,4133H
Let Register Pair HL equal 4133H, which is where the JULIAN DATE is now stored in ASCII.
4F54
LD DE,RTEMP
Let Register Pair DE equal 558AH, which is a temporary storage location.
4F57
LD BC,0003H
Since a Julian date is 3 digits, set Register Pair BC equal 0003H.
4F5A
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4F5C
4F5D
POP HL
POP HL
Restore the TEXT POINTER from the top of the stack into Register Pair HL, and then remove the entry from the stack.
4F5E
RST 08H
2C
RST 08H is used to look for expected characters (in this case, a ,) in a string and then return with (HL) pointing to the next non-blank character.

It is a COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call.

If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A register and HL incremented by one. If the two characters do not match, a syntax error message is given.
4F60
CALL 260DH
     [260DH]
Get the pointer to the variable by GOSUBing to the Model III ROM FIND ADDRESS OF VARIABLE routine at 260DH which searches the Variable List Table for a variable name which matches the name in the string pointed to in HL, and return the address of that variable in DE (and if there is no variable, it creates it, zeroes it, and returns THAT location).
4F63
CALL 0AF4H
     [0AF4H]
Call the Model III ROM routine at 0AF4H to force REG1 to be a STRING. The routine calls 20H (RST 20H) and returns if NTF=3 (string) else if NTF is not 3 then it generates a ?TM ERROR.
4F66
PUSH HL
Save the TEXT POINTER (held in Register Pair HL) to the top of the stack.
4F67
LD A,(DE)
Fetch the length of the string (held at the memory location pointed to by Register Pair DE) and store it into Register A.
4F68
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
4F69
JR Z,RETJU4
     [4F74H]
If the length of the string was 0 then we need to allocate string space via a JUMP to 4F74H.
4F6B
PUSH DE
Save the pointer (held in Register Pair DE) to the top of the stack.
4F6C
EX DE,HL
Let HL = the pointer (held in Register Pair DE).
4F6D
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the address of the string.
4F6E
LD E,(HL)
Fetch the LSB of the address of the string (held in the memory location pointed to by Register Pair HL) and store it into Register E.
4F6F
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the address of the string.
4F70
LD D,(HL)
Fetch the MSB of the address of the string (held in the memory location pointed to by Register Pair HL) and store it into Register D.
4F71
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
4F72
JR RETJU5
   [4F7FH]
Continue via a JUMP to 4F7FH.

4F74H – Julian Date Conversion Routine. Jumped to if we need to allocate string space because the current length was 0.

“RETJU4”
4F74
PUSH DE
Save the pointer to the variable (held in Register Pair DE) to the top of the stack.
4F75
LD A,03H
We need to clear 3 bytes of storage so start by setting Register A to 03H.
4F77
CALL 2857H
     [2857H]
Set Up a String by GOSUBing to the Model III ROM Routine at 2857H. For that routine, Register A needs to hold the length of the string to be created.
4F7A
LD HL,(40D4H)
Fetch the address of the string being created (held at 40D4H) into Register Pair HL. 40D3H is the VARPTR storage area for string currently being created by BASIC. 40D3H is the length, 40D4H is the LSB of the address of the string, and 40D5H is the MSB of the address of the string.
4F7D
POP DE
Restore the address of the variable held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
4F7E
EX DE,HL
Put the pointer to the variable into Register Pair HL and the address of the variable into Register Pair DE.
“RETJU5”
4F7F
LD (HL),03H
Set the length of the string to 03H (which is the length of a JULIAN DATE).
4F81
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the LSB of the string.
4F82
LD (HL),E
Store the value held in Register E as the LSB of the string.
4F83
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the string.
4F84
LD (HL),D
Store the value held in Register D as the LSB of the string.
4F85
LD HL,RTEMP
Let Register Pair HL equal 558AH which is where the DATE is stored.
4F88
LD BC,0003H
Prepare for a LDIR by setting the bytes to move to 3.
4F8B
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4F8D
POP HL
Restore the TEXT POINTER (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
“RETEXT”
4F8E
LD (BASIC1),HL
Store the TEXT POINTER (held in Register Pair HL) into memory location 4272H.
4F91
RET
RETurn to the caller.

4F92H – Julian Date Conversion Routine. Jumped point to convert JULIAN to GREGORIAN.

“RETDAT”
4F92
INC HL
INCrement the TEXT POINTER (stored in Register Pair HL) by 1 to move past the .
4F93
CALL GETNX1
     [50BCH]
Get the YEAR via a GOSUB to 50BCH.
4F96
CP 64H
Compare the user-supplied year (held in Register A) against 64H (Decimal: 100). If the user-supplied year >= 100, then we have an invalid year so …
4F98
JP NC,1997H
      [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4F9B
LD (YR),A
Store the year (held in Register A) into memory location 5587H.
4F9E
CALL GETNXT
     [50BAH]
Get the next 2 characters via a GOSUB to 50BAH.
4FA1
PUSH AF
Save the first two digits (held in Register A) to the top of the stack.
4FA2
CALL GETACR
     [50D3H]
Get 1 more character via a GOSUB to 50D3H.
4FA5
POP BC
Restore the first two digits (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
4FA6
PUSH HL
Save the TEXT POINTER (held in Register Pair HL) to the top of the stack.

Start moving the characters around.

4FA7
LD L,B
Copy the first digit (held in Register B) into Register L.
4FA8
LD H,00H
Let Register H equal 00H, so now Register Pair HL = the first digit.
4FAA
LD E,A
Copy the last digit (held in Register A into Register E.
4FAB
LD D,H
Set Register D to 00H.
4FAC
4FAD
PUSH HL
POP BC
Copy the first two digits (held in Register Pair HL) to Register Pair BC.

HL = HL * 10 … to make it the first 2 digits into 100s and 10s digits.

4FAE
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL.
4FAF
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL.
4FB0
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC.
4FB1
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL.

HL = HL + the 1s Digit.

4FB2
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
4FB3
EX DE,HL
Swap DE and HL.
4FB4
4FB5
LD A,D
OR E
Since the Z-80 cannot test Register Pair DE against zero, the common trick is to set Register A to equal to Register D, and then OR A against Register E. Only if both Register D and Register E were zero can the Z FLAG be set.
4FB6
JP Z,1997H
     [1997H]
If the Z FLAG (Zero) has been set then the DAY was 0, so return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4FB9
LD HL,016EH
Let Register Pair HL equal 016EH (Decimal: 366), which is the maximum number of JULIAN days.
4FBC
LD A,(YR)
Fetch the value held in memory location 5587H and store it into Register A.
4FBF
AND 03H
Test for a leap year by MASKing the value of Register A against 03H.
4FC1
JR Z,REDA00
     [4FC4H]
If that mask leaves a ZERO then the value was 4 and we have a leap year … so skip over the next instruction by JUMPing to 4FC4H.
4FC3
DEC HL
DECrement the value stored in Register Pair HL by 1 to now be 365, which is the maximum number of JULIAN days without a leap year.
“REDA00”
4FC4
OR A
Clear the CARRY FLAG.
4FC5
SBC HL,DE
Ensure that the number of days is not longer than the maximum (either 366 or 365) by SUBtracting the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
4FC7
JP C,1997H
     [1997H]
If the C FLAG (Carry) has been set then days exceeded the maximum possible days in a year, so return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
4FCA
JR NZ,REDA0X
      [4FD9H]
If the NZ FLAG (Not Zero) has been set, then it is not the last day of the year, so JUMP to 4FD9H.

If we pass through, then it is December 31, so just hard code that date.

4FCC
LD A,0CH
Let Register A equal 0CH (Decimal: 12).
4FCE
LD (MT),A
Store the a 12 into memory location 5588H.
4FD1
LD A,1FH
Let Register A equal 1FH (Decimal: 31).
4FD3
LD (DY),A
Store the 31 held in Register A into memory location 5589H.
4FD6
JP RETDA2
   [5043H]
Exit the routine via a JUMP to 5043H.

4FD9H – Continuation of the routine to convert JULIAN to GREGORIAN. Jumped here if we are not at the last day of the calendar year.

“REDA0X”
4FD9
LD HL,0269H
LD HL,0269H
Let Register Pair HL equal 0269H, which is the Model III ROM location which starts off the length of each of the 12 months (1F 1C 1F 1E 1F 1E 1F 1F 1E 1F 1E 1F).
4FDC
LD IX,0000H
Set up for an counter by initializing Special Index Register IX to 0000H.

Top of Loop

“RETDA1”
4FE0
LD C,(HL)
Fetch the length of the month from the table in the Model III ROM pointed to by Register Pair HL and store it into Register C.
4FE1
LD B,00H
Set Register B to 00H so now Register Pair BC holds the length of the month.
4FE3
INC HL
INCrement the pointer to the month lengths held in the Model III ROM by 1.
4FE4
INC IX
INCrement the month counter tracked by Special Index Register IX by 1.
4FE6
EX DE,HL
EXchange the value stored in Register Pair DE and HL.
4FE7
OR A
Clear the CARRY FLAG.
4FE8
SBC HL,BC
Subtracts the value stored in Register Pair BC (the month) and the carry flag from the value stored in Register Pair HL.
4FEA
EX DE,HL
EXchange the value stored in Register Pair DE and HL.
4FEB
JR C,RETDA8
     [4FF5H]
If the C FLAG (Carry) has been set then we have found the month! JUMP to 4FF5H to exit.
4FED
4FED
LD A,D
OR E
Since the Z-80 cannot test Register Pair DE against zero, the common trick is to set Register A to equal to Register D, and then OR A against Register E. Only if both Register D and Register E were zero can the Z FLAG be set.
4FEF
JR NZ,4FE0H
      [4FE0H]
If the NZ FLAG (Not Zero) has been set, then we are NOT at “0”, so JUMP to 4FE0H to continue.

End of Loop

4FF1
INC IX
INCrement the value stored in Special Index Register IX by 1 because the next dump is to a DEC IX.
4FF3
JR RETDA9
   [4FFEH]
JUMP to 4FFEH.

4FF5H – Continuation of the routine to convert JULIAN to GREGORIAN. Jumped here if have calculated the MONTH.

“RETDA8”
4FF5
DEC HL
DECrement the month (stored in Register Pair HL) by 1.
4FF6
LD C,(HL)
Fetch the number of days in the revised month.
4FF7
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4FF8
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC.
4FF9
4FF9
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set.
4FFB
JR NZ,RETDA0
      [5002H]
If the NZ FLAG (Not Zero) has been set, then we are not on a month boundary, so JUMP to 5002H.
4FFD
EX DE,HL
Put the MONTH into Register Pair HL.
“RETDA9”
4FFE
DEC HL
DECrement the month (stored in Register Pair HL) by 1.
4FFF
LD L,(HL)
Fetch the number of days in the revised month.
5000
DEC IX
DECrement the counter of the months stored in Special Index Register IX by 1.
“RETDA0”
5002
LD A,L
Copy the DAY (held in Register L) into Register A.
5003
LD (DY),A
Store the value held in Register A into memory location 5589H.
5006
5008
PUSH IX
POP HL
Copy the month counter to Register Pair HL.
5009
LD A,L
Copy the MONTH (thanks to the counter of IX) into Register A.
500A
LD (MT),A
Store the value held in Register A into memory location 5588H.
500D
LD A,(YR)
Fetch the YEAR (held in memory location 5587H) and store it into Register A.
5010
AND 03H
MASK the value of Register A against 03H to test for a leap year (Z FLAG) or not (NZ FLAG).
5012
JR NZ,5043H
      [5043H]
If the NZ FLAG (Not Zero) has been set it is not a leap year, so JUMP to 5043H.
5014
LD A,(MT)
Fetch the MONTH from memory location 5588H and store it into Register A.
5017
CP 03H
Compare the month (held in Register A) against 03H. If the month is < 3 (so either January or February) …
5019
JR C,RETDA2
     [5043H]
… JUMP to 5043H.
501B
LD A,(DY)
Fetch the DAY (held in memory location 5589H) and store it into Register A.
501E
DEC A
DECrement the DAY by 1.
501F
LD (DY),A
Store the decremented DAY into memory location 5589H.
5022
JR NZ,RETDA2
      [5043H]
If the NZ FLAG (Not Zero) has been set, then we were not at the 1st of the month, so JUMP to 5043H.
5024
LD A,(MT)
Fetch the month (held in memory location 5588H) and store it into Register A.
5027
DEC A
DECrement the month by 1.
5028
LD (MT),A
Store decremented MONTH into memory location 5588H.
502B
502C
LD E,A
LD D,00H
Let DE = the decremented month.
502E
LD HL,0268H
Let Register Pair HL equal 0268H which is one byte before the Model III ROM location which starts off the length of each of the 12 months.
5031
ADD HL,DE
LET Register Pair HL = the ROM Month Length List position minus 1 (held in Register Pair HL) + the decremented month (held in Register DE). This is the new month pointer.
5032
LD A,(HL)
Fetch the number of days in the new month from the ROM chart and store it into Register A.
5033
LD (DY),A
Store that as the new number of days into memory location 5589H.
5036
LD L,A
Save the number of days into Register L.
5037
LD A,(MT)
Fetch the value held in memory location 5588H and store it into Register A.
503A
CP 02H
Compare the month (held in Register A) against 02H. If the month is => 2 (so February and on) …
503C
JR NZ,5043H
      [5043H]
… we are good so JUMP to 5043H.

If we are here then we need to add in the leap day.

503E
INC L
INCrement the number of days in the month (stored in Register L) by 1 for the leap day.
503F
LD A,L
Copy the updated number of days into Register A.
5040
LD (DY),A
Store the value held in Register A into memory location 5589H.
“RETDA2”
5043
5044
POP HL
POP HL
Put the TEXT POINTER (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5045
RST 08H
2C
RST 08H is used to look for expected characters (in this case, a ,) in a string and then return with (HL) pointing to the next non-blank character.

It is a COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call.

If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A register and HL incremented by one. If the two characters do not match, a syntax error message is given.
5047
PUSH HL
Save the TEXT POINTER to the top of the stack.
5048
LD A,(MT)
Fetch the MONTH from memory location 5588H and store it into Register A.
504B
504C
LD L,A
LD H,00H
Copy the MONTH into Register Pair HL.
504E
CALL EDITM
     [50E6H]
Convert the MONTH to ASCII via a GOSUB to 50E6H.
5051
LD DE,RTEMP
Let Register Pair DE equal 558AH as temporary storage for the ASCII converted MONTH.
5054
CALL MOVIT
     [50A6H]
Move the ASCII MONTH to the temp area pointed to by DE via a GOSUB to 50A6H.
5057
PUSH DE
Save the pointer to the temporary storage area holding the ASCII converted MONTH to the top of the stack.
5058
LD A,(DY)
Fetch the DAY from memory location 5589H and store it into Register A.
505B
505C
LD L,A
LD H,00H
Copy the DAY into Register Pair HL.
505E
CALL EDITM
     [50E6H]
Convert the DAY to ASCII via a GOSUB to 50E6H.
5061
POP DE
Put the TEMP POINTER (held at the top of the STACK) into Register Pair DE, and then remove the entry from the stack.
5062
CALL MOVIT
     [50A6H]
Move the ASCII DAY to the temp area pointed to by DE via a GOSUB to 50A6H.
5065
PUSH DE
Save the pointer to the temporary storage area holding the ASCII converted DAY to the top of the stack.
5066
LD A,(YR)
Fetch the YEAR from memory location 5588H and store it into Register A.
5069
506A
LD L,A
LD H,00H
Copy the YEAR into Register Pair HL.
504E
CALL EDITM
     [50E6H]
Convert the YEAR to ASCII via a GOSUB to 50E6H.
506F
POP DE
Put the TEMP POINTER (held at the top of the STACK) into Register Pair DE, and then remove the entry from the stack.
5070
CALL MOVIT
     [50A6H]
Move the ASCII YEAR to the temp area pointed to by DE via a GOSUB to 50A6H.
5073
POP HL
Put the TEMP POINTER (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5074
CALL 260DH
     [260DH]
Get the pointer to the variable by GOSUBing to the Model III ROM FIND ADDRESS OF VARIABLE routine at 260DH which searches the Variable List Table for a variable name which matches the name in the string pointed to in HL, and return the address of that variable in DE (and if there is no variable, it creates it, zeroes it, and returns THAT location).
5077
CALL 0AF4H
     [0AF4H]
Call the Model III ROM routine at 0AF4H to force REG1 to be a STRING. The routine calls 20H (RST 20H) and returns if NTF=3 (string) else if NTF is not 3 then it generates a ?TM ERROR.
507A
PUSH HL
Save the TEXT POINTER to the top of the stack.
507B
LD A,(DE)
Fetch the length of the string (held in the memory location pointed to by Register Pair DE) and store it into Register A.
507C
CP 08H
Compare the value held in Register A against 08H to see if it is a new or smaller string. If the string length < 08H…
507E
JR C,RETDA3
     [5089H]
… create some string space via a JUMP to 5089H.
5080
PUSH DE
Save the variable pointer to the top of the stack.
5081
EX DE,HL
Put the variable pointer into Register Pair HL.
5082
INC HL
INCrement the value stored in Register Pair HL by 1 so as to now point to the LSB of the memory address for that string.
5083
LD E,(HL)
Fetch the LSB of the memory address for that string and put it into Register E.
5084
INC HL
INCrement the value stored in Register Pair HL by 1 so as to now point to the MSB of the memory address for that string.
5085
LD D,(HL)
Fetch the MSB of the memory address for that string and put it into Register D.
5086
POP HL
Restore the variable pointer to the top of the stack into Register Pair HL, and then remove the entry from the stack.
5087
JR RETDA4
   [5094H]
Continue processing via a JUMP to 5094H.

5089H – Create a variable of 8 bytes to house the ASCII DATE.

“RETDA3”
5089
PUSH DE
Save the variable pointer to the top of the stack.
508A
LD A,08H
Prepare to clear 8 bytes of string space by setting Register A to 08H.
508C
CALL 2857H
     [2857H]
Set Up a String by GOSUBing to the Model III ROM Routine at 2857H. For that routine, Register A needs to hold the length of the string to be created.
508F
LD HL,(40D4H)
Fetch the RAM address for that new space from memory location 40D4H.
5092
POP DE
Put the variable pointer (held at the top of the STACK) into Register Pair DE, and then remove the entry from the stack.
5093
EX DE,HL
EXchange the value stored in Register Pair HL (the RAM address for that new space) with the value stored in Register Pair DE (the variable pointer).

5094H – Store the 8 byte ASCII DATE into a variable.

“RETDA4”
5094
LD (HL),08H
Set the length of the string by storing 08H into the memory location pointed to by Register Pair HL.
5096
INC HL
INCrement the value stored in Register Pair HL by 1 so as to point to the LSB of the RAM address for the new string.
5097
LD (HL),E
Store the LSB of the RAM address for that new space into the memory location pointed to by Register Pair HL.
5098
INC HL
INCrement the value stored in Register Pair HL by 1 so as to point to the MSB of the RAM address for the new string.
5099
LD (HL),D
Store the MSB of the RAM address for that new space into the memory location pointed to by Register Pair HL.
509A
LD HL,RTEMP
Let Register Pair HL equal 558AH which is where the ASCII DATE is stored.
509D
LD BC,0008H
Let Register Pair BC equal 0008H, for 8 bytes to move.
50A0
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
50A2
POP HL
Put the TEMP POINTER (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
50A3
JP RETEXT
   [4F8EH]
Exit via a JUMP to 4F8EH.

50A6H – Move the value held in the temp area (4134H) to the memory location pointed to by Register Pair DE.

“MOVIT”
50A6
LD HL,4134H
Let Register Pair HL equal 4134H which is the last 2 bytes.
50A9
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A.
50AA
CP 30H
Compare the byte at 4134H against 30H (ASCII: 0). If A >= 0
50AC
JR NC,50B0H
      [50B0H]
… skip the next instruction by JUMPing to 50B0H.
50AE
LD (HL),30H
Put in a leading zero by storing a 0 into the memory location pointed to by Register Pair HL.
“MOVIT1”
50B0
LD BC,0002H
Prepare to move TWO bytes into a temp area.
50B3
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
50B5
LD A,2FH
Let Register A equal 2FH (ASCII: /).
50B7
LD (DE),A
Store the / delimeter into the memory location pointed to by Register Pair DE.
50B8
INC DE
INCrement the value stored in Register Pair DE by 1 to be after the /.
50B9
RET
RETurn to the caller.

50BAH – Fetch 2 user supplied numbers (such as the day or year), which must follow a “/”, into Register A.

“GETNXT”
50BA

2F
RST 08H is used to look for expected characters (in this case, a /) in a string and then return with (HL) pointing to the next non-blank character.

It is a COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call.

If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A register and HL incremented by one. If the two characters do not match, a syntax error message is given.
“GETNX1”
50BC
CALL GETACR
     [50D3H]
Get the next character into Register Avia a GOSUB to 50D3H.
50BF
LD C,A
Store the character into Register C.
50C0
CALL GETACR
     [50D3H]
Get the next character into Register Avia a GOSUB to 50D3H.
50C3
LD B,A
Store the character into Register B.
50C4
PUSH HL
Save the TEXT POINTER (held in Register Pair HL) to the top of the stack.
50C5
50C7
LD H,00H
LD L,C
Let Register Pair HL = Register C.
50C8
50C9
PUSH HL
POP DE
Copy HL to DE.
50CA
ADD HL,HL
LET Register Pair HL = Register Pair HL * 2.
50CB
ADD HL,HL
LET Register Pair HL = Register Pair HL * 2 again (now * 4).
50CC
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE (now * 5).
50CD
ADD HL,HL
LET Register Pair HL = Register Pair HL * 2 (now * 10).
50CE
LD E,B
Copy the MSB (held in Register B) into Register E.
50CF
ADD HL,DE
Add the MSB to HL.
50D0
LD A,L
Copy the result (held in Register L) into Register A.
50D1
POP HL
Restore the TEXT POINTER (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
50D2
RET
RETurn to the caller.

50D3H – Fetch 1 user supplied number, into Register A. If not a number, exit with a SYNTAX ERROR

“GETACR”
50D3
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A.
50D4
INC HL
INCrement the TEXT POINTER (held in Register Pair HL) by 1.
50D5
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). If the character is NOT a SPACE
50D7
JR NZ,GETAC1
      [50DBH]
… skip the next instruction by JUMPing to 50DBH.
50D9
LD A,30H
Let Register A equal 0.
“GETAC1”
50DB
SUB 30H
SUBtract the value 30H from Register A to test for a bad character. If it was < “0” then the value was bad …
50DD
JP C,1997H
     [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
50E0
CP 0AH
Compare the value held in Register A against 0AH (Decimal: 10). If the character is >= 10 then the value was bad …
50E2
JP NC,1997H
      [1997H]
… return to BASIC with a “?SN ERROR” via a JUMP to 1997H.
50E5
RET
RETurn to the caller.

50E6H – Convert the hex JULIAN DATE to ASCII and edit the spaces.

“EDITM”
50E6
OR 37H
OR Register A against 37H (0011 0111). This has the effect of turning on bits 5, 4, 2, 1, 0, leaving only 8 possible remaining numbers. 37H If the 0’d bits were 000, 3FH (001), 77H (010), 7FH (011), 87H (100), 8FH (101), C7H (110), and CFH (111).
50E8
PUSH AF
Save the contents of Register Pair AF, which would be a flag to supress editing, to the top of the stack.
50E9
CALL 0A9AH
     [0A9AH]
GOSUB to 0A9AH in the Model III ROM routine to put the value in HL into the single precision number storage area of 4121H and is flagged as an INTEGER.
50EC
XOR A
Set Register A to ZERO for no ascii editing.
50ED
CALL 1034H
     [1034H]
GOSUB to 1034H to turn off the EDIT flag and initialize the 4130H input buffer for a FLOATING POINT to ASCII conversion by putting a SPACE into 4130H.
50F0
OR (HL)
Set the flags by merging the value held in Register A against the byte of the program pointed to by Register Pair HL. This also clears the CARRY FLAG.
50F1
CALL 0FD9H
     [0FD9H]
GOSUB to 0FD9H in the Model III ROM to convert the integer value in 4124H to an ASCII string pointed to by Register Pair HL.
50F4
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
50F5
RET C
If the C FLAG (Carry) has been set, then no editing is wanted, so RETurn to the caller.
50F6
LD HL,4131H
OTHERWISE … let Register Pair HL equal 4131H to opint to the ASCII character.

Top of Loop.

“EDITM1”
50F9
LD A,(HL)
Fetch the ASCII character into Register A.
50FA
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). If the characeter is NOT a SPACE
50FC
RET NZ
… we are done, so RETurn to the caller.
50FD
LD (HL),30H
Store a 0 over the SPACE.
50FF
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next character.
5100
JR EDITM1
   [50F9H]
Loop back 5 instructions to 50F9H.

End of Loop.

5102H – “CROSS REFERENCE” Routine.

“CROSS”
5102
Poll the line printer port.
5104
AND 0E0H
MASK the value of Register A against E0H (1110 0000) to leave only bits 7, 6, 5 active. Bit 5: Device Select, Bit 6: Not Out of Paper, and Bit 7: Not Busy.
5106
JR NZ,CROSS1
      [510BH]
If any of bits 7, 6, and 5 are ON, skip the next instruction by JUMPing to 510BH.
5108
LD (PRTAVL),A
If bits 7, 6, and 5 were all OFF then printer is not available, so store the value held in Register A into memory location 51B4H to indicate that.
“CROSS1”
510B
LD HL,(BASIC1)
Fetch the TEXT POINTER (held in memory location 4272H) and store it into Register Pair HL.
510E
RST 08H
2C
RST 08H is used to look for expected characters (in this case, a ,) in a string and then return with (HL) pointing to the next non-blank character.

It is a COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call.

If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A register and HL incremented by one. If the two characters do not match, a syntax error message is given.
5110
LD A,(HL)
Fetch the first byte (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5111
AND 80H
MASK the value of Register A against 80H (1000 0000), leaving only Bit 7 active to test for a reserved word.
5113
LD BC,0001H
Initialize Register Pair BC to 0001H in case we have only 1 character.
5116
JR Z,CROSS2
     [511FH]
If Register A is NOT a reseved word (Bit 7 was 0), then JUMP to 511FH.
5118
INC HL
If we’re here, then Register A is holding a reserved word, so bump past it by INCrementing the value stored in Register Pair HL by 1.
5119
LD (BASIC1),HL
Store the current location (1 past a reserved word) into the TEXT POINTER.
511C
DEC HL
Back up to before the reserved word held in Register A by DECrementing the value stored in Register Pair HL by 1.
511D
JR DOCROS
   [5135H]
Do the cross reference by JUMPing to 5135H.

511FH – “CROSS REFERENCE” Routine. Jumped here if the character we just fetched into Register A was not a reserved word.

“CROSS2”
511F
CALL 2337H
     [2337H]
GOSUB to 2337H to evaluate the BASIC expression pointed to by HL and return with the result in REG 1.
5122
LD (BASIC1),HL
Store the TEXT POINTER (held in Register Pair HL) into memory location 4272H.
5125
CALL 29D7H
     [29D7H]
GOSUB to 29D7H to check to see if there is enough memory for the string.
5128
LD A,(HL)
Fetch the length of the string (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5129
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
512A
JP Z,1E4AH
     [1E4AH]
If Register A is 0, then we have a null string, which is bad, so exit with a “?FC ERROR” via a JUMP to 1E4AH.
512D
LD C,A
If the string is NOT empty, continue. First copy the string length (held in Register A) into Register C.
512D
512E
LD C,A
LD B,00H
Let Register Pair BC = A (i.e., the length of the string)
5130
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the address of the string.
5131
LD E,(HL)
Fetch the LSB of the address of the string (held in the memory location pointed to by Register Pair HL) and store it into Register E.
5132
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the address of the string.
5133
LD D,(HL)
Fetch the MSB of the address of the string (held in the memory location pointed to by Register Pair HL) and store it into Register D.
5134
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE (the address of the string in RAM).
“DOCROS”
5135
LD (NUMB0),BC
Store the length of the string (held in Register Pair BC) into memory location 4ED5H.
5139
LD (LAB15),HL
Store the pointer to the search arguments (held in Register Pair HL) into memory location 4EDBH.
513C
LD HL,(40A4H)
Fetch the value held in memory location 40A4H and store it into Register Pair HL.
NOTE: 40A4H is the storage location for the BEGINNING OF THE BASIC PROGRAM IN RAM.
513F
LD (VARPTR),HL
Store the address of the buffer pointer (held in Register Pair HL) into memory location 4EE1H.

Top of a loop.

“DOCRO1”
5142
LD HL,(VARPTR)
Fetch the buffer pointer (held in memory location 4EE1H) and store it into Register Pair HL.
5145
LD A,(HL)
Fetch the address (at the memory location pointed to by Register Pair HL) and store it into Register A.
5146
INC HL
INCrement the buffer pointer value stored in Register Pair HL by 1 to point to the byte after the one we just fetched into Register A.
5147
OR (HL)
Test to see if the next character is 00H by OR’ing Register A against the value of the next character in the program. If that next character was 00H then Register A will be unchanged, and the Z Flag will be set.
5148
JR NZ,DOCR00
      [514FH]
If the NZ FLAG (Not Zero) has been set then the next character was not a 00H, so we continue by JUMPing to 514FH.
514A
LD A,0DH
If we passed through to here, then we are at the end of the program. Let Register A equal CARRIAGE RETURN..
514C
JP DISOUT
   [51B2H]
Display the CARRIAGE RETURN and RETurn via a JUMP to 51B2H.

End of the loop.

514FH – “CROSS REFERENCE” Routine. Continued here as we narrow down the validity of the character and End-of-Line status.

“DOCR00”
514F
INC HL
INCrement the POINTER TO THE POSITION IN THE BASIC PROGRAM (held in Register Pair HL) so as to now point to the LINE NUMBER.
5150
LD (NUMB1),HL
Store the LINE NUMBER into memory location 4EDFH just in case we are going to need to track it.
5153
5154
INC HL
INC HL
Bump POINTER TO THE POSITION IN THE BASIC PROGRAM (held in Register Pair HL) by TWO to pass the line number and the SPACE.
“DOCRO2”
5155
LD A,(HL)
Fetch the next character in the program (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5156
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5157
JR NZ,DOCRO3
      [515FH]
If it OR wasn’t 00H then we are not at the end of the line, and need to keep processing, so JUMP to 515FH.
5159
INC HL
If we didn’t jump away, we are at the end of a line. INCrement the value stored in Register Pair HL by 1 to move to the beginning of the next line.
515A
LD (VARPTR),HL
Store the POINTER TO THE POSITION IN THE BASIC PROGRAM (held in Register Pair HL) into memory location 4EE1H.
515D
JR DOCRO1
   [5142H]
JUMP to 5142H.

515FH – “CROSS REFERENCE” Routine. Continued here as we narrow down the validity of the character and End-of-Line status.

“DOCRO3”
515F
LD DE,(LAB15)
Fetch the pointer to the SEARCH ARGUMENT (held in memory location 4EDBH) and store it into Register Pair DE.
5163
LD BC,(NUMB0)
Fetch the length (held in memory location 4ED5H) and store it into Register Pair BC.
5167
CALL COPARE
     [51C1H]
Compare them via a GOSUB to 51C1H.
516A
JR Z,DISPLY
     [516FH]
If the Z FLAG (Zero) has been set, then they match. JUMP to 516FH to display them.
516C
INC HL
If we passed through then there was no match, so move onto the next character in the program by INCrementing the value stored in Register Pair HL by 1.
516D
JR DOCRO2
   [5155H]
Loop back to continue via a JUMP to 5155H.

516FH – “CROSS REFERENCE” Routine DISPLAY routine. Starts by moving to the end of the program line.

“DISPLY”
516F
LD A,(HL)
Fetch a byte from the program held in the memory location pointed to by Register Pair HL and store it into Register A.
5170
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
5171
JR Z,5176H
     [5176H]
If the Z FLAG (Zero) has been set then we have reached the end of a program line, so JUMP to 5176H.
5173
INC HL
If not, move to the next byte of the program by 1 by INCrementing the value stored in Register Pair HL (POINTER TO THE POSITION IN THE BASIC PROGRAM) by 1.
5174
JR DISPLY
   [516FH]
Loop back to the top of this routine to keep processing characters by JUMPing to 516FH.

5176H – “CROSS REFERENCE” Routine DISPLAY routine. Continues once we are at the end of a program line.

“DISPL1”
5176
INC HL
Since we entered this routine with HL at the end of the line, bump it by 1 to move to point to the next line in the program.
5177
LD (VARPTR),HL
HL now points to a line number. Store the POINTER TO THE POSITION IN THE BASIC PROGRAM (held in Register Pair HL) into memory location 4EE1H.
517A
LD HL,(NUMB1)
Fetch the line number (held in memory location 4EDFH) and store it into Register Pair HL.
517D
LD E,(HL)
Fetch the LSB of the line number pointer (held in the memory location pointed) to by Register Pair HL and store it into Register E.
517E
INC HL
INCrement the value stored in Register Pair HL by 1.
517F
LD D,(HL)
Fetch the MSB of the line number pointer (held in the memory location pointed) to by Register Pair HL and store it into Register D.
5180
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the MSB of the line number) with the value stored in Register Pair DE (i.e., the line number pointer).
5181
CALL EDITX
     [50E7H]
Convert it to ASCII via a GOSUB to 50E7H.
5184
INC HL
Move past the SPACE after the line number by INCrementing the value stored in Register Pair HL by 1.
5185
LD B,05H
Since a line number is up to 5 characters, let Register B equal 05H for a DJNZ loop.

Start of a DJNZ loop of 5.

“DISPL2”
5187
LD A,(HL)
Fetch a digit from the line number (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5188
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
5189
JR Z,DISP22
     [5191H]
Was the digit in the line number a 00H (end of line number?). If so, the Z FLAG (Zero) has been set and we JUMP out of the loop to 5191H.
518B
CALL DISOUT
     [51B2H]
If the line number digit was not a 00H, then output the byte held in Register A to the screen (and if requested, the printer) via a GOSUB to 51B2H.
518E
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next character in the line number.
518F
DJNZ DISPL2
     [5187H]
LOOP back to 5187H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.

End of the DJNZ loop.

“DISP22”
5191
LD A,(4020H)
Fetch the value held in memory location 4020H and store it into Register A.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5194
AND 3FH
MASK the value of Register A against 3FH (0011 1111) which, when applied to a location on the screen, isolates the COLUMN.
5196
CP 3AH
Compare the value held in Register A against 3AH (Decimal: 58) to see if we need to display a CARRIAGE RETURN). If A < 58, the CARRY FLAG will be set and we have room to display another set of information. If A >= 58, the NO CARRY FLAG will be set and we don’t have room.
5198
JR C,DISPL3
     [51A2H]
If the C FLAG (Carry) has been set, then we have room …JUMP to 51A2H.
519A
LD A,0DH
Let Register A equal CARRIAGE RETURN.
519C
CALL DISOUT
     [51B2H]
Output the CARRIAGE RETURN held in Register A to the screen (and if requested, the printer) via a GOSUB to 51B2H.
519F
JP DOCRO1
   [5142H]
JUMP to 5142H to process the next line of the program.

51A2H – “CROSS REFERENCE” Routine DISPLAY routine. Move to a tab column.

“DISPL3”
51A2
NEG
Negate the contents of Register A (which is the same as -A).
51A4
AND 07H
MASK the value of Register A against 07H (0000 0111) to get a number which is no greater than 7 (because TAB columns are 8 characters).
51A6
INC A
We NEVER want a 0 value, so INCrement the value stored in Register A by 1.
51A7
LD B,A
Copy the contents of Register A into Register B for a DJNZ loop.

Start of a DJNZ loop of up to 8 spaces.

“”
51A8
LD A,20H
Let Register A equal 20H (ASCII: SPACE).
51AA
CALL DISOUT
     [51B2H]
Output the SPACE held in Register A to the screen (and if requested, the printer) via a GOSUB to 51B2H.
51AD
DJNZ 51A8H
     [51A8H]
LOOP back to 51A8H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.

End of the DJNZ loop.

51AF
JP DOCRO1
   [5142H]
JUMP to 5142H to process the next line of the program.

51B2H – “CROSS REFERENCE” Routine DISPLAY routine. Subroutine to output the byte held in Register A to the screen (and if requested, the printer).

“DISOUT”
51B2
LD C,A
Copy the byte to display (held in Register A) into Register C.
51B3
LD A,** PRTAVL **
Let Register A equal the value eplaced into 51B4H (PRTAVL) elsewhere in this Overlay. This is the Printer AVAILABLE/NOT AVAILABLE status flag.
51B5
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
51B6
LD A,C
Copy the byte to display (held in Register C) into Register A.
51B7
JR Z,DISOU1
     [51BEH]
If the Z FLAG (Zero) has been set then the printer is NOT available, so skip over the next 3 instructions (which print) and JUMP to 51BEH.
51B9
PUSH AF
Save the byte to print (held in Register Pair AF) to the top of the stack.
51BA
CALL 003BH
     [003BH]
GOSUB to 003BH.
NOTE: 003BH is the Model III ROM routine to write the byte held in Register A to the printer, including waiting for the printer to be available OR getting a BREAK. Uses Register Pair DE.
51BD
POP AF
Restore the byte to print (held at the top of the stack) back into Register A, and then remove the entry from the stack.
“DISOU1”
51BE
JP 0033H
   [0033H]
JUMP to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.

51C1H – “CROSS REFERENCE” Routine Subroutine to compare the contents of DE and HL.

“COPARE”
51C1
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
51C2
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
51C3
PUSH HL
Save the contents of Register Pair HL to the top of the stack.

Top of a loop.

“STRCM1”
51C4
LD A,(DE)
Fetch a byte from DE store it into Register A.
51C5
CP (HL)
Compare the DE byte with the HL byte. If they are different …
51C6
JR NZ,51CEH
      [51CEH]
… EXIT by JUMPing to 51CEH to restore the stack and RETurn.
51C8
LDI
If they are the same, then move to the 2nd character of both HL and DE via LDI command; which copies BC number of characters from (HL) to (DE), dropping BC each time. When BC hits 0, the PE flag is reset.
51CA
JP PE,51C4H
      [51C4H]
If the PARITY/OVERFLOW FLAG has been SET then we have more characters to process, so LOOP BACK to 51C4H.

End of the loop.

51CD
XOR A
Set Register A to ZERO and clear all Flags to signal a match (success!).
“STRCM2”
51CE
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
51CF
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
51D0
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
51D1
RET
RETurn to the caller.
 
END 4E00H
That’s it!