[
Index] [
Previous] [
Next]
1.11 Jumping to Program Lines
LineNumberFromStr
Gets a line number from a string pointer. The string pointer is passed in in HL, and the integer result is returned in DE. Leading spaces are skipped over, and it returns on finding the first non-digit. The largest possible line number is 65529 - it syntax errors out if the value of the first four digits is more then 6552.
One interesting feature of this function is that it returns with Z set if it found a valid number (or the string was empty), or NZ if the string didn't lead with a number.
Decrement string ptr (so we're pointing at preceding character) and initialise result to 0.
049D
2B
LineNumberFromStr
DCX H
049E
110000
LXI D,0000
Get next character and exit if it's not alphanumeric.
04A2
D0
RNC
04A3
E5
PUSH H
04A4
F5
PUSH PSW
Preserve flags
Syntax Error out if line number is already > 6552. This is really erroring out of the line number is >65529, since the next digit has not been counted in yet.
04A5
219819
LXI H,1998
Decimal 6552
Multiply result by 10.
04AC
62
MOV H,D
04AD
6B
MOV L,E
04AE
19
DAD D
04AF
29
DAD H
04B0
19
DAD D
04B1
29
DAD H
04B2
F1
POP PSW
Add this digit's value to the result and jump back.
04B3
D630
SUI '0'
04B5
5F
MOV E,A
04B6
1600
MVI D,00
04B8
19
DAD D
04B9
EB
XCHG
04BA
E1
POP H
Gosub
Gosub sets up a flow struct on the stack and then falls into Goto. The flow struct is KWID_GOSUB, preceded by the line number of the gosub statement, in turn preceded by prog ptr to just after the gosub statement.
Check we've got at least 12 bytes of memory spare.
04BE
0E03
Gosub
MVI C,03
Preserve return address in BC.
04C3
C1
POP B
Push prog ptr.
04C4
E5
PUSH H
Push the current line number on the stack so we can RETURN to it later.
04C5
E5
PUSH H
04C9
E3
XTHL
Push keyword ID of 'GOSUB' onto stack. Note we only push the single byte.
04CA
168C
MVI D,KWID_GOSUB
04CC
D5
PUSH D
04CD
33
INX SP
Push return address preserved in BC, and fall into GOTO.
04CE
C5
PUSH B
Goto
Sets program execution to continue from the line number argument.
Get line number argument in DE and return NZ indicating syntax error if the argument was a non-number .
04D2
C0
RNZ
Look up the address of the program line with the provided number, put that into HL, and return if the program line was found (ie it exists).
04D6
60
MOV H,B
04D7
69
MOV L,C
04D8
2B
DCX H
04D9
D8
RC
Carry flag was not set by FindProgramLine so Undefined Subroutine (US) error.
04DA
1E0E
MVI E,0E
Return
Returns program execution to the statement following the last GOSUB. Information about where to return to is kept on the stack in a flow struct (see notes).
No arguments allowed.
04DF
C0
Return
RNZ
Get pointer to flow struct on stack
04E0
16FF
MVI D,FF
04E5
F9
SPHL
If the first byte of the flow struct is not KWID_GOSUB (as placed there by the Gosub handler) then the gosub can't have happened so exit to a Return without Gosub (RG) error.
04E6
FE8C
CPI KWID_GOSUB
04E8
1E04
MVI E,04
Get line number of Gosub statement from flow struct into CURRENT_LINE.
04ED
E1
POP H
Set return address to ExecNext and pop the prog ptr to just after the Gosub statement into HL.
04F4
E3
XTHL
Safe to fall into FindNextStatement, since we're already at the end of the line!...
FindNextStatement
Finds the end of the statement or the end of the program line.
BUG: There is an interesting bug in this block, although it's harmless as by luck it's impossible to see it. The byte at 04F7 is 0x10, an illegal instruction, which is in turn followed by a NOP. This illegal instruction is almost certainly supposed to be 0x0E, so as to become the two-byte instruction MOV C,00. If this were the case it would make perfect sense as the loop reads ahead until it finds a null byte terminating the line or whatever the C register is loaded with.
04F7 is jumped to in two places - it is the REM handler, and also when an IF statement's condition evals to false and the rest of the line needs to be skipped. Luckily in both these cases, C just happens to be loaded with a byte that cannot occur in the program so the null byte marking the end of the line is found as expected.
Load C with the statement seperator character, a colon ':', and also LXI over the illegal instruction (which is a bug - see above).
04F5
013A..
FindNextStatement
LXI B,..3A
04F7
10
Rem
???
04F8
00
NOP
04F9
7E
FindNextStatementLoop
MOV A,M
04FA
B7
ORA A
04FB
C8
RZ
04FC
B9
CMP C
04FD
C8
RZ
04FE
23
INX H
[Index] [Previous] [Next]