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.