Sets HL to point to the appropriate flow struct on the stack. On entry, if this was called by the NEXT keyword handler then DE is pointing to the variable following the NEXT keyword.
The first four bytes on the stack are (or rather, should be) two return addresses. We're not interested in them, so the first thing to do is set HL to point to SP+4. | ||||
0192 | 210400 | GetFlowPtr | LXI H,0004 | HL=SP+4 (ie get word |
0195 | 39 | DAD SP | just past return addr) | |
Get the keyword ID, the byte that precedes the flow struct. Then we increment HL so it points to (what should be) the flow struct, and return if the keyword ID is not 'FOR'. | ||||
0196 | 7E | MOV A,M | ||
0197 | 23 | INX H | ||
0198 | FE81 | CPI 81 | 'FOR'? | |
019A | C0 | RNZ | Return if not 'FOR' | |
Special treatment for FOR flow structs. Here we check that we've got the right one, ie the one required by the NEXT statement which called us. When we're called by NEXT, it sets DE to point to the variable in the NEXT statement. So here we get the first word of the FOR flow struct which is the address of the FOR variable, and compare it to the one we've been given in DE. If they match, then we've found the flow struct wanted and we can safely return. If not then we jump 13 bytes up the stack - 13 bytes is the size of the FOR flow struct - and loop back to try again. | ||||
019B | F7 | RST PushNextWord | PUSH (HL) | |
019C | E3 | XTHL | POP HL (ie HL=(HL)) | |
019D | E7 | RST CompareHLDE | HL==DE? | |
019E | 010D00 | LXI B,000D | ||
01A1 | E1 | POP H | Restore HL | |
01A2 | C8 | RZ | Return if var ptrs match. | |
01A3 | 09 | DAD B | HL+=000D | |
01A4 | C39601 | JMP GetFlowPtr+4 | Loop |
Copies a block of memory from BC to HL. Copying is done backwards, down to and including the point where BC==DE. It goes backwards because this function is used to move blocks of memory forward by as little as a couple of bytes. If it copied forwards then the block of memory would overwrite itself.
01A7 | CDC301 | CopyMemoryUp | CALL CheckEnoughMem | |
Exchange BC with HL, so HL now points to the source and BC points to destination. | ||||
01AA | C5 | PUSH B | Exchange BC with HL. | |
01AB | E3 | XTHL | ||
01AC | C1 | POP B | ||
01AD | E7 | CopyMemLoop | RST CompareHLDE | HL==DE? |
01AE | 7E | MOV A,M | ||
01AF | 02 | STAX B | ||
01B0 | C8 | RZ | Exit if DE reached. | |
01B1 | 0B | DCX B | ||
01B2 | 2B | DCX H | ||
01B3 | C3AD01 | JMP CopyMemLoop |
Checks that there is enough room for C*4 bytes on top of (VAR_TOP) before it intrudes on the stack. Probably varspace.
01B6 | E5 | CheckEnoughVarSpace | PUSH H | |
01B7 | 2A6B01 | LHLD VAR_TOP | ||
01BA | 0600 | MVI B,00 | BC=C*4 | |
01BC | 09 | DAD B | ||
01BD | 09 | DAD B | ||
01BE | CDC301 | CALL CheckEnoughMem | ||
01C1 | E1 | POP H | ||
01C2 | C9 | RET |
Checks that HL is more than 32 bytes away from the stack pointer. If HL is within 32 bytes of the stack pointer then this function falls into OutOfMemory.
01C3 | D5 | CheckEnoughMem | PUSH D | |
01C4 | EB | XCHG | ||
01C5 | 21DEFF | LXI H,FFDE | HL=-34 (extra 2 bytes for return address) | |
01C8 | 39 | DAD SP | ||
01C9 | E7 | RST CompareHLDE | ||
01CA | EB | XCHG | ||
01CB | D1 | POP D | ||
01CC | D0 | RNC |
Notice use of LXI trick.
01CD | 1E0C | OutOfMemory | MVI E,0C | |
01CF | 01.... | LXI B,.... | ||
01D0 | 1E02 | SyntaxError | MVI E,02 | |
01D2 | 01.... | LXI B,.... | ||
01D3 | 1E14 | DivideByZero | MVI E,14 | |
Resets the stack, prints an error code (offset into error codes table is given in E), and stops program execution.
01D5 | CDB502 | Error | CALL ResetStack | |
01D8 | CD8A05 | CALL NewLine | ||
01DB | 21FA00 | LXI H,ERROR_CODES | ||
01DE | 57 | MOV D,A | ||
01DF | 3E3F | MVI A,'?' | Print '?' | |
01E1 | DF | RST OutChar | ||
01E2 | 19 | DAD D | HL points to error code. | |
01E3 | 7E | MOV A,M | ||
01E4 | DF | RST OutChar | Print first char of code. | |
01E5 | D7 | RST NextChar | ||
01E6 | DF | RST OutChar | Print second char of code. | |
01E7 | 218101 | LXI H,szError | Print " ERROR". | |
01EA | CDA305 | CALL PrintString | ||
01ED | 2A6101 | LHLD CURRENT_LINE | ||
01F0 | 7C | MOV A,H | ||
01F1 | A5 | ANA L | ||
01F2 | 3C | INR A | ||
01F3 | C42F0B | CNZ PrintIN | ||
01F6 | 01.... | LXI B,.... | LXI over Stop and fall into Main |