第貳篇 基礎篇(第一課、第二課)

第一課FORTH 緒論

FORTH 概說

FORTH 的每件事物都是一個字(詞)。 FORTH 的每一個字必須以空格(space)隔開。  FORTH 的每一個字儲存在一字典裡。  FORTH 的每一個字不是可直譯的就是可編譯(COMPILER)的。  FORTH 的每一個字在直譯的模式中才可執行。  FORTH 的每一個字在編譯的模式僅是儲存在字典裡。  將 FORTH 詞串連在一起,以形成 FORTH 片語。

如果你鍵入一個 FORTH 詞,並且按下 [Enter] 鍵,它就會執行。(直譯模式)

如果你鍵入一個數字 (例如:6) ,並且按下 [Enter] 鍵,這數字便以一個16-bit 含正負號的整數,被儲存在堆疊(stack)上。

FORTH 廣泛地使用堆疊(stack)來傳遞一個一個的參數,這意思是說FORTH 對變數的需要性已大幅度地減低了。

在FORTH 中,你可以定義新的文字(由那些已被定義過的 FORTH 詞所組成),而將之納入 FORTH 字典中的一部分,且像其他任何的 FORTH 詞一樣,可以被使用。

金城 註疏:

一、"FORTH" 在國外電腦界曾被人們如下定義:

二、在大陸 FORTH 被翻譯成"多思",已推廣有八年之久了,主要是航天部在使用,近年來,中共也舉辦了全中國的 FORTH 檢定考試。

FORTH 算術

FORTH 運用堆疊(stack)來執行算術的運算,使用的是反波蘭式(POSTFIX)這套符號。

包括 F-PC 在內大部分 FORTH 均將 16-bit 的數值儲存於堆疊(stack)中,像 Macforth 這類 32-bit 的 FORTH ,則儲存 32-bit 的數值存在堆疊(stack)中。因此,堆疊(stack)中的數值會在十六位元的 FORTH 中佔二個位元組;在三十二位元的 FORTH 中佔四個位元組。

當你鍵入一個數字,它便被安置在堆疊(stack) 中,你可以在任何基底(base)上鍵入數字,稍後我們將會看到如何改變這基底(base)。

開機設定的基底(base)是十進位(DECIMAL)的;因此,若你鍵入 "35" ,十六進位數值的 23h (字尾 h 表示一個十六進位數值) 會以下列形式被儲存在堆疊(stack)中:

       |------------|       |------------------------|         | 0  0  2  3 |       | 0  0  0  0  0  0  2  3 |         |------------|       |------------------------|         16位元堆疊值               32位元堆疊值

如果你鍵入二個數字,中間隔一空格,它們便會分別被儲存在堆疊(stack)中,例如:如果你鍵入 127 256

這二個十六進位數值 7Fh 和 100h 將會以下列形式儲存在堆疊(stack)中:

         |----------------|           |  0   1   0  0  |←堆疊(stack)頂端           |----------------|           |  0   0   7  F  |           |----------------|  

鍵入 .S 會顯示堆疊(stack)出的內容,但並不會破壞堆疊(stack)。(檢查堆疊上的現況)

127 256 .S 127 256 OK

" OK " 這個字是 FORTH 的提示字。

數值被儲存在堆疊(stack)中,如同帶正負的二階補數。

因此,對16位元的 FORTH 而言,存在堆疊(stack)中的數值可以在—32,768 至 +32,767之間變化。

對32位元的 FORTH 而言,儲存在堆疊(stack)中的數值可以在—2,147,483,648 至 +2,147,483,647 之間變化。

金城 註疏:

其實在電腦的二進位儲存模式中,由16個 1 所代表的意義為何,要看人來決定,如果是帶正負號(Signed)的整數,則代表 -1。如果是當無正負號(Unsigned)的整數,則代表 65535。你可以做一行小的測試,輸入 -1 DUP . U. 按看看結果是不是 -1 和 65535 。就似錄音機的轉數表一樣,999 可看成由 000 倒轉一圈的結果。相同的也可以看成由 000 正轉 999 圈的結果一樣。結論是電腦整數本無正負之分,是人類的定義有正負罷了。(風幡不動,賢者心自動)

