1. 程式人生 > >Forth 內部解釋程式工作流程

Forth 內部解釋程式工作流程

    地址解釋程式是一些 CODE 詞,計算機型別不同,這些 CODE 詞也不同,故地址解釋程式又往往稱為 內部 解釋程式。相應地,又把 文字解釋程式稱為外部解釋程式。     IP  解釋指標       W  現行詞指標 IP 通常指著在一個冒號定義中的下一個要被執行的詞,而 W 則指著當前要執行的詞(W 的內容為當前要執行的詞的 cfa);

地址解釋程式:【       在文字解釋程式中通過 EXECUTE 呼叫內部解釋程式。EXECUTE 初始化地址解釋程式,它接過留在堆疊上的程式碼指標域地址 cfa ,然後間接轉移執行由此地址所指的子程式。
CODE   EXECUTE
   ( cfa -  )              執行編譯地址(即 cfa )在引數棧頂的定義                   
       W   POP             把在堆疊上的 cfa 送入到現行詞指標 W 中
       0   [W]   JMP      經由 W 進行一次間接轉移

END-CODE
內部解釋程式由定義 NEXT、NEST 及 UNNEST所構成。他們是由主機的組合語言或巨集組合語言編寫的。
NEXT   是一個 CODE 詞。執行 NEXT 就是執行由 IP 所指著的下一個詞。在執行 NEXT 中要做三件事:
1、((IP)) -> W   使 W 指著由 IP 當前內容所指著的詞;
2、(IP)+2 -> IP   使 IP 的內容遞增 2;
3、間接轉移執行由 W 所指著的詞;

解釋指標 IP (有時又稱為指令指標)的值由 NEXT 來設定和更新,所以每一個 CODE 詞的最後都無例外地一定要執行 NEXT 。執行 NEXT 就去執行由 IP 所指的下一個 cfa 所代表的子程式,同時更新 IP 的值指向再下一個地址,一直重複直到執行完畢一個定義中的所有編譯地址。
NEST    在執行 NEST 之前,IP 含有待返回的地址,而 W 含有要被呼叫的冒號定義的 cfa 。執行 NEST 要做四件事:
1、(IP) -> 返回棧頂(即儲存好的 IP 原來的內容);
2、(W)+2 -> W   使 W 指向要被呼叫的定義的 pfa (即引數域地址);
3、(W) -> IP   把所要執行的詞的地址送入 IP;
4、執行 NEXT。

NEST 在不同的 FORTH 系統中可能有不同的名字,如(NEST)、DO_COLON等。NEST 所代表的子程式是所有的冒號定義在一開始執行時都要首先執行的共同子程式。
UNNEST   是一個 CODE 詞。它把返回棧頂的首項移入到解釋指標中,結束一冒號定義的執行和返回到它的呼叫者。執行 UNNEST 時要做兩件事:
1、把返回堆疊頂第一個單元的內容送入 IP 中;
2、執行 NEXT ;

UNNEST 在不同的 FORTH 版本中也可能有不同的名字,比如 ;S 、EXIT 等。在詞典中的每一個冒號定義的最後一個成分一定是 UNNEST ,它來源於冒號源定義中最後的分號。




冒號定義的執行過程: eg: :  NOTHING   ; :  STEP1   DUP   OVER   NOTHIN  +  +  ;   // 用詞 ' 可以求出每個詞的 cfa 地址;
NOTHING
^nest ^unnest(14B)
66DE 66E0 ( lfa ) 66E8 66EA ( pfa )
STEP1 ^NEST ^DUP(3C4) ^OVER(3E4) ^NOTHING(66E8) ^+(582) ^+(582) ^UNNEST(14B)
66F2 66F6 66F8 66FA 66FC 66FE 6700 6702
當執行 DUP 時,(IP)=66FA指向OVER,DUP詞本身的最後一個成分是NEXT,於是當執行DUP的NEXT時發生:
1、((IP)) -> W ,也即IP的內容的內容進入到 W 中,於是 (W)=3E4,它是詞 OVER 的 cfa;
2、(IP)+2 -> IP,於是 (IP)=66FC,指向詞NOTHING;
3、執行 W 所指的詞,即執行 OVER 。OVER 是一個 CODE 詞,它的 cfa 單元的內容就是它的 pfa ,於是就跳去執行其詞身內的機器指令。
執行 OVER 的最後一個成分又是 NEXT,當執行此 NEXT 時發生:
1、((IP)) -> W,於是 (W) = 66E8,它是 NOTHING 的 cfa;
2、(IP)+2 -> IP,於是 (IP) = 66FE,它指著第一個 +;
3、執行 W 所指的詞 NOTHING
NOTHING 是以冒號定義,所以它的 cfa 單元的內容是 NEST 的地址,於是就跳去執行 NEST,執行 NEST 時發生:
1、(IP) -> 返回堆疊棧頂,返回地址 66FE 就被儲存在返回棧中。
2、(W)+2 -> W,(W)=66EA,它是 NOTHING 的 pfa。
3、(W) -> IP,(IP)=66EA,指著 NOTHING 內的 UNNEST。
4、執行 NEXT

1)、((IP)) -> W,(W)=14B,它是 UNNEST 的地址。
2)、(IP)+2 -> IP,(IP)=66EC,這個地址是分號後的一個地址,沒有任何意義,後面執行UNNEST會被修改,直接丟棄
3)、執行W所指的詞,也即執行UNNEST
執行 UNNEST 時發生:
1、返回棧頂的內容 -> IP,於是(IP)=66FE,指著 STEP1 內的第一個 +;    //每執行一次UNNEST,程式執行巢狀就減少一層,返回到原來的呼叫層中
2、執行 NEXT
1)、((IP)) -> W,(W) = 582
2)、(IP)+2 -> IP,(IP) = 6700,指著 STEP1 中的第二個 +;
2)、執行由W所指的詞,也即此時 STEP1 中的第一個 + 被執行。                 //由於 + 是CODE詞,它不會進入更深一層的巢狀。
……等執行完STEP1的UNNEST之後就返回到STEP1的呼叫者,也就是返回到外部解釋程式INTERPRET,由於執行完STEP1後輸入流耗盡,於是跳轉到FORTH迴圈中的外迴圈 QUIT 。在顯示屏上打印出“ok”後,FORTH 又等待使用者從鍵盤上輸入下一行命令。