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.