FORTH 算術運算指令

FORTH 字 "‧" (點 唸 DOT)會將在堆疊(stack)頂端的數值印出(1 / 1 in/out)

7 9 .. 會印出 9 7

跳行回返的鍵值通常會被 FORTH 所忽略,並視之為一個空白處。這可使得你的程式較易閱讀。藉著以" 垂直 "的風格來寫你的程式,你可以將" 堆疊圖 " 在你程式的右邊指出,只需緊跟著一個倒斜線 " \ " 。

在一行中任何緊跟著一個倒斜線的符號皆被視為是一個註釋,而被忽略。

例如:要舉出上述例子中每一頁中堆疊(stack)裡的符號時,我們可以這樣寫

                               堆疊圖    (堆疊的最上端)                   7               \  7                   9               \  7  9                   .              \  7                   .              \

注意 " ." (點)指令用掉上了堆疊(stack)上的數值。

FORTH 的字 + (加號)會將堆疊(stack)頂端的二個數值相加,並且將結果留在堆疊(stack)中。(2 / 1 in/out)

7 9 + .會印出 16

               7              \  7                 9              \  7  9                 +              \  16                 .             \

FORTH 字 " - " (減號)將堆疊(stack)頂端的第二個數值減去堆疊(stack)上端的第一個數值,並且將差留堆疊(stack)中。(2 / 1 in/out)

8 5 - . 會印出 3

                 8               \  8                   5               \  8  5                   -               \  3                   .              \

FORTH 的字 " * " (乘號)(星號)會將堆疊(stack)頂端的二個數值相乘,並且將乘積留在堆疊(stack)上。 (2 / 1 in/out)

FORTH 的字 " / "(除號)會將堆疊(stack)中頂端的數值去除第二個數值,並且將整數的商留在堆疊(stack)頂端。(2 / 1 in/out)

               8  3  / .會印出 2                   8                  \  8                 3                  \  8  3                 /                  \  2                 .                 \

堆疊(stack)的操作的指令

