4BC9H - Overlay Load Block
The two bytes every SYS overlay deposits into the padding area of the resident core immediately below the RST 28H dispatcher. They are data, not instructions, and are never executed. SYS11/SYS writes FCH and 03H here, in the same way SYS10/SYS writes 73H and 01H and SYS8/SYS writes 96H and 02H.
4BC9
DEFB FCH, 03H FC 03
Two-byte load block written into the resident padding area at 4BC9H through 4BCAH by the overlay loader as SYS11/SYS is brought into memory. The bytes are data and are not part of the executable image, which begins at 4E00H.
4E00H - Overlay Entry and Request Dispatch
SYS11/SYS answers five supervisor requests, all of them parts of running a Job Control Language job: 9DH starts a job, 0ADH and 0BDH report that a program under the job has exited or aborted, and 0CDH and 0DDH are the two forms of the keyboard request through which the job feeds characters to the programs it runs. Every entry begins by clearing the interrupt-request bit in KFLAG$.
4E00
PUSH HL E5
Save Register Pair HL, which the caller may be using, while the keyboard flag byte is adjusted.
4E01
LD HL,4423H 21 23 44
Load Register Pair HL with 4423H, the address of the resident keyboard flag byte KFLAG$.
4E04
RES 2,(HL) CB 96
Clear bit 2 of KFLAG$ at 4423H. That bit is the interrupt request this overlay polls at 4EA0H while a timing directive is running, so every entry starts with it clear.
4E06
POP HL E1
Restore the caller's Register Pair HL.
4E07
AND 70H E6 70
Register A holds the RST 28H request code that the resident supervisor dispatcher at 4BCDH passed to this overlay. Mask off everything except bits 6-4 to isolate the sub-function selector.
4E09
CP 20H FE 20
Compare the sub-function in Register A against 20H, the selector produced by request code 0ADH, the @EXIT launch stub that reports a program finishing normally. If Register A equals 20H, the Z FLAG is set.
4E0B
If the Z FLAG has been set a program under the job has just exited, so JUMP to 4E60H to run the next line of the job.
4E0D
CP 40H FE 40
Compare the sub-function in Register A against 40H, the selector produced by request code 0CDH, which is @DOKEY, the keyboard request the resident vector at 44BEH issues. If Register A equals 40H, the Z FLAG is set.
4E0F
If the Z FLAG has been set a program is asking for keyboard input while the job runs, so JUMP to 4ECFH to decide whether the job should answer it.
4E12
CP 50H FE 50
Compare the sub-function in Register A against 50H, the selector produced by request code 0DDH, which is what the @DOKEY vector issues after the INPUT directive has patched it at 50C3H. If Register A equals 50H, the Z FLAG is set.
4E14
If the Z FLAG has been set the operator is part way through answering an INPUT directive, so JUMP to 50C8H to pass the request through to the real keyboard.
4E17
CP 30H FE 30
Compare the sub-function in Register A against 30H, the selector produced by request code 0BDH, the @EXIT launch stub that reports a program aborting. If Register A equals 30H, the Z FLAG is set.
4E19
If the Z FLAG has been set a program under the job has aborted, so JUMP to 4E8AH to end the whole job with a message.
4E1B
CP 10H FE 10
Compare the sub-function in Register A against 10H, the selector produced by request code 9DH, which is the request SYS6/SYS DO issues at 5301H to start a compiled job. If Register A equals 10H, the Z FLAG is set.
4E1D
RET NZ C0
If the NZ FLAG has been set the request is none of the five this overlay services; return to the RST 28H dispatcher at 4BCDH having taken no action.
4E1EH - Start a Job
Starting a job saves the real keyboard driver, diverts the keyboard to the job file, arms the exit vectors so that a program finishing or failing comes back here, reads the first line of the job into the command buffer and hands it to the command interpreter. The stack is reset to the resident base at every step rather than unwound, because the commands the job runs may leave it anywhere.
4E1E
DI F3
Disable interrupts while the resident vectors that drive the job are switched over, so that no timer interrupt can run against a half-changed set.
4E1F
LD HL,4423H 21 23 44
Load Register Pair HL with 4423H, the address of the resident keyboard flag byte KFLAG$.
4E22
RES 0,(HL) CB 86
Clear bit 0 of KFLAG$ at 4423H, the BREAK flag, so that a BREAK left over from before the job started is not mistaken at 4E9CH for a request to abort it.
4E24
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, the address of the resident system flag byte SFLAG$.
4E27
BIT 5,(HL) CB 6E
Test bit 5 of SFLAG$ at 430FH. That bit records that a job is in effect and that the system is therefore not at command level. The NZ FLAG is set if a job was already running.
4E29
SET 5,(HL) CB EE
Set bit 5 of SFLAG$ at 430FH, declaring that a job is now in effect. The test at 4E27H already captured the previous state.
4E2B
If the NZ FLAG has been set a job was already running, so its saved vectors must not be overwritten; JUMP to 4E39H and skip the save.
4E2D
LD HL,(4016H) 2A 16 40
No job was running. Fetch the current address of the *KI keyboard driver from 4016H, the driver-address word inside the resident keyboard device control block KIDCB$ at 4015H.
4E30
LD (43BEH),HL 22 BE 43
Store that driver address into KIJCL$ at 43BEH, the resident slot reserved for holding the real keyboard driver while a job has the keyboard diverted. It is put back at 4EB7H when the job ends.
4E33
LD HL,406BH 21 6B 40
Load Register Pair HL with 406BH, the six-byte image of the exit vectors as they must stand while a job is running.
4E36
GOSUB to 4EC6H to copy those six bytes over 402DH through 4032H, the resident @EXIT, @ABORT and @DVRHK vectors, so that a program finishing or failing re-enters this overlay instead of returning to the command interpreter.
4E39
LD SP,41E0H 31 E0 41
Reset the stack pointer to 41E0H, the base of the resident stack. The job runs commands that may have left the stack anywhere, so it is reset at every step rather than unwound.
4E3C
EI FB
Re-enable interrupts now that the vectors are consistent.
4E3D
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the address of JFCB$, the resident File Control Block through which the compiled job file is read.
4E40
GOSUB to the resident @CKEOF vector at 444BH to test whether the job file addressed by Register Pair DE still has records to read.
4E43
If the NZ FLAG has been set the job file could not be checked, so JUMP to the resident @ERROR vector at 4409H to report the failure with the error code in Register A.
4E46
LD DE,4E5AH 11 5A 4E
Load Register Pair DE with 4E5AH, the address of this overlay's own keyboard driver, which returns the next byte of the job file instead of a keystroke.
4E49
LD (4016H),DE ED 53 16 40
Store 4E5AH into 4016H, the driver-address word of the resident keyboard device control block KIDCB$. Every keyboard read now comes out of the job file, which is what lets the ROM line-input routine below read a job line as though it were typed.
4E4D
GOSUB to 4E82H to read one line of the job into the resident command buffer INBUF$ at 4318H through the ROM line-input routine.
4E50
LD DE,44BEH 11 BE 44
Load Register Pair DE with 44BEH, the address of the resident @DOKEY vector.
4E53
LD (4016H),DE ED 53 16 40
Store 44BEH into 4016H, the driver-address word of KIDCB$, so that from now on keyboard reads go through @DOKEY. That vector issues request code 0CDH, which brings control back into this overlay at 4ECFH where each request is judged individually.
4E57
JUMP to the resident @CMNDI vector at 4405H to execute the job line now sitting in the command buffer INBUF$ at 4318H, exactly as though the operator had typed it.
4E5AH - The Job File as a Keyboard Driver
Two instructions that make the whole design work. Installed as the *KI driver, this routine returns the next byte of the compiled job file instead of a keystroke, so the ordinary ROM line-input routine collects a line of the job exactly as though the operator had typed it.
4E5A
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the address of JFCB$, the File Control Block of the compiled job file.
4E5D
JUMP to the ROM byte-input routine at 0013H, which returns in Register A the next byte of the file whose control block Register Pair DE addresses. Installed as the *KI driver at 4E49H, this makes the job file the source of every keystroke the system sees.
4E60H - Resume After a Program Exits
Request code 0ADH arrives when a program run by the job finishes normally. Unless BREAK has been pressed, the next line of the job is read and executed; when the job file is exhausted the run ends with Job done.
4E60
LD SP,41E0H 31 E0 41
Reset the stack pointer to 41E0H, the base of the resident stack, discarding whatever the program that just finished left behind.
4E63
EI FB
Re-enable interrupts, which the exiting program may have left disabled.
4E64
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, the address of the resident system flag byte SFLAG$.
4E67
BIT 4,(HL) CB 66
Test bit 4 of SFLAG$ at 430FH, which suppresses the BREAK check below. The NZ FLAG is set when BREAK is not to be honoured.
4E69
If the NZ FLAG has been set BREAK is disabled, so JUMP to 4E74H and go straight on to the next job line.
4E6B
LD A,(4423H) 3A 23 44
Fetch the resident keyboard flag byte KFLAG$ from 4423H into Register A. Its bit 0 is set when the operator has pressed BREAK.
4E6E
RRCA 0F
Rotate Register A right circularly, moving the BREAK flag from bit 0 into the CARRY flag.
4E6F
LD HL,51A0H 21 A0 51
Load Register Pair HL with 51A0H, the address of the text Job aborted, ready in case BREAK was pressed.
4E72
If the CARRY FLAG has been set the operator pressed BREAK, so JUMP to 4E8DH to display that message and abandon the job.
4E74
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the address of JFCB$, the File Control Block of the compiled job file.
4E77
GOSUB to the resident @CKEOF vector at 444BH to test whether the job file addressed by Register Pair DE has any records left.
4E7A
If the NZ FLAG has been set the job file is exhausted, so JUMP to 4EA3H to finish with the message Job done.
4E7C
GOSUB to 4E82H to read the next line of the job into the resident command buffer INBUF$ at 4318H.
4E7F
JUMP to the resident @CMNDI vector at 4405H to execute that line as a command.
4E82H - Read One Job Line into the Command Buffer
The job line is collected by the ordinary ROM line-input routine at 0040H. Because the keyboard driver has been diverted to the job file, that routine gathers a line of the job into INBUF$ without knowing it is not reading the keyboard.
4E82
LD HL,4318H 21 18 43
Load Register Pair HL with 4318H, the address of INBUF$, the resident buffer the command interpreter reads its command line from.
4E85
LD B,3FH 06 3F
Load Register B with 3FH, that is sixty-three, the largest number of characters the command buffer will accept.
4E87
JUMP to the ROM line-input routine at 0040H, which fills the buffer addressed by Register Pair HL until a carriage return. Its characters come from whichever driver is installed in KIDCB$ at 4016H, which during a job is this overlay's job-file reader at 4E5AH, so a line of the job is collected as though it had been typed. That routine returns directly to this routine's caller.
4E8AH - Abort the Job
Request code 0BDH arrives when a program run by the job has aborted. The job ends with Job aborted and control passes to the resident @ABORT vector. This is also where the BREAK check and the malformed-job path arrive.
4E8A
LD HL,51A0H 21 A0 51
Load Register Pair HL with 51A0H, the address of the text Job aborted.
4E8D
LD DE,4030H 11 30 40
Load Register Pair DE with 4030H, the resident @ABORT vector, which is where control is to be sent once the message has been shown and the job dismantled.
4E90
JUMP to 4EA9H, the common ending, to display the message addressed by Register Pair HL, restore everything the job changed, and then transfer to the vector in Register Pair DE.
4E92H - Break and Interrupt Poll
Every directive that waits calls this routine. It abandons the whole job if the operator has pressed BREAK, and otherwise reports in the Z FLAG whether the directive that is running should be cut short.
4E92
LD A,(430FH) 3A 0F 43
Fetch the resident system flag byte SFLAG$ from 430FH into Register A.
4E95
BIT 4,A CB 67
Test bit 4 of Register A, the copy of SFLAG$, which suppresses the BREAK check. The NZ FLAG is set when BREAK is not to be honoured.
4E97
LD A,(4423H) 3A 23 44
Fetch the resident keyboard flag byte KFLAG$ from 4423H into Register A, without disturbing the flags the test above produced.
4E9A
If the NZ FLAG has been set BREAK is disabled, so JUMP to 4EA0H and test only the interrupt request.
4E9C
BIT 0,A CB 47
Test bit 0 of Register A, the copy of KFLAG$, which the resident keyboard handling sets when the operator presses BREAK.
4E9E
If the NZ FLAG has been set the operator pressed BREAK, so JUMP to 4E8AH to abandon the whole job with the message Job aborted.
4EA0
BIT 2,A CB 57
Test bit 2 of Register A, the copy of KFLAG$. That bit is cleared at 4E04H on every entry to this overlay and is set when the running directive is to be cut short, so the NZ FLAG returned here tells a timing directive to stop waiting.
4EA2
RET C9
Return to the calling directive with the NZ FLAG set if it should stop waiting and the Z FLAG set if it should carry on.
4EA3H - End the Job and Restore the Resident Vectors
The common ending. The message is displayed, the in-effect flag is cleared, the job file control block is closed, the real keyboard driver is put back and the three exit vectors are restored from their saved image. The destination vector is pushed before the restore so that the closing RET transfers to either @EXIT or @ABORT.
4EA3
LD HL,51ACH 21 AC 51
Load Register Pair HL with 51ACH, the address of the text Job done.
4EA6
LD DE,402DH 11 2D 40
Load Register Pair DE with 402DH, the resident @EXIT vector, which is where control is to be sent once the job has been dismantled.
4EA9
PUSH DE D5
Save the destination vector held in Register Pair DE onto the stack. The RET at 4ECEH at the end of the restore below takes it off again, which is how this routine transfers to either @EXIT or @ABORT without a jump.
4EAA
GOSUB to the resident @LOGOT vector at 447BH to display the carriage-return terminated message addressed by Register Pair HL on the video device.
4EAD
DI F3
Disable interrupts while the resident vectors the job diverted are put back.
4EAE
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, the address of the resident system flag byte SFLAG$.
4EB1
RES 5,(HL) CB AE
Clear bit 5 of SFLAG$ at 430FH, declaring that no job is in effect any more and that the system is back at command level.
4EB3
XOR A AF
Set Register A to ZERO and clear all flags.
4EB4
LD (4358H),A 32 58 43
Store zero into 4358H, the first byte of JFCB$, the File Control Block of the job file. That byte is the type and attribute field, so clearing it marks the control block closed and unusable.
4EB7
LD HL,(43BEH) 2A BE 43
Fetch the real keyboard driver address back out of KIJCL$ at 43BEH, where 4E30H put it when the job started.
4EBA
LD (4016H),HL 22 16 40
Store it into 4016H, the driver-address word of the resident keyboard device control block KIDCB$, so that keystrokes once again come from the keyboard rather than from the job file.
4EBD
LD DE,4015H 11 15 40
Load Register Pair DE with 4015H, the address of the resident keyboard device control block KIDCB$.
4EC0
GOSUB to the ROM control routine at 0023H to issue a control call to the device whose control block Register Pair DE addresses, resetting the keyboard device now that its driver has been changed back.
4EC3
LD HL,4065H 21 65 40
Load Register Pair HL with 4065H, the six-byte image of the exit vectors as they stand when no job is running.
4EC6
LD DE,402DH 11 2D 40
Load Register Pair DE with 402DH, the address of the resident @EXIT vector, which begins the three-vector block @EXIT, @ABORT and @DVRHK.
4EC9
LD BC,0006H 01 06 00
Load Register Pair BC with 0006H, the length of that three-vector block.
4ECC
LDIR ED B0
Block move with increment: copy the six bytes from the image addressed by Register Pair HL over the vectors at 402DH. Entered at 4EC3H this restores the normal vectors, and entered at 4EC6H from 4E36H it installs the job-active ones.
4ECE
RET C9
Return. When this routine was reached by falling through 4EA9H the return address is the @EXIT or @ABORT vector pushed there, so the job ends by transferring to it.
4ECFH - Keyboard Request Interception
Request code 0CDH is what the resident @DOKEY vector issues once a job is running. Because the supervisor dispatcher throws away the return address the RST 28H pushed, this routine can reach down the stack into the working state of whatever asked for the keystroke. It looks for the return address 05E3H, which the ROM line-input routine KEYIN leaves there while it waits for a key, and answers only those requests from the job file; anything else is chained straight to the real keyboard driver. It then reads KEYIN's own buffer counts to tell the start of a fresh line from the middle of one, and a line beginning with a slash is taken away to be processed as a directive rather than handed to the program.
4ECF
LD HL,000AH 21 0A 00
Load Register Pair HL with 000AH, the offset at which the working state of the ROM line-input routine can be reached down the stack.
4ED2
ADD HL,SP 39
Add the stack pointer. The supervisor dispatcher discards the return address the RST 28H itself pushed, at 4BD1H through 4BDDH, so what lies above this overlay is the chain of return addresses and saved registers belonging to whatever asked for the keystroke. Register Pair HL now addresses ten bytes into that chain.
4ED3
LD C,(HL) 4E
Fetch the low half of that word into Register C. When the request came from the ROM line-input routine KEYIN at 05D9H this is its Register C, which the LD C,B at 05DFH set to the size of the input buffer.
4ED4
INC HL 23
Advance Register Pair HL to the high half of that word.
4ED5
LD B,(HL) 46
Fetch it into Register B. In the ROM line-input routine that is the number of bytes still free in the buffer, which it counts down as each character is accepted, so Register B and Register C are equal only while the line is still empty.
4ED6
INC HL 23
Advance Register Pair HL by one byte towards the next word of interest.
4ED7
INC HL 23
Advance Register Pair HL by a second byte towards that word.
4ED8
INC HL 23
Advance Register Pair HL by a third byte, so it addresses the low half of the word fourteen bytes down the stack.
4ED9
LD E,(HL) 5E
Fetch the low half of that word into Register E.
4EDA
INC HL 23
Advance Register Pair HL to the high half of that word.
4EDB
LD D,(HL) 56
Fetch it into Register D, so Register Pair DE now holds the whole word.
4EDC
LD HL,05E3H 21 E3 05
Load Register Pair HL with 05E3H. That is the CP 20H at the head of the character-dispatch loop of the ROM line-input routine KEYIN, and so it is the return address that the CALL 0049H at 05E0H leaves on the stack while KEYIN waits for a key.
4EDF
SBC HL,DE ED 52
Subtract the word recovered from the stack. The CARRY flag was left clear by the address addition at 4ED2H, so this is an exact subtraction and the Z FLAG is set only when that word is 05E3H, which is to say only when this keyboard request arose inside the ROM line-collection loop.
4EE1
If the Z FLAG has been set the request is part of collecting a command line, which is precisely what a job exists to supply, so JUMP to 4EE8H to take the next line from the job file.
4EE3
LD HL,(43BEH) 2A BE 43
The request came from somewhere other than the line-collection loop, so it belongs to a program reading the keyboard for its own purposes and the job must not answer it. Fetch the real keyboard driver address from KIJCL$ at 43BEH, where 4E30H saved it when the job started.
4EE6
SCF 37
Set the CARRY flag, which is the condition the real keyboard driver is entered with.
4EE7
JP (HL) E9
JUMP to the real keyboard driver whose address is in Register Pair HL, letting the operator answer this request directly. That driver returns to this overlay's caller.
4EE8
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the address of JFCB$, the File Control Block of the compiled job file.
4EEB
PUSH BC C5
Save the two buffer counts recovered at 4ED3H and 4ED5H across the end-of-file test.
4EEC
GOSUB to the resident @CKEOF vector at 444BH to test whether the job file addressed by Register Pair DE has records left.
4EEF
POP BC C1
Restore the two buffer counts.
4EF0
If the NZ FLAG has been set the job file is exhausted, so JUMP to 4EA3H to finish the job with the message Job done.
4EF2
LD A,B 78
Copy the count of bytes still free in the line-input buffer, recovered into Register B at 4ED5H, into Register A.
4EF3
CP C B9
Compare it against Register C, the original size of that buffer. The two are equal only while no character has yet been accepted, which marks the start of a fresh line. If they are equal, the Z FLAG is set.
4EF4
If the NZ FLAG has been set characters have already been accepted into the line, so the job is part way through feeding one; JUMP to the ROM byte-input routine at 0013H to hand over the next byte of the job file and let the line carry on.
4EF7
This is the start of a fresh line. GOSUB to the resident @RREAD vector at 4454H to read the next record of the job file into its buffer.
4EFA
If the NZ FLAG has been set the record could not be read, so JUMP to the resident @ERROR vector at 4409H to report the failure with the error code in Register A.
4EFD
GOSUB to the ROM byte-input routine at 0013H to take the first byte of that record out of the job file.
4F00
OR A B7
OR Register A with itself to test the byte just read. The Z FLAG is set if it is zero.
4F01
If the Z FLAG has been set the job file holds a zero byte where a line should begin, which cannot be executed, so JUMP to 4EA3H to end the job.
4F03
PUSH AF F5
Save the byte just read, together with the flags, while it is examined.
4F04
CP 2FH FE 2F
Compare the byte in Register A against 2FH, the ASCII code for /. A job line beginning with that character is a directive or a label rather than a command. If Register A equals 2FH, the Z FLAG is set.
4F06
If the Z FLAG has been set the line begins with / and must be examined by the job processor, so JUMP to 4F0AH.
4F08
POP AF F1
The line is an ordinary character destined for the program that asked for it. Restore it into Register A together with the flags.
4F09
RET C9
Return that character to the caller as though it had been typed at the keyboard.
4F0AH - Directive Line Processing and Dispatch
A line beginning with a slash is collected into the command buffer and examined. Two slashes followed by a third slash or by a digit make a label, which is stepped over. Otherwise the directive name is extracted, looked up in the keyword table at 51B5H, and the handler address the lookup returns is pushed and returned to, which transfers control to it with the line still addressable on the stack.
4F0A
POP AF F1
Restore the / that started this line into Register A, discarding the saved flags.
4F0B
PUSH BC C5
Save the caller's Register Pair BC while the line is collected and acted upon.
4F0C
PUSH DE D5
Save the caller's Register Pair DE alongside it.
4F0D
LD B,3FH 06 3F
Load Register B with 3FH, that is sixty-three, the largest number of characters that will be collected into the command buffer.
4F0F
LD HL,4318H 21 18 43
Load Register Pair HL with 4318H, the address of INBUF$, the resident buffer the line is gathered into.
4F12
PUSH HL E5
Save the address of the start of the buffer, which is needed again each time the line is re-examined below.
4F13
LD (HL),A 77
Loop Start
Store the character in Register A into the buffer at the address in Register Pair HL.
4F14
INC HL 23
Advance Register Pair HL to the next position in the buffer.
4F15
CP 0DH FE 0D
Compare the character just stored against 0DH, a carriage return, which ends a job line. If Register A equals 0DH, the Z FLAG is set.
4F17
If the Z FLAG has been set the whole line has been collected, so JUMP to 4F20H to examine it.
4F19
GOSUB to the ROM byte-input routine at 0013H to fetch the next byte of the job file into Register A.
4F1C
DECrement Register B and loop back to 4F13H if it has not reached zero, collecting up to sixty-three characters.
Loop End
4F1E
The line ran past the end of the buffer without a carriage return. JUMP to 4F5FH to report it as a malformed job and abandon the run.
4F20
POP HL E1
Recover the address of the start of the collected line into Register Pair HL.
4F21
PUSH HL E5
Save it again, since each test below consumes the copy it takes.
4F22
INC HL 23
Advance Register Pair HL to the second character of the line.
4F23
LD A,(HL) 7E
Fetch that second character into Register A.
4F24
CP 2FH FE 2F
Compare it against 2FH, the ASCII code for /. A directive or label line begins with two of them. If Register A equals 2FH, the Z FLAG is set.
4F26
If the NZ FLAG has been set only one / was present, so this is not a directive at all; JUMP to 4F5AH to discard the line and read the next one.
4F28
INC HL 23
Advance Register Pair HL to the third character of the line, the one that decides between a directive and a label.
4F29
SUB (HL) 96
Subtract that third character from Register A, which holds 2FH. The Z FLAG is set when the third character is itself a /.
4F2A
If the Z FLAG has been set the line begins with three slashes, which marks an unconditional label rather than a directive, so JUMP to 4FCCH to step over it.
4F2D
SUB 0F6H D6 F6
Subtract 0F6H from Register A. Register A held 2FH less the third character, so the NO CARRY FLAG is left set precisely when that character was one of the digits 0 through 9.
4F2F
If the NO CARRY FLAG has been set the third character is a digit, which makes the line a numbered label rather than a directive, so JUMP to 4FC8H to compare it against any key the job is waiting on.
4F32
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL, bringing the address of the start of the line into Register Pair HL for logging.
4F33
GOSUB to the resident @LOGER vector at 447EH to write the directive line to the job log device, so the operator has a record of what the job did.
4F36
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL again, restoring the scanning position and putting the line start back on the stack.
4F37
LD A,(HL) 7E
Loop Start
Fetch the character at the scanning position addressed by Register Pair HL into Register A.
4F38
CP 0DH FE 0D
Compare it against 0DH, a carriage return. If Register A equals 0DH, the Z FLAG is set.
4F3A
If the Z FLAG has been set the line ended before any directive name was found, so JUMP to 4F5AH to discard it and read the next line.
4F3C
CP 20H FE 20
Compare the character against 20H, a space, which is skipped over between the slashes and the directive name.
4F3E
INC HL 23
Advance Register Pair HL to the next character of the line.
4F3F
If the Z FLAG has been set the character was a space, so LOOP BACK to 4F37H to look at the next one.
Loop End
4F41
DEC HL 2B
A non-space character was found. Step Register Pair HL back one place so it addresses that first character of the directive name.
4F42
LD DE,5181H 11 81 51
Load Register Pair DE with 5181H, the six-byte scratch area this overlay keeps just above its code, into which the directive name is copied.
4F45
LD B,05H 06 05
Load Register B with 05H, the length of a directive name in the keyword table. The extractor called below sets its own limit at 50DCH, so this value does not survive.
4F47
GOSUB to 50DCH to copy the directive name out of the line into the scratch area at 5181H, folding lower case to upper case and ending it with an 03H terminator.
4F4A
If the NZ FLAG has been set no name characters were found at all, so JUMP to 4F5AH to discard the line and read the next one.
4F4C
LD DE,5181H 11 81 51
Load Register Pair DE with 5181H, the scratch area now holding the extracted directive name.
4F4F
LD BC,51B5H 01 B5 51
Load Register Pair BC with 51B5H, the base of the directive keyword table, which holds ten seven-byte entries followed by a zero byte.
4F52
GOSUB to 5125H to look the extracted name up in that table. On a match the Z FLAG is set and Register Pair DE comes back holding the address of the routine that carries the directive out.
4F55
If the NZ FLAG has been set the name is not a directive this overlay knows, so JUMP to 4F5AH to discard the line and read the next one.
4F57
PUSH DE D5
Push the handler address that Register Pair DE came back holding onto the stack.
4F58
RET C9
Return, which transfers to the handler address just pushed. The handler finds the address of the start of the line still on the stack, which is how the directives that take an operand reach their text.
4F59
POP BC C1
Discard a saved Register Pair BC. Directives that were entered with an extra value stacked come back here so that the common tidy-up below sees the stack in the expected shape.
4F5A
POP HL E1
Discard the saved address of the start of the line.
4F5B
POP DE D1
Restore the caller's Register Pair DE, saved at 4F0CH.
4F5C
POP BC C1
Restore the caller's Register Pair BC, saved at 4F0BH.
4F5D
LOOP BACK to 4EE8H to take the next line of the job file, the directive on this line having been dealt with.
4F5F
LD HL,5197H 21 97 51
Load Register Pair HL with 5197H, the address of the text Bad JCL, Job aborted.
4F62
JUMP to 4E8DH to display that message, dismantle the job and transfer to the resident @ABORT vector at 4030H.
4F65H - The STOP Directive
STOP dismantles the job but does not abandon the command that is running. The keyboard is handed back to the operator, who finishes the command by hand.
4F65
GOSUB to 4EADH to dismantle the job: clear the in-effect flag in SFLAG$, close the job file, put the real keyboard driver back and restore the exit vectors. The job stops here but the command that is running carries on.
4F68
POP HL E1
Discard the saved address of the start of the line.
4F69
POP DE D1
Restore the caller's Register Pair DE, saved at 4F0CH.
4F6A
POP BC C1
Restore the caller's Register Pair BC, saved at 4F0BH.
4F6B
EI FB
Re-enable interrupts, which 4EADH disabled while it changed the resident vectors back.
4F6C
LD DE,4015H 11 15 40
Load Register Pair DE with 4015H, the address of the resident keyboard device control block KIDCB$, which now points once more at the real keyboard driver.
4F6F
JUMP to the ROM byte-input routine at 0013H to fetch a character from the device whose control block Register Pair DE addresses. The program that asked for keyboard input is answered from the keyboard, the job having ended.
4F72H - The DELAY Directive
DELAY reads a decimal count from the line and pauses for that many delay units, each of which honours the Fast and Slow setting recorded in SFLAG$.
4F72
GOSUB to 5167H to read the decimal number that follows the directive name out of the line addressed by Register Pair HL, returning it in Register Pair BC.
4F75
LD B,C 41
Copy the low byte of that count from Register C into Register B, the loop counter.
4F76
Loop Start
GOSUB to 504CH for one unit of delay, which also honours the Fast and Slow setting in SFLAG$.
4F79
DECrement Register B and loop back to 4F76H if it has not reached zero, giving the number of delay units the directive asked for.
Loop End
4F7B
JUMP to 4F5AH to tidy the stack and go on to the next line of the job.
4F7DH - The PAUSE Directive
PAUSE displays the rest of the line and waits. The wait ends when the interrupt-request bit in KFLAG$ is set, and pressing BREAK abandons the job entirely.
4F7D
POP HL E1
Recover the address of the start of the line into Register Pair HL.
4F7E
PUSH HL E5
Save it again for the tidy-up below.
4F7F
GOSUB to the resident @DSPLY vector at 4467H to show the text of the line, which is the prompt the operator is to read, on the video device.
4F82
Loop Start
GOSUB to 4E92H, which abandons the whole job if BREAK has been pressed and otherwise reports in the Z FLAG whether the wait should continue.
4F85
If the Z FLAG has been set nothing has asked for the wait to end, so LOOP BACK to 4F82H and keep waiting.
Loop End
4F87
JUMP to 4F5AH to tidy the stack and go on to the next line of the job.
4F89H - The KEYIN Directive and the Label Search
KEYIN is how a job asks a question. The rest of the line is displayed as a prompt, one key is read and echoed, and the job file is then scanned forward for a line beginning with two slashes and that key, or with three slashes which matches anything. The job resumes at the line after the label, which is what gives Job Control Language its branching.
4F89
POP HL E1
Recover the address of the start of the line into Register Pair HL.
4F8A
PUSH HL E5
Save it again for the label search below.
4F8B
LD A,(HL) 7E
Loop Start
Fetch the next character of the prompt text from the address in Register Pair HL into Register A.
4F8C
INC HL 23
Advance Register Pair HL to the following character.
4F8D
CP 0DH FE 0D
Compare the character against 0DH, a carriage return, which ends the prompt. If Register A equals 0DH, the Z FLAG is set.
4F8F
If the Z FLAG has been set the whole prompt has been shown, so JUMP to 4F96H to wait for the operator's reply.
4F91
GOSUB to the ROM character-output routine at 0033H to display the character in Register A at the cursor.
4F94
LOOP BACK to 4F8BH to display the next character of the prompt.
Loop End
4F96
GOSUB to the ROM keyboard routine at 0049H, which waits until the operator presses a key and returns it in Register A.
4F99
GOSUB to the ROM character-output routine at 0033H to echo the key just pressed so the operator can see the answer.
4F9C
LD (4FC9H),A 32 C9 4F
Self-Modifying Code
Store the key the operator pressed into 4FC9H, the immediate operand of the CP nn instruction at 4FC8H, so the label search below looks for the line labelled with that key.
4F9F
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, to close the echoed line.
4FA1
GOSUB to the ROM character-output routine at 0033H to move the cursor to the start of the next line.
4FA4
POP HL E1
Loop Start
Recover the address of the buffer the job lines are gathered into.
4FA5
PUSH HL E5
Save it again, since each pass of the search consumes its copy.
4FA6
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the address of JFCB$, the File Control Block of the compiled job file.
4FA9
GOSUB to the resident @CKEOF vector at 444BH to test whether the job file addressed by Register Pair DE has records left.
4FAC
If the NZ FLAG has been set the job file ran out before a matching label was found, so JUMP to 4EA3H to finish with the message Job done.
4FAF
Loop Start
GOSUB to the ROM byte-input routine at 0013H to fetch the next byte of the job file into Register A.
4FB2
LD (HL),A 77
Store it into the buffer at the address in Register Pair HL.
4FB3
INC HL 23
Advance Register Pair HL to the next position in the buffer.
4FB4
CP 0DH FE 0D
Compare the byte just stored against 0DH, a carriage return, which ends a job line. If Register A equals 0DH, the Z FLAG is set.
4FB6
If the NZ FLAG has been set the line is not complete, so LOOP BACK to 4FAFH to collect the next byte.
Loop End
4FB8
POP HL E1
Recover the address of the start of the line just collected.
4FB9
PUSH HL E5
Save it again for the next pass of the search.
4FBA
LD A,(HL) 7E
Fetch the first character of the line into Register A.
4FBB
CP 2FH FE 2F
Compare it against 2FH, the ASCII code for /. Only a line beginning with two of them can be a label. If Register A equals 2FH, the Z FLAG is set.
4FBD
If the NZ FLAG has been set this is an ordinary line rather than a label, so LOOP BACK to 4FA4H to collect the next one.
4FBF
INC HL 23
Advance Register Pair HL to the second character of the line.
4FC0
CP (HL) BE
Compare Register A, still holding 2FH, against that second character. If it is also a /, the Z FLAG is set.
4FC1
If the NZ FLAG has been set only one / was present, so LOOP BACK to 4FA4H to collect the next line.
4FC3
INC HL 23
Advance Register Pair HL to the third character of the line, which carries the label.
4FC4
SUB (HL) 96
Subtract that third character from Register A, which holds 2FH. The Z FLAG is set when the third character is itself a /, which marks a label that matches whatever key was pressed.
4FC5
If the Z FLAG has been set this is an unconditional label, so JUMP to 4FCCH to resume the job at the line after it.
4FC7
LD A,(HL) 7E
Fetch the third character of the line, the label itself, into Register A.
4FC8
CP 00H FE 00
Self-Modifying Code
Compare the label character in Register A against the operand at 4FC9H, which 4F9CH set to the key the operator pressed. If they match, the Z FLAG is set. This instruction is also entered directly from 4F2FH, which reaches it when a numbered label appears on the line the job is already executing.
4FCA
If the NZ FLAG has been set this label is not the one the operator selected, so LOOP BACK to 4FA4H to collect the next line.
Loop End
4FCC
LD (4FC9H),A 32 C9 4F
The label matches. Store Register A into 4FC9H, the operand of the comparison above, clearing the pending key so that a later label line is not taken by mistake.
4FCF
POP HL E1
Recover the address of the start of the label line.
4FD0
PUSH HL E5
Save it again for the tidy-up below.
4FD1
GOSUB to the resident @LOGER vector at 447EH to write the label line to the job log device, recording where the job resumed.
4FD4
JUMP to 4F5AH to tidy the stack and go on with the line that follows the label.
4FD6H - The ALERT Directive
ALERT plays a sequence of numbers as alternating tones and silences, so that the first number is sounded, the second is a pause, the third is sounded and so on. A group written in brackets is repeated: the position of the opening bracket is remembered in a self-modified operand and the closing bracket jumps back to it.
4FD6
XOR A AF
Set Register A to ZERO and clear all flags.
4FD7
LD (5006H),A 32 06 50
Self-Modifying Code
Store zero into 5006H, the immediate operand of the LD A,nn instruction at 5005H. That operand alternates between 00H and 0FFH so that successive numbers in the directive produce a tone and then a silence in turn, and it is reset here at the start of every ALERT.
4FDA
LD A,(HL) 7E
Loop Start
Fetch the next character of the directive operand from the address in Register Pair HL into Register A.
4FDB
INC HL 23
Advance Register Pair HL to the following character.
4FDC
CP 20H FE 20
Compare the character against 20H, a space, which separates the numbers in the operand.
4FDE
If the Z FLAG has been set the character is a space, so LOOP BACK to 4FDAH to skip it.
4FE0
CP 2CH FE 2C
Compare the character against 2CH, a comma, which may also separate the numbers.
4FE2
If the Z FLAG has been set the character is a comma, so LOOP BACK to 4FDAH to skip it.
4FE4
CP 0DH FE 0D
Compare the character against 0DH, a carriage return, which ends the directive.
4FE6
If the Z FLAG has been set the whole operand has been played, so JUMP to 4F5AH to tidy the stack and go on to the next line of the job.
4FE9
CP 29H FE 29
Compare the character against 29H, the ASCII code for ), which closes a repeated group.
4FEB
If the Z FLAG has been set the group is complete, so JUMP to 4FF6H to go back to its opening bracket.
4FED
CP 28H FE 28
Compare the character against 28H, the ASCII code for (, which opens a group that is to be repeated.
4FEF
If the NZ FLAG has been set the character is none of the separators or brackets, so it begins a number; JUMP to 5000H to play it.
4FF1
LD (4FF7H),HL 22 F7 4F
Self-Modifying Code
Store the current position in the line, held in Register Pair HL, into 4FF7H, the operand of the LD HL,nnnn instruction at 4FF6H, remembering where the repeated group begins.
4FF4
LOOP BACK to 4FDAH to read the first number inside the group.
4FF6
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the operand at 4FF7H, which 4FF1H set to the position of the opening bracket, so that the group is played again from its beginning.
4FF9
LD A,H 7C
Copy the high byte of that saved position into Register A.
4FFA
OR L B5
OR it with the low byte. The Z FLAG is set only when no opening bracket was ever recorded.
4FFB
If the NZ FLAG has been set a bracket was recorded, so LOOP BACK to 4FDAH to replay the group from it.
Loop End
4FFD
A closing bracket appeared with no opening bracket before it. JUMP to 4F5FH to report a malformed job and abandon the run.
5000
DEC HL 2B
Step Register Pair HL back one place so it addresses the first digit of the number, which the scan above stepped past.
5001
GOSUB to 5167H to read that decimal number out of the line, returning it in Register Pair BC and leaving Register Pair HL past the last digit.
5004
LD B,C 41
Copy the low byte of the number from Register C into Register B, where the tone and delay routines expect their count.
5005
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the operand at 5006H, which holds 00H or 0FFH according to whether the previous number in this directive produced a silence or a tone.
5007
XOR 0FFH EE FF
Exclusive-OR Register A with 0FFH, flipping it to the other of the two values.
5009
LD (5006H),A 32 06 50
Self-Modifying Code
Store the flipped value back into 5006H, so the next number in the directive takes the opposite action to this one.
500C
LD C,A 4F
Copy the flipped value into Register C, where its bit 0 selects between a tone and a silence.
500D
BIT 0,C CB 41
Test bit 0 of Register C.
500F
If the NZ FLAG has been set this number is to be sounded, so GOSUB to 501FH to play the tone it selects.
5012
BIT 0,C CB 41
Test bit 0 of Register C again, the tone routine having preserved it.
5014
If the Z FLAG has been set this number is a silence, so GOSUB to 5044H to wait for the corresponding time without sounding anything.
5017
GOSUB to 4E92H, which abandons the whole job if BREAK has been pressed and otherwise reports in the Z FLAG whether the directive should be cut short.
501A
If the NZ FLAG has been set the directive is to stop early, so JUMP to 4F5AH to tidy the stack and go on to the next line of the job.
501D
LOOP BACK to 4FDAH to read the next number of the directive operand.
501FH - Sound One Tone
The number selects one of the eight entries of the tone table at 5187H, whose first byte sets the pitch and whose second sets the length. The note is produced by swinging bit 0 of the cassette port at FFH, which is how the Model I makes sound, and interrupts are disabled across the loop so that a timer tick cannot stretch a half-cycle and spoil the pitch.
501F
PUSH BC C5
Save Register Pair BC, which holds the count and the tone-or-silence flag.
5020
PUSH HL E5
Save Register Pair HL, the current position in the directive line.
5021
LD HL,5187H 21 87 51
Load Register Pair HL with 5187H, the base of the tone table, which holds eight two-byte entries giving the half-period and the repeat count of each available note.
5024
LD A,B 78
Copy the number the directive gave from Register B into Register A.
5025
AND 07H E6 07
Keep only bits 2-0, reducing the number to one of the eight tones the table describes.
5027
RLCA 07
Rotate Register A left circularly, doubling it so that it indexes two-byte entries.
5028
LD C,A 4F
Move that offset into Register C.
5029
LD B,00H 06 00
Clear Register B so that Register Pair BC is the offset alone.
502B
ADD HL,BC 09
Add the offset to the table base in Register Pair HL, so Register Pair HL addresses the chosen entry.
502C
LD C,(HL) 4E
Fetch the entry's first byte, the half-period of the note, into Register C.
502D
INC HL 23
Advance Register Pair HL to the entry's second byte.
502E
LD L,(HL) 6E
Fetch that second byte, the number of complete cycles to sound, into Register L.
502F
DI F3
Disable interrupts, since a timer interrupt in the middle of the loop below would stretch a half-cycle and spoil the pitch.
5030
LD B,C 41
Loop Start
Copy the half-period from Register C into Register B, the counter for the first half of the cycle.
5031
LD A,01H 3E 01
Load Register A with 01H, the value that drives the cassette output line one way.
5033
OUT (0FFH),A D3 FF
Send Register A to the cassette port at FFH. Bit 0 of that port drives the cassette output, which is what the Model I sounds a tone through.
5035
DECrement Register B and loop back to 5035H if it has not reached zero, holding the output steady for the first half of the cycle. The instruction jumps to itself, so the delay is the count in Register B alone.
5037
LD B,C 41
Copy the half-period from Register C into Register B again, for the second half of the cycle.
5038
INC A 3C
Increment Register A to 02H, the value that drives the cassette output line the other way.
5039
OUT (0FFH),A D3 FF
Send Register A to the cassette port at FFH, completing the swing that makes the sound.
503B
DECrement Register B and loop back to 503BH if it has not reached zero, holding the output steady for the second half of the cycle.
503D
DEC L 2D
Decrement Register L, the count of complete cycles still to sound.
503E
If the NZ FLAG has been set there are cycles left, so LOOP BACK to 5030H to sound another one.
Loop End
5040
EI FB
Re-enable interrupts now that the note has finished.
5041
POP HL E1
Restore Register Pair HL, the position in the directive line.
5042
POP BC C1
Restore Register Pair BC, the count and the tone-or-silence flag.
5043
RET C9
Return to 500FH with the note sounded.
5044H - Silence and the Delay Unit
The counterpart of the tone routine waits without sounding anything. Both it and the DELAY directive measure time in units produced by the routine at 504CH, which doubles the pause when SFLAG$ shows the machine is running fast so that a job keeps roughly the same timing on either setting.
5044
OR B B0
Loop Start
OR Register A with Register B to test the count of delay units still to run. The Z FLAG is set when it reaches zero.
5045
RET Z C8
If the Z FLAG has been set the silence is complete, so return to 5014H.
5046
GOSUB to 504CH for one unit of delay.
5049
DECrement Register B and loop back to 5044H if it has not reached zero, giving the number of delay units the directive asked for.
Loop End
504B
RET C9
Return to 5014H with the silence complete.
504C
LD A,(430FH) 3A 0F 43
Fetch the resident system flag byte SFLAG$ from 430FH into Register A.
504F
BIT 3,A CB 5F
Test bit 3 of Register A, the copy of SFLAG$, which records whether the machine is running in its Fast or its Slow setting.
5051
If the NZ FLAG has been set the machine is running fast, so GOSUB to 5054H for a second helping of delay, keeping the timing of a job roughly the same on either setting.
5054
PUSH BC C5
Save Register Pair BC, which holds the caller's counts, across the pause.
5055
LD BC,199BH 01 9B 19
Load Register Pair BC with 199BH, the loop count that gives one unit of delay.
5058
GOSUB to the ROM delay routine at 0060H, which counts Register Pair BC down to zero.
505B
POP BC C1
Restore Register Pair BC.
505C
RET C9
Return with one unit of delay elapsed.
505DH - The FLASH Directive
FLASH shows the rest of the line, leaves it up for a fixed count of polling passes, then erases it with the video control codes 1BH and 1EH and pauses before showing it again, repeating the number of times the directive asks for.
505D
GOSUB to 5167H to read the decimal number that follows the directive name out of the line addressed by Register Pair HL, returning the number of flashes in Register Pair BC.
5060
LD B,C 41
Copy the low byte of that count from Register C into Register B, the loop counter.
5061
POP HL E1
Recover the address of the start of the line, which carries the text to be flashed.
5062
PUSH HL E5
Save it again for the next pass.
5063
PUSH BC C5
Loop Start
Save the count of flashes still to run.
5064
GOSUB to the resident @DSPLY vector at 4467H to show the text of the line on the video device.
5067
LD BC,4000H 01 00 40
Load Register Pair BC with 4000H, the number of passes the message is to remain visible for.
506A
Loop Start
GOSUB to 4E92H, which abandons the whole job if BREAK has been pressed and otherwise reports in the Z FLAG whether the directive should be cut short.
506D
If the NZ FLAG has been set the directive is to stop early, so JUMP to 4F59H to tidy the stack and go on to the next line of the job.
5070
DEC BC 0B
Decrement Register Pair BC, the count of passes the message still has to remain visible.
5071
LD A,B 78
Copy the high byte of that count into Register A.
5072
OR C B1
OR it with the low byte. The Z FLAG is set only when both halves have reached zero.
5073
If the NZ FLAG has been set the message is to stay up longer, so LOOP BACK to 506AH.
Loop End
5075
LD A,1BH 3E 1B
Load Register A with 1BH, the video control code that moves the cursor back over the message.
5077
GOSUB to the ROM character-output routine at 0033H to send it to the video device.
507A
LD A,1EH 3E 1E
Load Register A with 1EH, the video control code that erases from the cursor to the end of the line, taking the message off the screen.
507C
GOSUB to the ROM character-output routine at 0033H to send it to the video device.
507F
GOSUB to 504CH for one unit of delay, which is how long the message stays off the screen between flashes.
5082
POP BC C1
Restore the count of flashes still to run.
5083
DECrement Register B and loop back to 5063H if it has not reached zero, showing the message the number of times the directive asked for.
Loop End
5085
JUMP to 4F5AH to tidy the stack and go on to the next line of the job.
5088H - The WAIT Directive
WAIT collects a time written as hours, minutes and seconds into the scratch area and then polls the resident clock workspace until it matches. The clock fields run downwards in memory from the hours at 4043H, which is why the comparison steps its pointer backwards.
5088
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL, bringing the address of the start of the line into Register Pair HL so the text can be shown.
5089
GOSUB to the resident @DSPLY vector at 4467H to show the text of the line, which tells the operator what is being waited for, on the video device.
508C
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL again, restoring the scanning position and putting the line start back on the stack.
508D
LD DE,5181H 11 81 51
Load Register Pair DE with 5181H, the six-byte scratch area this overlay keeps just above its code, into which the three parts of the time are collected.
5090
LD B,03H 06 03
Load Register B with 03H, the number of fields in a time written as hours, minutes and seconds.
Overlapping Instruction
The three bytes at 5092H are read two ways. Reached in sequence they are JP NZ,0AFEH, which the flags on entry leave untaken so that execution falls through to 5095H. The DJNZ at 50A0H instead re-enters at 5093H, one byte in, where the same two operand bytes 0FEH and 0AH stand alone as CP 0AH. The effect is that the test for the colon between the fields of a time is skipped before the first field is read and applied between the fields thereafter, and 0AFEH is never a real destination.
5092
JP NZ,0AFEH C2 FE 0A
Overlapping Instruction
Jump if the NZ FLAG has been set. The flags on entry leave this jump untaken, so the two operand bytes 0FEH and 0AH that follow are stepped over on the first pass; the loop below re-enters at 5093H, where those same two bytes are executed as CP 0AH. The effect is that the separator test is skipped before the first field is read and applied between the fields thereafter.
5095
If the NZ FLAG has been set the fields were not separated by colons, so JUMP to 4F5FH to report a malformed job and abandon the run.
5098
PUSH BC C5
Save the count of time fields still to be read.
5099
GOSUB to 5167H to read the next decimal field of the time out of the line, returning it in Register Pair BC.
509C
LD (HL),C 71
Store the low byte of that field, held in Register C, at the current scanning position addressed by Register Pair HL, so that the block move below has it to hand.
509D
LDI ED A0
Block move one byte from the position addressed by Register Pair HL to the scratch area addressed by Register Pair DE, advancing both. The field is now held in the scratch area at 5181H.
509F
POP BC C1
Restore the count of time fields still to be read.
50A0
DECrement Register B and loop back to 5093H if it has not reached zero, collecting the hours, the minutes and the seconds in turn.
Loop End
50A2
Loop Start
GOSUB to 4E92H, which abandons the whole job if BREAK has been pressed and otherwise reports whether the wait should be cut short.
50A5
LD HL,5181H 21 81 51
Load Register Pair HL with 5181H, the scratch area holding the hours, minutes and seconds the job is waiting for.
50A8
LD DE,4043H 11 43 40
Load Register Pair DE with 4043H, the hours byte of the resident real-time clock workspace. The clock runs downwards in memory from there, with the minutes at 4042H and the seconds at 4041H.
50AB
LD B,03H 06 03
Load Register B with 03H, the number of fields to be compared.
50AD
LD A,(DE) 1A
Loop Start
Fetch the current clock field addressed by Register Pair DE into Register A.
50AE
CP (HL) BE
Compare it against the wanted value addressed by Register Pair HL. If they are equal, the Z FLAG is set.
50AF
If the NZ FLAG has been set the wanted time has not arrived, so LOOP BACK to 50A2H to poll again.
50B1
INC HL 23
Advance Register Pair HL to the next wanted field in the scratch area.
50B2
DEC DE 1B
Step Register Pair DE down to the next clock field, the workspace running from hours at 4043H down to seconds at 4041H.
50B3
DECrement Register B and loop back to 50ADH if it has not reached zero, comparing all three fields.
Loop End
50B5
The wanted time has arrived. JUMP to 5085H, which joins the common exit and goes on to the next line of the job.
50B7H - The INPUT Directive and the Keyboard Passthrough
INPUT hands the keyboard back to the operator for one reply. It plants the real driver address in the call at 50C8H and changes the request code the resident @DOKEY vector issues from 0CDH to 0DDH, which routes every following keyboard request straight to the operator until a terminating character comes back, at which point the code is set to 0CDH again and the job resumes supplying the keyboard.
50B7
POP HL E1
Recover the address of the start of the line, which carries the prompt the operator is to read.
50B8
GOSUB to the resident @DSPLY vector at 4467H to show that prompt on the video device.
50BB
LD HL,(43BEH) 2A BE 43
Fetch the real keyboard driver address from KIJCL$ at 43BEH, where 4E30H saved it when the job started.
50BE
LD (50C9H),HL 22 C9 50
Self-Modifying Code
Store that address into 50C9H, the operand of the CALL nnnn instruction at 50C8H, so that the keyboard requests which follow are handed to the real keyboard driver.
50C1
LD A,0DDH 3E DD
Load Register A with 0DDH, the request code the @DOKEY vector is to issue while the operator is typing.
50C3
LD (44BFH),A 32 BF 44
Self-Modifying Code
Store 0DDH into 44BFH, the immediate operand of the LD A,nn instruction at the resident @DOKEY vector 44BEH. That vector now asks for request code 0DDH instead of 0CDH, which the dispatch at 4E12H sends to 50C8H, so the operator answers from the keyboard rather than the job supplying the characters.
50C6
POP DE D1
Restore the caller's Register Pair DE, saved at 4F0CH.
50C7
POP BC C1
Restore the caller's Register Pair BC, saved at 4F0BH.
50C8
CALL 0000H CD 00 00
Self-Modifying Code
GOSUB to the real keyboard driver, whose address 50BEH planted in the operand at 50C9H, to collect one character from the operator. This address is also the entry the dispatch at 4E14H uses for every request code 0DDH while the operator is answering.
50CB
PUSH AF F5
Save the character the operator typed, together with the flags.
50CC
DEC A 3D
Decrement Register A. The Z FLAG is set if the character was 01H.
50CD
If the Z FLAG has been set the operator's reply has been terminated, so JUMP to 50D5H to hand the keyboard back to the job.
50CF
CP 0CH FE 0C
Compare the decremented character against 0CH, which identifies an original value of 0DH, a carriage return.
50D1
If the Z FLAG has been set the operator pressed ENTER and the reply is complete, so JUMP to 50D5H to hand the keyboard back to the job.
50D3
POP AF F1
The reply is still being typed. Restore the character together with the flags.
50D4
RET C9
Return that character to the program that asked for it, leaving the interception in place for the next one.
50D5
LD A,0CDH 3E CD
Load Register A with 0CDH, the request code the @DOKEY vector issues when a job is supplying the keyboard.
50D7
LD (44BFH),A 32 BF 44
Self-Modifying Code
Store 0CDH back into 44BFH, the operand of the LD A,nn at the resident @DOKEY vector 44BEH, so that keyboard requests are once again answered by the job rather than by the operator.
50DA
POP AF F1
Restore the terminating character together with the flags.
50DB
RET C9
Return that character to the program that asked for it, the operator's reply being complete.
50DCH - Extract a Name and Test for Alphanumeric
The directive name is copied out of the job line into the scratch area, folded to upper case so it may be written either way, and closed with an 03H terminator. A self-modified operand records whether any characters were copied at all, which is how an empty name is reported as a malformed job.
50DC
LD B,08H 06 08
Load Register B with 08H, the largest number of characters that will be copied out of the line into the scratch area. The caller's value is replaced here, so every extraction uses this limit.
50DE
LD A,B 78
Copy that limit into Register A so it can be planted as the not-yet-copied marker.
50DF
LD (5113H),A 32 13 51
Self-Modifying Code
Store the non-zero value into 5113H, the operand of the LD A,nn instruction at 5112H. It is cleared at 5105H as soon as a character is copied, so at the end it reports whether the extraction found anything at all.
50E2
INC B 04
Increment Register B, so that the first pass of the loop below reduces it back to the true limit.
50E3
LD A,(HL) 7E
Loop Start
Fetch the next character of the line from the address in Register Pair HL into Register A.
50E4
CP 03H FE 03
Compare it against 03H, the string terminator, which ends the extraction.
50E6
If the Z FLAG has been set the string has ended, so JUMP to 510EH to terminate the extracted name.
50E8
CP 0DH FE 0D
Compare the character against 0DH, a carriage return, which also ends the extraction.
50EA
If the Z FLAG has been set the line has ended, so JUMP to 510EH to terminate the extracted name.
50EC
CP 28H FE 28
Compare the character against 28H, the ASCII code for (, which begins an operand and therefore ends the name.
50EE
If the Z FLAG has been set an operand follows, so JUMP to 510EH to terminate the extracted name.
50F0
INC HL 23
Advance Register Pair HL to the next character of the line.
50F1
GOSUB to 5117H to test whether the character in Register A is a digit or an upper-case letter, which comes back reported in the CARRY flag.
50F4
If the NO CARRY FLAG has been set the character is already a digit or an upper-case letter, so JUMP to 5100H to store it unchanged.
50F6
CP 61H FE 61
Compare the character against 61H, the ASCII code for lower-case a.
50F8
If the CARRY FLAG has been set the character is below the lower-case letters and so is not part of a name, so JUMP to 510EH to terminate the extracted name.
50FA
CP 7BH FE 7B
Compare the character against 7BH, the ASCII code just above lower-case z.
50FC
If the NO CARRY FLAG has been set the character is above the lower-case letters and so is not part of a name, so JUMP to 510EH to terminate the extracted name.
50FE
RES 5,A CB AF
The character is a lower-case letter. Clear bit 5 of Register A, which folds it to upper case so that directive names may be written either way.
5100
DEC B 05
Decrement Register B, the count of character positions still free in the scratch area.
5101
If the Z FLAG has been set the scratch area is full, so JUMP to 510BH to go on scanning without storing anything more.
5103
LD (DE),A 12
Store the character into the scratch area at the address in Register Pair DE.
5104
XOR A AF
Set Register A to ZERO and clear all flags.
5105
LD (5113H),A 32 13 51
Self-Modifying Code
Store zero into 5113H, the operand of the LD A,nn at 5112H, recording that at least one character has been copied.
5108
INC DE 13
Advance Register Pair DE to the next position in the scratch area.
5109
LOOP BACK to 50E3H to examine the next character of the line.
510B
INC B 04
Increment Register B to undo the decrement above, so the scanning continues without the counter running past zero.
510C
LOOP BACK to 50E3H to examine the next character of the line.
Loop End
510E
LD C,A 4F
Save the character that ended the name in Register C, so it can be returned to the caller.
510F
LD A,03H 3E 03
Load Register A with 03H, the terminator that closes an LDOS string.
5111
LD (DE),A 12
Store it into the scratch area at the address in Register Pair DE, ending the extracted name.
5112
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the operand at 5113H, which is zero when at least one character was copied and non-zero when none was.
5114
OR A B7
OR Register A with itself, so the Z FLAG reports success and the NZ FLAG reports that no name was found.
5115
LD A,C 79
Recover the character that ended the name into Register A, the flags set above being preserved.
5116
RET C9
Return to 4F47H with the extracted name in the scratch area and the Z FLAG reporting whether anything was found.
5117
CP 30H FE 30
Compare the character in Register A against 30H, the ASCII code for 0.
5119
RET C D8
If the CARRY FLAG has been set the character is below the digits, so return with the CARRY flag reporting that it is not alphanumeric.
511A
CP 3AH FE 3A
Compare the character against 3AH, the ASCII code just above 9.
511C
If the CARRY FLAG has been set the character is a digit, so JUMP to 5123H to report it as alphanumeric.
511E
CP 41H FE 41
Compare the character against 41H, the ASCII code for A.
5120
RET C D8
If the CARRY FLAG has been set the character lies between the digits and the letters, so return with the CARRY flag reporting that it is not alphanumeric.
5121
CP 5BH FE 5B
Compare the character against 5BH, the ASCII code just above Z. The CARRY flag is set when the character is an upper-case letter.
5123
CCF 3F
Complement the CARRY flag, so that the routine returns with no carry for a digit or an upper-case letter and with carry for anything else.
5124
RET C9
Return to 50F1H or 5159H with the CARRY flag reporting whether the character is alphanumeric.
5125H - Look Up a Directive Name
The extracted name is searched for in the seven-byte entries of the keyword table. A shorter name matches an entry padded with spaces, and a match returns the two-byte handler address that follows the name in the entry.
5125
PUSH HL E5
Save the caller's Register Pair HL, the position in the job line.
5126
LD H,B 60
Copy the high byte of the table base from Register B into Register H.
5127
LD L,C 69
Copy the low byte from Register C into Register L, so Register Pair HL addresses the first entry of the keyword table.
5128
LD A,(DE) 1A
Loop Start
Fetch the first character of the name being looked up, from the scratch area addressed by Register Pair DE, into Register A.
5129
CP (HL) BE
Compare it against the first character of the current table entry, addressed by Register Pair HL. If they are equal, the Z FLAG is set.
512A
If the Z FLAG has been set the first characters agree, so JUMP to 5139H to compare the rest of the name.
512C
PUSH BC C5
Save the table base held in Register Pair BC while the entry pointer is advanced.
512D
LD BC,0007H 01 07 00
Load Register Pair BC with 0007H, the length of one keyword table entry: five characters of name followed by a two-byte handler address.
5130
ADD HL,BC 09
Add seven to Register Pair HL, so it addresses the next entry of the table.
5131
POP BC C1
Restore the table base into Register Pair BC.
5132
LD A,(HL) 7E
Fetch the first character of the new entry into Register A. A zero byte marks the end of the table.
5133
OR A B7
OR Register A with itself. The Z FLAG is set only at the end of the table.
5134
If the NZ FLAG has been set there is another entry to try, so LOOP BACK to 5128H.
Loop End
5136
POP HL E1
The whole table has been searched without a match. Restore the caller's Register Pair HL.
5137
INC A 3C
Increment Register A, which was zero, so that the NZ FLAG reports to 4F52H that the name is not a directive.
5138
RET C9
Return with the NZ FLAG set.
5139
LD B,04H 06 04
Load Register B with 04H, the number of characters of the name still to be compared after the first.
513B
PUSH HL E5
Save the address of the current table entry, which is needed again if the comparison fails.
513C
PUSH DE D5
Save the address of the name being looked up alongside it.
513D
INC DE 13
Loop Start
Advance Register Pair DE to the next character of the name being looked up.
513E
INC HL 23
Advance Register Pair HL to the next character of the table entry.
513F
LD A,(DE) 1A
Fetch the next character of the name being looked up into Register A.
5140
CP 03H FE 03
Compare it against 03H, the terminator that closes the extracted name.
5142
If the Z FLAG has been set the name has ended, so JUMP to 515EH to check that the table entry is padded out to the same point.
5144
CP 0DH FE 0D
Compare the character against 0DH, a carriage return, which also ends the name.
5146
If the Z FLAG has been set the name has ended, so JUMP to 515EH to check the padding of the table entry.
5148
CP (HL) BE
Compare the character against the corresponding character of the table entry, addressed by Register Pair HL. If they are equal, the Z FLAG is set.
5149
If the NZ FLAG has been set the names differ here, so JUMP to 5159H to decide whether this is a real mismatch.
514B
DECrement Register B and loop back to 513DH if it has not reached zero, comparing the remaining four characters.
Loop End
514D
POP DE D1
Every character matched. Discard the saved address of the name being looked up.
514E
POP BC C1
Recover the address of the matching table entry into Register Pair BC.
514F
LD HL,0005H 21 05 00
Load Register Pair HL with 0005H, the offset of the handler address within a table entry.
5152
ADD HL,BC 09
Add the address of the entry, so Register Pair HL addresses the low byte of that handler address.
5153
LD E,(HL) 5E
Fetch the low byte of the handler address into Register E.
5154
INC HL 23
Advance Register Pair HL to the high byte of the handler address.
5155
LD D,(HL) 56
Fetch it into Register D, so Register Pair DE now holds the address of the routine that carries the directive out.
5156
POP HL E1
Restore the caller's Register Pair HL, the position in the job line, which the directive handlers need.
5157
XOR A AF
Set Register A to ZERO and clear all flags, setting the Z FLAG to report the match to 4F52H.
5158
RET C9
Return with Register Pair DE holding the handler address and the Z FLAG set.
5159
GOSUB to 5117H to test whether the character that failed to match is a digit or an upper-case letter.
515C
If the NO CARRY FLAG has been set the character is a genuine part of a longer name, so JUMP to 5163H to give this entry up.
515E
LD A,(HL) 7E
The name has ended. Fetch the corresponding character of the table entry into Register A.
515F
CP 20H FE 20
Compare it against 20H, a space. Entries shorter than five characters are padded with spaces, so a space here means the entry has ended too.
5161
If the Z FLAG has been set both names ended together, so LOOP BACK to 514DH to collect the handler address.
5163
POP DE D1
Restore the address of the name being looked up.
5164
POP HL E1
Restore the address of the current table entry.
5165
LOOP BACK to 512CH to advance to the next entry of the table.
5167H - Read a Decimal Number
Digits are accumulated by multiplying the running total by ten through repeated additions of Register Pair HL to itself. The routine returns the value in Register Pair BC and leaves in Register A the character that stopped it, less 30H, which is how the WAIT directive recognises the colons between the fields of a time.
5167
LD BC,0000H 01 00 00
Clear Register Pair BC, which accumulates the value of the number being read.
516A
LD A,(HL) 7E
Loop Start
Fetch the next character of the line from the address in Register Pair HL into Register A.
516B
SUB 30H D6 30
Subtract 30H, the ASCII code for 0, converting a digit to its value. Register A is left holding the character code less 30H, which is how the callers at 5093H identify the separator that ended the number.
516D
RET C D8
If the CARRY FLAG has been set the character is below 0 and so is not a digit; return with the accumulated value in Register Pair BC.
516E
CP 0AH FE 0A
Compare the converted value against 0AH, that is ten. A digit gives a value below ten.
5170
RET NC D0
If the NO CARRY FLAG has been set the character is above 9 and so is not a digit; return with the accumulated value in Register Pair BC.
5171
PUSH BC C5
Save the accumulated value held in Register Pair BC.
5172
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL, bringing the accumulated value into Register Pair HL for the multiplication and putting the line position on the stack.
5173
ADD HL,HL 29
Add Register Pair HL to itself, doubling the accumulated value.
5174
ADD HL,HL 29
Add Register Pair HL to itself again, so the accumulated value has been multiplied by four.
5175
ADD HL,BC 09
Add the original accumulated value, still in Register Pair BC, giving five times the original.
5176
ADD HL,HL 29
Add Register Pair HL to itself once more, giving ten times the original accumulated value.
5177
LD B,00H 06 00
Clear Register B, the high byte of the digit about to be added.
5179
LD C,A 4F
Move the value of the new digit from Register A into Register C.
517A
ADD HL,BC 09
Add the new digit to the multiplied total in Register Pair HL.
517B
LD B,H 44
Copy the high byte of the new total into Register B.
517C
LD C,L 4D
Copy the low byte into Register C, so Register Pair BC once again accumulates the value.
517D
POP HL E1
Recover the position in the line from the stack into Register Pair HL.
517E
INC HL 23
Advance Register Pair HL to the next character of the number.
517F
LOOP BACK to 516AH to take the next digit.
Loop End
5181H - Scratch Area (Not Present in the File)
Six bytes that the load module deliberately steps over: the file loads 4E00H through 5180H and resumes at 5187H. The area needs no initial contents because it is only ever written before it is read, holding the directive name that 50DCH extracts and, for the WAIT directive, the three fields of the time collected at 509DH.
5181-5186
DEFS 6
Six bytes of scratch, not loaded from the file. The name extractor at 50DCH copies the directive name here and closes it with an 03H terminator, and the lookup at 5125H then reads it from here. The WAIT directive reuses the same area at 508DH for the hours, minutes and seconds it collects, which is why only three of the six bytes are used in that case.
5187H - Tone Table
Eight two-byte entries, indexed by the low three bits of the number the ALERT directive is given. The first byte of an entry is the half-period held by the delay loops at 5035H and 503BH and so sets the pitch; the second is the number of complete cycles sounded and so sets the length. The two run in opposite directions through the table, so the higher notes are sounded for more cycles and every entry lasts about the same time.
5187
DEFB 6BH, 9CH 6B 9C
Tone table entry 0, selected when the ALERT directive is given a number whose low three bits are 0. The first byte, 6BH, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 9CH, is the number of complete cycles sounded and so sets the length. This is the lowest of the eight notes.
5189
DEFB 72H, 92H 72 92
Tone table entry 1, selected when the ALERT directive is given a number whose low three bits are 1. The first byte, 72H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 92H, is the number of complete cycles sounded and so sets the length.
518B
DEFB 79H, 89H 79 89
Tone table entry 2, selected when the ALERT directive is given a number whose low three bits are 2. The first byte, 79H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 89H, is the number of complete cycles sounded and so sets the length.
518D
DEFB 80H, 81H 80 81
Tone table entry 3, selected when the ALERT directive is given a number whose low three bits are 3. The first byte, 80H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 81H, is the number of complete cycles sounded and so sets the length.
518F
DEFB 87H, 7AH 87 7A
Tone table entry 4, selected when the ALERT directive is given a number whose low three bits are 4. The first byte, 87H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 7AH, is the number of complete cycles sounded and so sets the length.
5191
DEFB 8EH, 74H 8E 74
Tone table entry 5, selected when the ALERT directive is given a number whose low three bits are 5. The first byte, 8EH, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 74H, is the number of complete cycles sounded and so sets the length.
5193
DEFB 95H, 6FH 95 6F
Tone table entry 6, selected when the ALERT directive is given a number whose low three bits are 6. The first byte, 95H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 6FH, is the number of complete cycles sounded and so sets the length.
5195
DEFB 99H, 6BH 99 6B
Tone table entry 7, selected when the ALERT directive is given a number whose low three bits are 7. The first byte, 99H, is the half-period the cassette output is held for by the loops at 5035H and 503BH, and so sets the pitch; the second, 6BH, is the number of complete cycles sounded and so sets the length. This is the highest of the eight notes.
5197H - Message Text
The three ways a job can end, written as two overlapping strings and one separate one. The malformed-job message at 5197H runs straight into the abort message at 51A0H, so the shorter text is simply the tail of the longer and the two share their carriage return.
5197
DEFM "Bad JCL, " 42 61 64 20 4A 43 4C 2C 20
The opening of the malformed-job message, loaded into Register Pair HL at 4F5FH whenever a line beginning with a slash cannot be understood. It runs on into the text at 51A0H, so the whole message reads Bad JCL, Job aborted.
51A0
DEFM "Job aborted" 4A 6F 62 20 61 62 6F 72 74 65 64
The abort message, loaded into Register Pair HL at 4E8AH when a program under the job fails and at 4E6FH when the operator presses BREAK. It is also the tail of the malformed-job message that begins at 5197H.
51AB
DEFB 0DH 0D
The carriage return that ends both the abort message and the malformed-job message, which the resident @LOGOT vector at 447BH takes as the end of the string.
51AC
DEFM "Job done" 4A 6F 62 20 64 6F 6E 65
The normal completion message, loaded into Register Pair HL at 4EA3H when the job file has been read to its end or an EXIT directive is reached.
51B4
DEFB 0DH 0D
The carriage return that ends the completion message.
51B5H - Directive Keyword Table
Ten seven-byte entries followed by a zero byte, searched by the lookup at 5125H. Each entry is five characters of directive name, padded with a space where the name is shorter, followed by the two-byte address of the routine that carries the directive out. The entries are in alphabetical order except for INPUT, which sits last and was evidently added after the rest.
51B5
DEFM "ABORT" / DEFW 4E8AH 41 42 4F 52 54 8A 4E
Keyword table entry for the ABORT directive. The five name characters are followed by the address of the routine that carries it out, 4E8AH, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to end the job at once, reporting Job aborted.
51BC
DEFM "ALERT" / DEFW 4FD6H 41 4C 45 52 54 D6 4F
Keyword table entry for the ALERT directive. The five name characters are followed by the address of the routine that carries it out, 4FD6H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to sound the sequence of tones and silences given as its operand.
51C3
DEFM "DELAY" / DEFW 4F72H 44 45 4C 41 59 72 4F
Keyword table entry for the DELAY directive. The five name characters are followed by the address of the routine that carries it out, 4F72H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to pause for the number of delay units given as its operand.
51CA
DEFM "EXIT " / DEFW 4EA3H 45 58 49 54 20 A3 4E
Keyword table entry for the EXIT directive. The five name characters are followed by the address of the routine that carries it out, 4EA3H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to end the job normally, reporting Job done. The name is padded to five characters with a space, which the comparison at 515FH accepts as the end of a shorter name.
51D1
DEFM "FLASH" / DEFW 505DH 46 4C 41 53 48 5D 50
Keyword table entry for the FLASH directive. The five name characters are followed by the address of the routine that carries it out, 505DH, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to show the rest of the line the given number of times, blanking it between each.
51D8
DEFM "KEYIN" / DEFW 4F89H 4B 45 59 49 4E 89 4F
Keyword table entry for the KEYIN directive. The five name characters are followed by the address of the routine that carries it out, 4F89H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to show a prompt, read one key, and resume at the label matching that key.
51DF
DEFM "PAUSE" / DEFW 4F7DH 50 41 55 53 45 7D 4F
Keyword table entry for the PAUSE directive. The five name characters are followed by the address of the routine that carries it out, 4F7DH, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to show the rest of the line and wait until the job is told to carry on.
51E6
DEFM "STOP " / DEFW 4F65H 53 54 4F 50 20 65 4F
Keyword table entry for the STOP directive. The five name characters are followed by the address of the routine that carries it out, 4F65H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to end the job but leave the command that is running to finish from the keyboard. The name is padded to five characters with a space, which the comparison at 515FH accepts as the end of a shorter name.
51ED
DEFM "WAIT " / DEFW 5088H 57 41 49 54 20 88 50
Keyword table entry for the WAIT directive. The five name characters are followed by the address of the routine that carries it out, 5088H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to wait until the real-time clock reaches the time given as its operand. The name is padded to five characters with a space, which the comparison at 515FH accepts as the end of a shorter name.
51F4
DEFM "INPUT" / DEFW 50B7H 49 4E 50 55 54 B7 50
Keyword table entry for the INPUT directive. The five name characters are followed by the address of the routine that carries it out, 50B7H, which the lookup at 5153H returns in Register Pair DE and the caller reaches by pushing it and returning. This directive tells the job to show a prompt and let the operator type the answer from the keyboard.
51FB
DEFB 00H 00
The zero byte that ends the keyword table. The search at 5132H fetches the first character of each entry in turn and stops when it finds this, reporting through the NZ FLAG at 5137H that the directive name is not one this overlay knows.