Explaining the code: please enter
Today, I will explain a small routine called ENTER (or DOCOL) which deals with words that are defined in terms of other Forth words. We are in the midst of executing the sequence 3 sq . …
, where sq
is defined as : sq dup * ;
.
We have already loaded the literal value 0x0003
on the data stack, the program counter (PC
) is at 0x1A
and we are now starting to execute the word sq
. The situation looks like this:
PC ---> 0x1A: 0x8723 PUSH RB[RS], IP
0x1B: 0x7004 INC A
0x1C: 0x2134 LD IP, A
0x1D: 0x2043 LD A, *(IP)
0x1E: 0x7003 INC IP
0x1F: 0x2004 JMP *(A)
… …
A ---> 0x2E: 0x001A
0x2F: 0x0027
0x30: 0x8614
… …
0x32: 0x0007 LIT
0x33: 0x0003 0x0003
0x34: 0x002D SQ
IP ---> 0x35: 0x0020 DOT
… …
0x39: 0x0003
DB[SP] ---> 0x3A: 0xFFFF
0x3B: 0xFFFF
RB[RS] ---> 0x3C: 0x9999
0x3D: 0x9999
0x3E: 0x9999
The instruction pointer still points to the next instruction dot (.
), but before we can execute this, we need to execute that active word, which is sq
. So the first thing is do, to save the instruction pointer on the return stack with PUSH RB[RS], IP
which gets us here:
0x1A: 0x8723 PUSH RB[RS], IP
PC ---> 0x1B: 0x7004 INC A
0x1C: 0x2134 LD IP, A
0x1D: 0x2043 LD A, *(IP)
0x1E: 0x7003 INC IP
0x1F: 0x2004 JMP *(A)
… …
A ---> 0x2E: 0x001A
0x2F: 0x0027
0x30: 0x8614
… …
0x32: 0x0007 LIT
0x33: 0x0003 0x0003
0x34: 0x002E DUP
IP ---> 0x35: 0x0020 DOT
… …
0x39: 0x0003
DB[SP] ---> 0x3A: 0xFFFF
0x3B: 0xFFFF
0x3C: 0x0035
RB[RS] ---> 0x3D: 0x9999
0x3E: 0x9999
Now we can update the active word and make it the instruction pointer with first INC A
, then LD IP, A
.
0x1A: 0x8723 PUSH RB[RS], IP
0x1B: 0x7004 INC A
PC ---> 0x1C: 0x2134 LD IP, A
0x1D: 0x2043 LD A, *(IP)
0x1E: 0x7003 INC IP
0x1F: 0x2004 JMP *(A)
… …
0x27: 0x0028
0x28: 0xB461
… …
0x2E: 0x001A
A ---> 0x2F: 0x0027
0x30: 0x8614
… …
0x32: 0x0007 LIT
0x33: 0x0003 0x0003
0x34: 0x002E DUP
IP ---> 0x35: 0x0020 DOT
… …
0x39: 0x0003
DB[SP] ---> 0x3A: 0xFFFF
0x3B: 0xFFFF
0x3C: 0x0035
RB[RS] ---> 0x3D: 0x9999
0x3E: 0x9999
0x1A: 0x8723 PUSH RB[RS], IP
0x1B: 0x7004 INC A
0x1C: 0x2134 LD IP, A
PC ---> 0x1D: 0x2043 LD A, *(IP)
0x1E: 0x7003 INC IP
0x1F: 0x2004 JMP *(A)
… …
0x27: 0x0028
0x28: 0xB461
… …
0x2E: 0x001A
IP, A ---> 0x2F: 0x0027
0x30: 0x8614
… …
0x32: 0x0007 LIT
0x33: 0x0003 0x0003
0x34: 0x002E DUP
0x35: 0x0020 DOT
… …
0x39: 0x0003
DB[SP] ---> 0x3A: 0xFFFF
0x3B: 0xFFFF
0x3C: 0x0035
RB[RS] ---> 0x3D: 0x9999
0x3E: 0x9999
Then we execute NEXT
, which I will explain in a future post.