FORTH 不用區域變數,而在堆疊(stack)上自己調整所需用的數值

  FORTH 不用區域變數,而在堆疊(stack)上自己調整所需用的數值     堆疊圖 (之前--之後)     之前 = 堆疊(stack)上在詞執行之前所需的參數(PARAMETER)   之後 = 堆疊(stack)上在詞執行之後留下來的返回值(RETURN VALUE)     DUP 複製堆疊(stack)中頂端的元素。(1 / 2  in/out)         5  DUP ..會印出  5  5                   5                  \  5                 DUP                \  5  5                 .                 \  5                 .                 \     SWAP ( N1 N2 -- N2 N1 ) 交替互換堆疊(stack)頂端的二個元素。   (2 / 2  in/out)          3  7 SWAP ..會印出 3  7                   3                  \  3                 7                  \  3  7                 SWAP               \  7  3                 .                 \  7                 .                 \     DROP ( N-- ) 拋除堆疊(stack)頂端的元素。(1 / 0  in/out)          6  2 DROP . 會印出 6                   6                  \  6                 2                  \  6  2                 DROP               \  6                 .                 \     OVER ( N1 N2 -- N1 N2 N1 ) 複製堆疊(stack)中第二個元素。                              (2 / 3 in/out)         6  1 OVER  . . .會印出 6  1  6                   6                  \  6                 1                  \  6  1                 OVER               \  6  1  6                 .                 \  6  1                 .                 \  6                 .                 \     TUCK ( N1 N2 -- N2 N1 N2 ) 複製堆疊(stack)端頂元素插在第二個元素之        下。這就是 SWAP OVER 或 DUP -ROT 之最佳化。(2 / 3  in/out)              6  1  TUCK  . . .會印出 1  6  1                   6                  \  6                 1                  \  6  1                 TUCK               \  1  6  1                 .                 \  1  6                 .                 \  1                 .                 \     ROT ( N1 N2 N3 -- N2 N3 N1 ) 迴轉堆疊(stack)上的第三個元素,使第三       個元素變成第一個元素  (3 / 3  in/out)         3  5  7  ROT . . . 會印出 3  7  5                   3                  \  3                 5                  \  3  5                 7                  \  3  5  7                 ROT                \  5  7  3                 .                 \  5  7                 .                 \  5                 .                 \     —ROT ( N1 N2 N3 -- N3 N1 N2 ) 倒轉堆疊(stack)上的第一個元素,使第         一個元素反轉至第三個位置。此為ROT ROT 的最佳化。         (3 / 3  in/out)           3  5  7 —ROT . . .會印出 5  3  7                   3                  \  3                 5                  \  3  5                 7                  \  3  5  7                 -ROT               \  7  3  5                 .                 \  7 3                 .                 \  7                 .                 \     NIP   ( n1 n2 -- n2 )         從堆疊(stack)中移走第二個元素,這相當於 SWAP DROP         (2 / 1  in/out)            6  2  NIP . 會印出  2                   6                  \  6                 2                  \  6  2                 NIP                \  2                 .                 \     2DUP  ( N1 N2 -- N1 N2 N1 N2 )         複製頂端二個元素在堆疊(stack)上 ( 通常用來複製一對16位元或一         個32位元的數)(2DUP 為 OVER OVER 的最佳化) (2 / 4  in/out)           2  4  2DUP .S 會印出  2  4  2  4     2SWAP ( N1 N2 N3 N4 --N3 N4 N1 N2 )         將堆疊(stack) 頂端第一、二個元素與第三、第四個元素互換。         (為>R -ROT R> -ROT 之最佳化) (4 / 4  in/out)           2  4  6  8  2SWAP .S 會印出  6  8  2  4     2DROP ( N1 N2 -- )        將頂端二個元素自堆疊(stack)中移走  (2 / 0  in/out)          2  4  6  8  2DROP .S 會印出  2  4     PICK  ( N1 -- N2 )        從堆疊(stack)頂端複製在N1位置的值(不算N1)堆疊(stack),頂端相當        於N1等於0。 (N / N  in/out)          0 PICK  與 DUP  相同        1 PICK  與 OVER 相同          2  4  6  8  2  PICK .S 會印出  2  4  6  8  4     ROLL  ( N -- )        將在N位置(不算N)的值旋轉至堆疊(stack)頂端。(N / N-1  in/out)          1 ROLL  與 SWAP 相同        2 ROLL  與 ROT  相同          2  4  6  8  3  ROLL  .S  會印出  4  6  8  2

金城 註疏:

一、PICK 與 ROLL 最好少用,因效率不佳且難以閱讀了解,且一個稍          具功力的程式設師,其堆疊一般皆控制在四到六層之內,所以根本          用不到 PICK 與 ROLL 兩詞。        二、           |---------|   <---堆疊(stack)頂端           |   11    | 0           |---------|           |   14    | 1    在 ROLL 處的係數 1 即為第二個值 14           |---------|           |   28    | 2           |---------|        三、堆疊(stack)運算指令基本型態有四類:        (一) DUP、OVER 皆用來複製產生足夠的運算元。        (二) SWAP、ROT 皆用來調整運算元到適當的位置,以便使處理正確             無誤。        (三) DROP 用來去除堆疊上多餘的贅物,以維持堆疊的平衡。        (四) >R、R@、R> 用來取深度超過三層以上的運算元。        (五) 所有其它的堆疊操作指令,均可以此四類來區分和使用之。

