[
Index] [
Previous] [
Next]
1.4 Utility Functions
Some useful functions.
GetFlowPtr
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.
019C
E3
XTHL
POP HL (ie HL=(HL))
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
CopyMemoryUp
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.
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
01AE
7E
MOV A,M
01AF
02
STAX B
01B0
C8
RZ
Exit if DE reached.
01B1
0B
DCX B
01B2
2B
DCX H
CheckEnoughVarSpace
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
01BA
0600
MVI B,00
BC=C*4
01BC
09
DAD B
01BD
09
DAD B
01C1
E1
POP H
01C2
C9
RET
CheckEnoughMem
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
01CA
EB
XCHG
01CB
D1
POP D
01CC
D0
RNC
Three common errors.
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
Error
Resets the stack, prints an error code (offset into error codes table is given in E), and stops program execution.
01DE
57
MOV D,A
01DF
3E3F
MVI A,'?'
Print '?'
01E2
19
DAD D
HL points to error code.
01E3
7E
MOV A,M
01E4
DF
RST
OutChar
Print first char of code.
01E6
DF
RST
OutChar
Print second char of code.
01E7
218101
LXI H,
szError
Print " ERROR".
01F0
7C
MOV A,H
01F1
A5
ANA L
01F2
3C
INR A
01F6
01....
LXI B,....
LXI over Stop and fall into Main
[Index] [Previous] [Next]