Explaining the code: executing the first word

After all the initializations, the program counter (PC) is at 0x0008 and the registers are pointing1 to memory as follows:

    PC ---> 0x08: 0x9613
            0x09: 0x7003
            0x0A: 0x2043
            0x0B: 0x7003
            0x0C: 0x2004
             …       …
     A ---> 0x32: 0x0007
    IP ---> 0x33: 0x0003
            0x34: 0x002E
            0x35: 0x0020
             …       …
DB[SP] ---> 0x39: 0xFFFF
            0x3A: 0xFFFF
            0x3B: 0xFFFF

Let’s add some mnemonics to each line. Note, the values from addresses 0x08 to 0x0C represent machine instructions, the values from 0x32 to 0x35 represent Forth words, and the values from 0x39 to 0x3B are there to show as of yet unused stack space.

    PC ---> 0x08: 0x9613    PUSH DB[SP], *(IP) 
            0x09: 0x7003    INC IP
            0x0A: 0x2043    LD A, *(IP)
            0x0B: 0x7003    INC IP
            0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x32: 0x0007    LIT
    IP ---> 0x33: 0x0003    0x0003
            0x34: 0x002E    DUP
            0x35: 0x0020    DOT
             …       …
DB[SP] ---> 0x39: 0xFFFF
            0x3A: 0xFFFF
            0x3B: 0xFFFF

Register A points to a memory cell that contains the address of the active word while register IP, the instruction pointer, points to the next instruction to be executed on Forth level. (In contrast to register PC, the program counter, which points to the next machine instruction to be executed.)

The purpose of the LIT word is to put the content of the following memory cell onto the data stack. This is exactly what the first instruction, PUSH DB[SP], *(IP), does. Afterwords the situation looks like this:

            0x08: 0x9613    PUSH DB[SP], *(IP) 
    PC ---> 0x09: 0x7003    INC IP
            0x0A: 0x2043    LD A, *(IP)
            0x0B: 0x7003    INC IP
            0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x32: 0x0007    LIT
    IP ---> 0x33: 0x0003    0x0003
            0x34: 0x002E    DUP
            0x35: 0x0020    DOT
             …       …
            0x39: 0x0003    
DB[SP] ---> 0x3A: 0xFFFF
            0x3B: 0xFFFF

Then INC IP moves the instruction pointer to the next Forth word to be exectued, which will be DUP.

            0x08: 0x9613    PUSH DB[SP], *(IP) 
            0x09: 0x7003    INC IP
    PC ---> 0x0A: 0x2043    LD A, *(IP)
            0x0B: 0x7003    INC IP
            0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x32: 0x0007    LIT
            0x33: 0x0003    0x0003
    IP ---> 0x34: 0x002E    DUP
            0x35: 0x0020    DOT
             …       …
            0x39: 0x0003    
DB[SP] ---> 0x3A: 0xFFFF
            0x3B: 0xFFFF

The inner interpreter (next)

The next three machine instructions implement a core piece of any Forth, the inner interpreter often just called next.

The first instruction, LD A, *(IP), updates the active word.

            0x08: 0x9613    PUSH DB[SP], *(IP) 
            0x09: 0x7003    INC IP
            0x0A: 0x2043    LD A, *(IP)
    PC ---> 0x0B: 0x7003    INC IP
            0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x2E: 0x0028    
            0x2F: 0xB461
            0x30: 0x8614    
             …       …
            0x32: 0x0007    LIT
            0x33: 0x0003    0x0003
    IP ---> 0x34: 0x002E    DUP
            0x35: 0x0020    DOT
             …       …
            0x39: 0x0003    
DB[SP] ---> 0x3A: 0xFFFF
            0x3B: 0xFFFF

The next instruction, INC IP, moves the instruction pointer one instruction ahead.

            0x08: 0x9613    PUSH DB[SP], *(IP) 
            0x09: 0x7003    INC IP
            0x0A: 0x2043    LD A, *(IP)
            0x0B: 0x7003    INC IP
    PC ---> 0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x2E: 0x0028    
            0x2F: 0xB461
            0x30: 0x8614    
             …       …
            0x32: 0x0007    LIT
            0x33: 0x0003    0x0003
            0x34: 0x002E    DUP
    IP ---> 0x35: 0x0020    DOT
             …       …
            0x39: 0x0003    
DB[SP] ---> 0x3A: 0xFFFF
            0x3B: 0xFFFF

Then JMP *(A) starts exeucting the next word.

            0x08: 0x9613    PUSH DB[SP], *(IP) 
            0x09: 0x7003    INC IP
            0x0A: 0x2043    LD A, *(IP)
            0x0B: 0x7003    INC IP
            0x0C: 0x2004    JMP *(A)
             …       …
     A ---> 0x2E: 0x0028    
    PC ---> 0x2F: 0xB461
            0x30: 0x8614    
             …       …
            0x32: 0x0007    LIT
            0x33: 0x0003    0x0003
            0x34: 0x002E    DUP
    IP ---> 0x35: 0x0020    DOT
             …       …
            0x39: 0x0003    
DB[SP] ---> 0x3A: 0xFFFF
            0x3B: 0xFFFF
  1. The registers are pointing to memory insofar as the following instructions will interpret their values as dping so.