其他的一些 FORTH 常用字

 MOD   ( N1 N2 -- N3 )         將 N1 除以 N2 ,留下餘數 N3 在堆疊(stack)上。(2 / 1  in/out)            8  3 MOD . 會印出   2     /MOD  ( N1 N2 -- N3 N4 )         將 N1 除以 N2,留下商數 N4 在堆疊(stack)頂端,餘數 N3 在堆疊         (stack)的第二個位置。(2 / 2  in/out)            10  3 /MOD .S 會印出 1  3     MIN   ( N1 N2 -- N3 )         留下 N1 和 N2 中較小的數在堆疊(stack) 上。(2 / 1  in/out)            8  3 MIN . 會印出 3     MAX   ( N1 N2 -- N3 )          留下 N1 和 N2 中較大的值在堆疊(stack) 上。(2 / 1  in/out)            8  3 MAX . 會印出 8     NEGATE ( N1 -- N2 )         改變 N1 的正負號。 (1 / 1  in/out)            8 NEGATE . 會印出 -8     ABS   ( N1 -- N2 )         留下 N1 的絕對值在堆疊(stack)上。 (1 / 1  in/out)            -8 ABS . 會印出  8     2*    ( N1 -- N2 )         以執行一個算術左移運算會將 N1 乘以 2  (1 / 1  in/out)            8  2* . 會印出  16           這相當於 8  2  *  但是快的多也精簡的多。     2/    ( N1 -- N2 )         以執行一個算術右移運算,會將 N1 除以 2。(1 / 1  in/out)            8  2/ . 會印出  4           這相當於 8  2  / 但是快的多     U2/   ( N1 -- N2 )          執行一個 16 位元邏輯右移運算。(1 / 1  in/out)              40000 U2/ . 會印出  20000         但 40000 2/ . 會印出  -12768     8*    ( N1 -- N2 )          執行一個 3 次的算術左移運算,會將 N1 乘以 8。(1 / 1  in/out)               7  8* . 會印出 56            這相當於 7  8 * 但較快些     1+    ( N1 -- N2 )         將堆疊(stack)頂端元素加 1 。(比 1 + 快些)(1 / 1  in/out)     1-     ( N1 -- N2 )         將堆疊(stack)頂端元素減 1。(1 / 1  in/out)     2+    ( N1 -- N2 )         將堆疊(stack)頂端元素加 2。 (1 / 1  in/out)     2-    ( N1 -- N2 )         將堆疊(stack)頂端元素減 2。 (1 / 1  in/out)     U/16  ( U -- U/16 )         U代表一個不帶正負號的 16-bit 整數,以執行一個 4-bit 邏輯右         移運算,會將未帶正負號的整數 U 除以 16。 (1 / 1  in/out)

金城 註疏:

in/out 用來提供使用者參考,每一指令(word)在堆疊上(之前/之後)的變化,要精通 FORTH ,第一要務在"維持精準的堆疊平衡"留下垃圾會使堆疊爆掉(當機)。不足時,會使所有的運算結果亂掉。

冒號定義(高階程序)

可以藉著使用下列形式的 FORTH 的詞 " : "(冒號)來組成其他的 FORTH 的   用詞。   定義你自己的 FORTH 的詞:            : (程序名稱) --- --- --- ---  ;     上列中,冒號 " : " 開始定義,是你的 FORTH 詞的名字。    " --- --- --- --- " 是構成你所定義的 FORTH 的其他詞。     分號 " ; " END 結束整個定義。     舉例:如果你不喜歡將堆疊(stack)頂端之值印出的這個點"‧"指令,你可以   將它重新定義為 " == "(我們將使用雙符號,因為單等號 " = " 已經是一個    FORTH 詞了)       備註:       小括號" ( ) "是一種 FORTH 文字,將在小括號中的文數字當作一種對       堆疊(stack)變化的註解。因此 " ( " 的後面必須空一格。      COMMENT:--- COMMENT;  將COMMENT:開始到COMMENT;之間都括弧起來。     當你鍵入 FLOAD LESSON01 所有在 COMMENT:和 COMMENT;之間的文字都會   被當成一個註解的被忽略。不過,下列的冒號定義會藉著被載入字典中   而被編譯。你可以自將它們一一鍵入,或者僅鍵入 FLOAD LESSON01

: == ( n-- )    \ 印出堆疊頂(stack)端的值    .  ;

鍵入這一個冒號定義,然後試試看。輸入

5 7 + ==

: SQUARED ( N -- N ** 2 )   \  計算 N 的平方    DUP *  ;

試著輸入         5 SQUARED  ==         3 SQUARED  ==         7 SQUARED  ==

: CUBED  ( N --N**3 )    \  計算 N 的立方   DUP      \  N N   SQUARED  \  N N ** 2   *     \  N ** 3 ;

試著輸入         3  CUBED  ==         5  CUBED  ==        10  CUBED  ==

金城 註疏:

耐心而詳實的追蹤每個指令(word)執行前後的堆疊變化圖,為程式除錯與了解 FORTH 程式的唯一大道。

下列為兩個常用的 FORTH 用字:     CR     ( -- ) ( " 跳行迴轉 " )        在螢幕上產生一個迴轉和跳行的動作     ."   ( -- )  ( " DOT-QUOTE " )         印出一個被夾在 ." ------- " 中的字串。

定義下列的字

: BAR ( -- )          \ 印出一個星狀橫條   CR ." ***** "  ; 鍵入     BAR   : POST ( -- )          \ 印出一個星狀直條   CR ." * "   CR ." * "  ; 鍵入     POST   : C    ( -- )         \ 印出一個字母 C   BAR   POST   POST   BAR  ; 鍵入     C : E    ( -- ©         \ 印出一個 E 字母   BAR POST   BAR POST   BAR  ; 鍵入     E

提示:

FORTH 的新詞是由從前所定義過的詞來組成,這是 FORTH 的工作方式。新的更有威力的詞連續的被定義出來。當你完成工作時,整個主程式是最後一個定義的詞。你所定義過的詞,是存在 FORTH 的字典中(程式館)和原先定義過的詞在一起,這些新定義的字就變成 FORTH 語言的一部份。使用起來就像是原先定義的字一樣。(其他語言均有保留字,FORTH 沒有)FORTH 的解釋機構不會將原來的詞與你自己所定義的詞做差別性的對待和執行。這也就是說,每一個 FORTH 應用程式事實上是在設計一個解決特定問題的應用語言給使用者使用。

金城 註疏:

一、在寫作 FORTH 程式的過程中,你是用 FORTH 的語言(字),對電    腦說話,這些話(字)組成一個個的句子(冒號定義)。重點在於,    這些句子你懂、電腦也懂;如果你自己不懂、電腦更不會懂。 二、FORTH 的精神在於(KISS : Keep it Simple and Stupid,保持問    題的單純性)。不要將其複雜化。 三、FORTH 有自己的 CPU 硬體結構。所以,不怕這種一層叫一層的副    程式呼叫。 四、一個程式(冒號定義)不要太長,否則不易專心思考問題容易出錯。

練習 1.1

藉著鍵入左上方( t l )及右下方( b r )的坐標可定義一長方形,讓 X坐標   從左往右增加, Y 坐標從上往下增加。定義三個 FORTH 詞,面積、周圍、   中心,就可計算出面積、周邊、和長方形的中心,只須按下列方法將上、左   、下、右四個值輸入堆疊(stack)中。     AREA    ( t l b r --- 面積 )   CIRCUM  ( t l b r --- 周長 )   CENTER  ( t l b r --- 中心位置 )     使用下列二組上、左、下、右的數值,來測試你的三個詞:     上   31    10   左   16    27   下   94   215   右   69   230

使用 F-PC

使用 SED 來編輯檔案

螢幕式編輯器是用來編寫你的程式和儲存它們進入磁碟中。     例如:寫練習 1.1 的作業應先進入 F-PC 看到 OK      再鍵入  SED HW1     這將會開一個新當名叫 HW1.SEQ 所有的 FORTH 程式用 " SEQ " 作副檔名,   它會自動的加在你的檔名後面。     程式的風格在第一行使用一個反斜線 " \ " 跟隨其後的是程式的名稱。   這第一行的內容會在你用 FPRINT HW1 時印在每一頁的頁頭上。在第二行鍵   入一個反斜線,再鍵入 ALT--O P ,會將當時的日期和時間附加在檔案上。     現在練習鍵入下列的程式

: SIDES     ( T  L  B  R -- R-L  B-T )   ROT           \ T  B  R  L   -             \ T  B  T-L   -ROT          \ T-L  T  B   SWAP -        \ R-L  B-T ;   : AREA      ( T  L  B  R -- AREA )   SIDES *  ;  : CIRCUM    ( T  L  B  R -- CIRCUM)   SIDES + 2*  ;  : CENTER    ( T  L  B  R -- XC  YC )   ROT           \ T  B  R  L   +             \ T  B  R+L   2/            \ T  B  XC   -ROT          \ XC  T  B   + 2/          \ XC  YC ;  

注意" SIDES "是一個中間產物被定義來留下(左 — 右)及(底 — 頂)的值在堆疊(stack)上," SIDES "這個字是在面積及周長的定義中被使用。

F-PC 對大小寫沒有編譯上的差異,這意思是你可以交替地使用大寫或小寫的字母,我們一般會依循傳統,將我們自己的新字定義用小寫來定義,而將我們在定義時所使用到的 F-PC 的原定義用詞用大寫來輸入,這使得一個定義較容易被辨識出那些是 F-PC 的字,那些是我們自己先前所定義的新字。

也需注意到在定義 "SIDE" 和 "CENTER" 時,我們將堆疊圖當做註解顯示在每一行的右邊;當大量的堆疊操作在連續進行的時候,你就會發現這非常有用。

SED 編輯器的全部編輯能力,在第四章 F-PC 的使用者手冊中會有描述。在 F-PC 程式的磁片中,你可以藉鍵入一些字而將第四章印出來。

鍵入 TYPE CHARPTER4.TXT

一旦你完成進入這程式的動作,你可以藉著按" ESC ",然後按 [Enter] 來離開 SED ;此時你可以編輯另一個檔案,只需鍵入檔名即可,若此時你不想編輯另一個檔案,按" ESC "和 [ENTER]。你現在有 " OK " 提示你在F-PC 中,這時你大致上可以載入並執行你的程式。不過 SED 編輯器還沒有釋放在編輯你的程式時所佔用的記憶體,這時你要載入較大程式,就會有麻煩。所以,我將程序修改為鍵入 BYE ,而暫時離開 F-PC ,然後鍵入 F ,重新進入F-PC 。這時你可以載入任何大小的檔案,而不會發生問題。

載入並執行你的程式

要載入在 HW1.SEQ 檔中的程式,你只需鍵入 fload hw1 [ENTER] 如果你沒有做 HW1.SEQ 這個檔,你也可以只藉載入本課來完成同樣的事。   鍵入 fload lesson02 [ENTER]。   這是因為除了 "SIDES"、"AREA"、"CIRCUM"、"CEHTER" 這幾個字的定義外,其他的都是註解。

金城 註疏:

一、由 COMMENT: 到COMMENT ;的中間行內容均是註解說明。 二、載入任何一個檔案的過程都會使得所有的冒號定義被加進字典中    ,這也就像是你在 F-PC 的直譯模式中,鍵入所有的冒號定義一    般。除此以外所有的冒號定義現皆被存在磁片中,你可以在任何    時候進入且編輯它們。

如果你要藉使用練習 1.1 中所提供的值來測試程式,你將會獲得下列的結果:

     31  16  94  69  area   3339       31  16  94  69  circum  232       31  16  94  69  center   62 42         10  27  215  230  area   -23921       10  27  215  230  circum  816       10  27  215  230  center   112 128

面積的第二個值等於 —23921 ,這沒有意義;真正的情況是面積大於 32767,所以16位元的符號值便跑到負的區域去了,因為 bit 15 的符號 bit 被設為 1。我們可以使用 FORTH 的字 U (U-點),而不是 .(點)來印出面積真正的值 。 U. 這個字將在堆疊(stack)的頂端不帶符號的 16 位元整數值印出,這會產生下列的結果。

10 27 215 230 area U. 41615

除去你程式中的蟲 (除錯)

F-PC有許多有用的字可以幫助你除去你程式中的錯誤。 SEE 這個字會讓你反編譯(DECOMPILE)分解一個字。例如在 floding HW1 (或第二課)這檔案後,鍵入

see area see sides see circum see center

注意每一個冒號定義都出現了。這是藉著在字典中找出每一個字,然後找出每一個字定義的名字。

VIEW 這個字允許你找到已定義好的檔案,並顯示這檔案正確的定義內容。鍵入

VIEW sides

你可以使用 VIEW 這個字來找出任何一個 F-PC 文字的定義(原始程式)。

F-PC 文字中 DEBUG 是一個強有力的除錯工具,允許你一邊看堆疊(stack)上儲存了什麼東西,一邊一步一步地執行一個字。

在 FLOAD LESSON02 後,鍵入 debug area

AREA 這個字在下一次被執行時,會在定義好的每一個字上面暫停並顯示堆疊(stack)上的內容。按任意鍵(Q、C、N、U、X、F 除外)就可以繼續。

例如,如果你鍵入 10 27 215 230 area AREA 的定義就會顯示在螢幕的上端,而當你按三次空間棒時,下列數字便會顯現在螢幕的下端。

  10 27 215 230 AREA [4]    10    27    215   230    12648  0 :    SIDES     ?>  [2]    203   205    12648  2      *         ?>  [1]  41615    12648  4      UNNEST    ?>  OK

按空間棒,以單步執行每個名字的定義,同時堆疊(stack)的深度也會顯示在括弧 "[ ]" 中,而且堆疊(stack)最上面的四個項目值也會被顯示。要注意到在這個例子中,當 203 和 205 這二個數值被相乘以產生 41615 時,為何顯示的值是 —23921 其理由在我們測試這程式時便會變得清楚,事實上,在經過上述 AREA 的定義的每一步驟之後,41615 這個值會被留在堆疊(stack)中。如果你接著鍵入‧(點),—23921 便會顯示出來,這當然就是 16 位元整數值 41615 的符號值。

鍵入 UNBUG 以鍵入取消除錯,好使得將來執行 AREA 時不會被除掉、當一步一步執行時,按下 Q ,會停止除錯,並執行 UNBUG ;鍵入 C 會繼續執行直到定義結束,或一直到按下 [ENTER] 鍵才會結束;鍵入 F ,會暫時的回到FORTH 系統再鍵入 [ENTER] 會回到除錯程序中。

鍵入 X 會開/關,原始程式的部份。按下 N ,會進入將被執行的字;按下 U,會回復原來的字。例如,鍵入 DEBUG AREA ,然後鍵入

10 27 215 230 AREA

然後按 N ,這會進入 SIDES 的定義,一步一步地經過這定義並且看它如何轉回至 AREA 的定義。

練習2.1

建一個名叫 HW2.SEQ 的檔,並且在這檔中寫下下列冒號定義:     : stacktest  ( a b ---?)                 DUP *                 SWAP DUP                 * + ;     加一堆疊畫面到這定義中每一行的右邊。FLOAD 此檔,當你鍵入        4  5 stacktest     使用 DEBUG 在字中的每一步。     a 和 b 會留下什麼數值在堆疊(stack)中。