Forth 语言概要
Forth 語言概要
原作者 Peter Knaggs
原文標題《 Forth: An underview 》
本文的目的是給出 Forth 編程系統的一個整體輪廓,包括語言的歷史、突出的特點和使用方法,討論了最常用的實現方法,但更重要的是討論了 Forth 編程的方法和哲學思想。
1.Forth 的來歷
按照 Forth 語言的發明人 Charles Moore ( Chuck )的說法:
我第一次把各種想法組合成一個整體之后,它在“第三代計算機” IBM1130 上工作得如此有效,以致于我認為它是“第四代語言”,理所當然地應該被稱為 FOURTH 。不過,當時的 IBM 計算機只允許 5 個字符的標識符。所以 FOURTH 變成了 Forth ,這是一個非常好的的文字游戲。
2. 歷史
Forth 語言是 60 年代發明的,當時 Moore 在斯坦福線性加速器中心做計算機程序員工作,后來變成了一個自由工程師。當時的工程技術人員為了控制編譯程序必須學習大量的方法,包括連接器、匯編器、偽指令以及高級語言,開發這個新工具的目標就是為了克服這些問題。
第一個稱為 Forth 的程序大約是在 1970 年編寫的。第一個完整的實現是 1971 年在一臺 PDP-11 上完成的,用于亞利桑那州國家射電天文臺的 11 米射電望遠鏡。這個系統的責任是定向和跟蹤望遠鏡,收集數據并記錄到磁帶上,支持一個交互式的圖形終端,供天文學家分析以前記錄的數據。系統的多任務特點允許這些功能同時執行,沒有時間上和其它方面的沖突。
這個系統取得了巨大的成功,世界各地的天文學家開始請求提供軟件拷貝。Forth的使用范圍迅速也擴大,國際天文學會于 1976 年接受了 Forth 作為標準語言。
這個應用的成功還促使 Moore 和 Elizabeth Rather ( ("Bess") 于 1973 年成立了 Forth, Inc. 公司,目標是開發這種語言的商業應用。 Forth, Inc. 在小型機上開發了多用戶的 Forth 版本,可以用于從數據庫到圖像處理等科學和應用領域。和第一個應用一樣,它們需要不同工具的組合。
1977 年,公司為剛剛出現的 8 位處理器開發了一個稱為“microForth”的版本,對小型機上的“miniForth”做了擴展和補充。1979 年,稱為“PolyForth”的產品替代了這些系統。從此以后,它就成了市場上銷售量最大的 Forth 系統。
“microForth”系統在美國、歐洲和日本的嵌入式微處理器應用中取得了成功,由此產生了歐洲 Forth 用戶團體 (EFUG) ;1978年,位于北加利佛尼亞的計算機愛好者成立了 Forth 興趣組織 (FIG).
FIG 從天文臺得到 Forth 系統,再用這個系統開發出一個簡單的模型,然后在幾個不同的系統上實現(那當然是得到了 Forth,Inc 的許可之后)并以非常低的價格銷售。這個模型后來變成了著名的 FIG-Forth 模型。所有這些使得對 Forth 的興趣迅速增大。 FIG 目前在 15 個國家中有 60 個分支。
3. 特點
Forth 是一個交互式的程序設計環境,最初是為程序員在小型和微型計算機上開發應用程序而設計的。最早用于科學和工業應用,比如儀器、機器人、過程控制、圖形和圖像處理、人工智能和商業應用。 Forth 的主要優點是軟件開發快速、交互式、計算機硬件的高效使用等。
Forth 常常被作為一種語言,這當然也是它最常見的方面,然而 Forth 所提供的功能比傳統的程序設計語言要多。傳統的高級語言工具包含有許多分離的工具(編譯器、編輯器、匯編器等等), Forth 把它們融為一體。與傳統的高級語言相比,它是經過深思熟慮的,完全沒有傳統高級語言那么復雜的語法特性。
最早實現的 Forth 是一個獨立的系統,它包含獨立操作系統的一般功能,還包括有編輯器、編譯器、匯編器、調試器和其它工具。一個單一的、簡單的、一致的規則支配這些能力。今天,盡管還能在許多處理器上見到獨立的版本,但更多的版本是與 MSDOS 、 WINDOWS、UNIX 一類操作系統協同工作的。
Forth 并不起源于其它已有的程序設計語言,所以它的外觀和內部特點對于新用戶來說是特殊的。但是 Forth 的簡單性、高度模塊化和交互式特性可以彌補初學者的陌生感,使得 Forth 非常易于學習和使用。一個新的程序員通常需要花一些時間來掌握 Forth 巨大的命令集,通過一個月左右的全面使用,程序員就可以理解它的整個內部工作機理,所學到的東西要比傳統操作系統和編譯器多得多。
Forth 與傳統語言最大的不同是它的可擴展性。 Forth 的編程過程就是定義新的字,字實際上就是語言的新命令。字可以用一系列以前定義的字來定義,這個過程與教育孩子的過程相似:我們總是用孩子們以前理解的概念來教給孩子們新的概念,而這些字被稱為“高級定義”。同樣,新的字也可以用匯編代碼定義,因為在多數 Forth 實現中都包括宿主處理器的匯編器,而這些字被稱為 CODE 字。
可擴展性的結果是我們在開發一個應用的同時,也間接地開發了一個特殊的、針對這一類應用的“面向應用的語言”,它可以用于或者經過修改之后被用于相似的應用。
Forth 的可擴展性并不僅僅是為語言自身增加新的命令,所以不要把定義字與傳統高級語言定義函數、過程等同。可擴展性還能夠創建一個可以定義其它字的字,這種字被稱為“定義字”。在創建這樣一個定義字的時候,程序員能夠指定它所創建的字在編譯時間、運行時間或者這兩種狀態下的特殊行為。這個能力允許我們定義特殊的數據類型,并對其行為和結構實施完全的控制。又由于這種字的運行時間行為可以用高級語言或者匯編語言來定義,所以由定義字創建的字將具有與其它 Forth 字一樣的性能。系統也允許我們增加一個新的“編譯指示符”以實現特殊類型的循環或者其它的控制結構,比如 CASE 結構。
4. 編程
Forth 語言和英語非常相似,它的基本元素是已命名的數據項、過程,以及創建用戶化數據項的定義字的能力。過程和定義字可以使用以前定義的字或者匯編代碼來定義,它們與其它語言的子程序相似,也與其它語言的命令等效。 Forth 允許我們在鍵盤上打入一個函數的名字,這個函數將被立即執行。然而,如果我們把功能的名字放到定義中,將編譯成對于這個函數的引用。
高級字是由其它字的集合來定義的,我們可以把這個過程想象成是其它語言的宏或者詞典中的英語定義。新的字被加入到它們可以使用的存儲器中,其定義被加入到字典中。在一個 Forth 字的命名規則中,只有很少的幾個字符不能作為命名字符使用。許多程序組織使用更好的命名約定,通過可打印的字符以增加程序的可讀性。
當遇到一個字的時候, Forth 就通過字典搜索希望找到這個字的定義,如果找到,這個字定義的功能或者被立即執行,或者作為引用而被編譯到新的定義中。然而,如果在字典中沒有找到這個字,系統就試著把它轉換成一個數。如果轉換成功,就把它放在堆棧上。如果不能轉換成數字,就顯示這個字并打印出一個錯誤的信息來報告這個字是系統所不知道的。
Forth 堅持“結構化程序設計”原理:
?? 字必須在引用之前被定義;
?? 邏輯流限制只有順序、條件和循環,有專門的字用于實現常用的程序控制結構;
?? 程序員使用許多小的、獨立的模塊(字)來實現最大的可測試性和可靠性;
這種方法有兩個明顯的優點
?? 新的字總是用以前定義和測試過的字來構造,所以調試更容易。模塊可以單獨執行以測試它的功能;
?? 固有的模塊性使 Forth 成為一個“設計性語言”,允許自頂向下的設計同時保持自底向上的測試。一個字可以在不同的程序中使用,但是它的功能只需要定義一次;
這些都保證了 Forth 軟件能夠快速和有效地被開發,同時,如果管理得當,也可以作為自身文檔的基礎。
Forth 的 5 個主要元素決定了它的特點:
?? 一個字典;
?? 兩個堆棧,一個是參數棧,另一個是用于嵌套的返回棧;
?? 鍵盤(輸入流)解釋器;
?? 一個匯編器;
?? 虛擬存儲;
用 Forth 開發的項目
以下是一些使用 Forth 開發的項目
Atari 的許多投幣游戲機都是用 Forth 開發的。他們相信開發高性能代碼的最快方法是使用 Forth ,加上使用匯編語言來重寫最內層的循環。
按照最近與著名的 Infocom 高級游戲開發者的談話,他們的游戲解釋器也是用 Forth 寫成的。
Unison World 為 CP/M 操作系統開發了許多游戲,全部都是用 FIG-Forth 編寫的。按他們技術總監 Marc de Groot 的說法,把一個基于 Z80 的游戲移植到 6502 或者 MC6809 上,典型的時間不多于 3 個月。
美國 Federal Express (聯邦快遞)公司的手持式行李分撿系統的程序是用 Forth 編寫的。項目經理 Gene Farrar 說,他可以按需要在幾個星期內升級新固件,相比而言,其它的小組維護 C 語言代碼則至少需要 6 個月的時間。
1990 年 11 月哥倫比亞航天飛機的 4 個載荷中有 3 個是用 Forth 編程的。按設計團隊之一Johns Hopkins University's Applied Physics Laboratory的 John Hayes 說法,他們選擇 Forth 來解決飛行中的硬件問題,靈活性是一個主要的因素。
SUN 公司把 Forth 用于它的工作站可編程 Boot ROM 中,以每天 500-1000 臺的速度發貨,是可編程 Forth 系統中數量最大的。 1994 年 IEEE 1275-1994 將 Forth 用于 BOOT (初始配置) 固件的標準,這也是 POWER PC 通用硬件平臺的基礎。
在電影《終結者 II :世界末日》中, Cyberdyne Systems T1000 系統的特技效果是基于 Morphing 軟件包 Forth 產生的。
5. 字典
Forth 程序存儲在字典中。字典占據了系統存儲器的很大部分,它由一個串線鏈接的可變長度的項目組成,每個項目定義了一個字。每個定義的內容根據字的類型(數據項、常數、操作序列等)而有所不同,字典是可擴展的。
字是由“定義字”加入字典的,最常用的定義字是:(冒號)。當冒號執行的時候,它為后面的字建立一個字典項,然后進入“編譯”模式。有許多不同的編譯方法,最常用的是“串線編碼”,這種方法把定義編譯成一系列以前定義字的地址引用。定義由;(分號)結束。下面就是一個定義:
: NETWORK ( -- ) OPEN LINK TRXT. ECHO CLOSE LINK ;
圖 1 編譯的字典項
當一個名字項被編譯到字典中的時候(稱為定義的首部),它包含一個指向字典中前一個首部的指針。新字的名字加入字典(這里就是 NETWORK ),接著一個指向名字為“( : )”子程序調用的指針編譯到字典中作為定義的第一部分,這個指針指向一段在解釋定義體時需要執行的代碼。當然,這里所說的不是唯一的編譯技術,但它的應用最為普遍,這種技術稱為間接串線編碼,因為定義中的第一個項目是一段代碼的引用,這段代碼知道如何解釋定義的其它部分。
定義的其它部分稱為這個定義的體。在編譯模式下,系統將依次尋找每個字的首部。每個首部地址依次放到定義體中,這樣就產生了一個地址列表。最后在到達;時,一個稱為“EXIT”的子程序地址被編譯進定義。 EXIT 子程序用來將控制返回到調用字,就像一個子程序返回一樣。
6. 堆棧
Forth 維護兩個下推式堆棧,下推式堆棧也稱為后進先出列表,它們提供了 Forth 字之間通信以及邏輯控制的有效機制。
盡管兩個堆棧的結構是相同的,但它們的用途卻大不相同。與用戶/程序員關系最為密切的是數據棧,它保存有調用字之間傳遞的參數,以替代傳統語言的參數列表,同時也是一個實現定義重用的有效內部機制。第二個堆棧是返回棧,用于保存嵌套定義的返回地址,偶爾也用于臨時保存其它的數據。
數據棧的使用導致了一種操作數位于操作符后面的“后綴”表示方法,這種后綴表示方法常常被稱為 RPN 或者“逆波蘭表示法”,用以紀念 Lukasiewicz 教授,上個世紀 20 年代時, Lukasiewicz 教授在華沙大學工作,為 Sentential Calculus 開發了這種方法。
作為一個例子,我們來看一下字 BLANK 。這個字希望堆棧上有一個地址和一個數,字 BLANK 將從指定地址開始填充指定數目的 ASCII 空格,于是:
PAD 25 BLANK
將向 Forth 系統的便箋區填入25個空格,這里地址是由字 PAD 放到堆棧上的。應用字通常按相似的方法定義,比如:
100 SAMPLES
將定義一個用于保存 100 個測量值的數據數組。算術操作也從堆棧上取值并將結果保存到堆棧上。例如, + 操作把棧頂的兩個數相加,并用它們的和替代棧頂。由于操作的結果仍然留在棧頂,所以連續的操作就可以組合在一起而不需要臨時存儲變量。例如,表達式
tempn + ((reading % interval) / interval) * (tempn1 - tempn)
變成:
reading interval % interval / tempn1 tempn - * tempn +
7. 解釋器
Forth 本質上是一個解釋系統,在這樣的系統中,程序的執行是由數據項而不是由機器代碼控制的。解釋系統通常很慢,但是 Forth 卻通過兩級解釋而保持了實時應用所需要的高速度。當然,我們這樣說是假設系統使用普通的串線編碼方法,如果使用編譯技術來產生本地代碼,就根本不會有任何速度上的損失了。
?? 第一個解釋器是文本解釋器,它掃描從終端(或者從海量存儲器)得到的字符串,并在字典中查找每一個字。如果找到了這個字,就通過第二級地址解釋器執行。
?? 第二級解釋器是“地址解釋器”。盡管不是所有的系統都用這種方法實現,但這種方法卻是最早的和最基本的方法,地址解釋器通過執行每個定義點的程序來處理地址(或者標記)串,這些定義點是由:(冒號)創建并編譯到定義中的。
7.1 文本解釋器
上電之后。 Forth 啟動一個稱為 QUIT 的無限循環。這就是 Forth 文本解釋器,也稱為鍵盤解釋器。
: QUIT ( -- ) BEGIN RESET QUERY INTERPRET AGAIN ;
RESET 清除堆棧, QUERY 等待用戶從鍵盤(或者從海量存儲設備)輸入一個命令, INTERPRET 尋找字典匹配,然后執行。 BEGIN 和 AGAIN 是程序控制字,用于構造無限循環。
QUIT 循環提供了語言的“交互式”特點,如果輸入命令,它就可以立即被執行,而執行的結果可以使用相同的文本解釋器來觀察。與其它的編輯 - 編譯 - 鏈接 - 測試程序開發過程相比,一個新的定義可以在極短的時間里被反復地測試和排錯。
7.2 地址解釋器
定義項首部的最后一個字段是指向功能執行的代碼指針,這個字段所在的地址被稱為“代碼域地址”,簡稱 CFA 。對于所有的 Forth 高級定義字(使用 : 冒號定義的字),這個地址就是地址解釋器的地址,它指向字 (:) 。
地址解釋器有一個寄存器 I ,其中包含被執行列表的下一個入口的地址。這個入口就是某個字的 CFA 地址,這個字被當前正在執行的高級定義字所調用。正是 CFA 決定了一個字的屬性(或者類型)。
在下面的例子中,字 A 調用字 B ,字 B 調用字 X 等等。 CFA 保存在中間寄存器 W 中。采用這種兩級間接尋址和字典列表結構的 Forth 編碼方式也被稱為“間接串線編碼”。
圖 2 間接串線編碼
地址解釋器讀入 I 并使用列表中的下一個地址裝入 W ,然后從 W 讀出并執行由它指示的代碼。 I 自動增量指向列表中的下一個入口,因為第一個入口是 CFA ,所以 I 現在指向了定義體。這對于查找表一類的數據結構非常有用,因為定義體就是表元素的存儲區。在高級定義的情況下,代碼域地址指向子程序 (:) ,它把當前的 I 保存到返回棧上,然后從 W 裝入 I 并重復這一過程。在高級定義的結尾,字 EXIT 被執行,恢復原來的 I 值,程序像以前一樣繼續執行。這三個動作“讀 I 指針,保存 I 指針,恢復 I 指針”是地址解釋器得以工作的基本機制。
地址解釋器有三個重要的特點:
?? 特別快。盡管實際的速度依賴于特定的實現,但專業化的實現是高度優化的,每個地址通常要求 1-2 個機器字。這相比純的匯編代碼只增加 0%-50% 的開銷。在許多基準程序測試中,好的 Forth 實現遠遠勝過諸如 BASIC 或者 LISP 一類的解釋語言,可以與其它的編譯高級語言相比;
?? 它使得 Forth 定義極其緊縮,每一個引用僅僅需要一個單元(可以把單元理解成機器字,但是“字”在 Forth 中是指一個定義項)。作為比較,我們可以考慮一下許多高級語言產生的子程序調用結構:一個 CALL 或者 JSR 指令,后隨地址,在這之前和之后,還有參數序列的訪問指令。
?? 使用返回棧保存地址的方法對于程序員是透明的,字也可以按需要嵌套許多層,這樣的高級定義字序列可以被自動處理而不需要特殊的代碼。
Forth 系統中的許多字都是用 : 定義并通過地址解釋器進行解釋的,而許多 Forth 系統本身也是用這種方法定義的。
8. 匯編器
大多數 Forth 系統都包含一個宏匯編器,為它們所在的 CPU 進行匯編語言編程。通過使用定義字 CODE ,程序員可以創建由實際的機器代碼組成的定義。 CODE 定義可以用來完成 I/O 、算術原語和其它依賴機器(時間緊迫)的處理功能。當程序員使用 CODE 時,他就和使用其它匯編器一樣對 CPU 有完全的控制能力, CODE 定義的字以機器速度全速運行。
這是 Forth 的一個重要特點。它允許那些明顯地依賴機器的代碼通過機器無關接口變換成為可管理的片斷。當需要把應用移植到不同的處理器上時,我們僅僅需要重新編寫 CODE 字,這些 CODE 字就可以嚴格地按相同的方法與其它 Forth 字進行交互。
Forth 匯編器本身也是極其緊縮的(典型地為 1K 字節),它們可以和編譯器、編輯器以及其它編程工具一起駐留在系統中。這就意味著程序員可以打入很短的 CODE 定義,然后立即執行它們,這個能力在調試客戶硬件時特別有用。
9. 虛擬存儲
Forth 最后一個獨特的組成元素是它按數據和源程序虛擬存儲器的方式使用磁盤(或者其它海量存儲器)。在地址解釋器的情況下,這種方法在歷史上是典型的 Forth 方式,但現在并不通用。磁盤被分成 1024 字節大小的塊,在內存中則準備兩個或者多個緩沖區,數據在引用時被自動讀入緩沖區。每個塊有固定的塊號,直接對應于本地存儲系統的物理位置。任何時候程序需要訪問時,它都會在內存中找到數據,并不需要顯式的讀寫操作。
這樣一個面向塊的磁盤管理方法對于 Forth 獨立系統的實現是簡單和高效的,結果是塊為獨立和協同駐留 Forth 實現中的源程序和數據處理提供了一個完全透明的機制。
在源程序塊中的定義通過 LOAD 命令編譯到內存中。許多系統包含一個編輯器,它把每個塊組織成 64 字符 16 行的顯示模式并提供命令來修改源程序。
源塊在歷史上曾經是 Forth 風格的一個重要組成元素。就像 Forth 的定義可以被視為自然語言中的句子,一個塊相當于是一個段落,通常包含有與一個主題相關的定義,比如“向量處理”。在塊文本的頂行含有這個主題的注釋說明,應用程序可以按實際需要來選擇裝入塊。
塊也被用于存儲數據。小的記錄可以組合進一個塊,大的記錄也可以分布在幾個塊中。程序員可以根據應用的需要分配塊,獨立的 Forth 系統還能夠按磁頭運動最少的原則來組織數據以優化系統,還有幾個開發商提供了基于 Forth 塊的文件和數據庫系統。
在主機操作系統之上運行的 Forth 版本使用文件系統來實現塊機制,另外也提供基于操作系統環境的一般文件操作方法。
10. 數據結構
所有的高級字共享相同的數據結構,這種字的首部含有文本解釋器識別一個字所需要的數據信息,見圖 3 所示。
圖 3 定義的首部
“LINK”字段包含字典中前一個命令的首部地址,在搜索字典時需要這個地址。
“名字長度”字段包含名字中全部字符的數量,后隨這些字符,在解釋過程中進行名字匹配時需要這些數據。許多 Forth 系統僅僅存儲名字的前3個字符,這可以在占用空間最小的情況下避免名字沖突,而許多系統的名字長度允許在 3-31 個字符之間選擇。
本文解釋器從字典的最后一個入口開始處理,并沿著鏈表向后查找直到匹配名字為止。現在還有許多系統提供散列算法,它們把字典分成幾個表,每次只查找其中的一個,這種方式可以大大地節省查找時間。
“代碼指針”是這個字將被執行的第一個指令的 CFA ,它形成了定義體的第一個入口。它也是代碼的地址,這個地址解釋定義的其它部分,對于不同的數據結構將指向不同的代碼。
圖 4 不同的數據類型所指向的行為也不同
字的其它部分也就是定義體,它依不同的數據類型而不同,如圖 4 所示:
?? 在匯編 (CODE) 定義中,體中含有定義命令行為的機器操作碼列表,因此 CFA 含有這個體的地址;
?? 在諸如 VARIBLE 和 CONSTANT 這樣的數據結構命令中,字義的體中含有實際的數據。 CFA 含有處理這些數據所需要的子程序的入口地址,用戶定義數據結構的例子如圖 5 所示。
?? 在高級 : (冒號)定義中,字的體中含有構成這個定義的所有以前定義字的地址列表。 CFA 是地址解釋器 (:) 的地址。
11. 程序舉例
下面是一個典型的 Forth 源程序塊。這個應用程序用來控制 8 個 LED 提示燈,它也說明了 Forth 定義是如何組合以形成應用環境的。
圖 5 一個源程序塊
注意第一行 (LINE 0) 的注釋說明了這個塊中所列出的其它字的屬性,這一行通常被稱為索引行。多數 Forth 系統都有一個命令字來查找塊的第一行以發現哪個塊是應用程序所需要的。
所有的 LED 通過一個位于地址 40H 的 8 位口來訪問。這個位置通過第一行的常數定義給出,于是這個口可以通過名字來引用,而如果以后硬件地址改變了,我們也僅僅需要調整這個常數。字 LIGHTS 在堆棧上返回這個地址,定義 LIGHT 得到棧頂值并把它發送到設備上。這個值的屬性是位掩碼,每一位對應一個 LED 。于是命令:
255 LIGHTS
將點亮所有的燈,而命令
0 LIGHTS
將關閉所有的燈。如果硬件變化了,我們也只需要改寫字 LIGHTS 以適應新的硬件,而應用程序的其它部分則不需要做任何改變。
行 4-6 含有對我們終端輸入進行的處理,終端輸入是為了能夠進行簡單的診斷以確認各個方面都能夠工作正常。這里 DELAY 含有以微秒為單位的延時時間,執行字 DELAY 返回這個變量的地址。 DELAY 的兩個值是由 FAST 和 SLOW 定義的,使用 Forth 的操作!(讀作 STORE )從棧頂得到地址和值,并把值存儲到相應的地址中。
定義 COUNT 運行一個從 0-255 的循環(在字 DO 和 LOOP 之間)。字 I 把循環的當前值放到棧頂,然后發送給 LIGHTS 。接著系統等待由 DELAY 指定的時間。
字 @ (讀作 FETCH )從 DELAY 提供的地址讀取一個值,并把這個值交給 MS 等待指定的毫秒。執行 COUNT 的結果就是以指定的速率從 0 到 255 之間計數。可以這樣調用:
SLOW COUNTS 或者
FAST COUNTS
8-10 行提供單獨命名燈的能力。在這個應用中,它們用作燈的指示器。字 LAMP 是一個使用位掩碼作為參數的定義字。字 CREATE 把一個首部編譯進字典,同時字,(逗號)把掩碼放到定義體中。字 DOES> 把代碼地址放到新字的 CFA 中。于是當新字執行時,它的動作就是獲得所定義的新字體中的第一個項目的內容。
行9和10使用 LAMP來命名特別的指示燈。當其中的一個字比如 POWER 執行時,掩碼就返回到棧頂。實際上,這種行為與 Forth 字 COSNTANT 一樣。但是 LAMP 是一個例子,像這樣使用 CREATE …… DOES> 定義字的能力是 Forth 語言最強大的功能之一,它允許我們定義基于數據結構的“智能應用”。
最后,行 13-15 ,我們有了控制燈面板的字。 LAMPS 是一個變量,它包含有燈的當前狀態。字 LAMP-ON 得到一個掩碼(由其中一個 LAMP 字提供),然后點亮燈。 LAMP-OFF 將指定的燈關閉,同時改變 LAMPS 的狀態。
在應用程序的其它地方,燈的名字和 LAMP-ON 、 LAMP-OFF 可能才是需要直接執行的字。用法是:
POWER LAMP-ON 或
SAMPLING LAMP-OFF
在系統上編譯這個代碼塊的時間大約是半秒,包括從磁盤上讀入的時間。這樣程序員就有可能簡單地打入一個定義然后立即執行它。另外我們總是具有與外部設備直接通信的能力。我們可以首先打入:
HEX FF 40 OUTPUT
來看看是不是所有的燈都亮。如果不是,可以假定有些地址不對,因為上面的句子是把全 1 直接發送給設備。這種類型的交互在與硬件打交道的時候特別有用,它們能夠縮短硬件的開發時間。
12. 擴展
由于 Forth 是可擴展的,大量的開發商為 Forth 語言的應用提供許多擴展產品。這些擴展包括自動化的文檔、終端驅動、磁盤文件管理、數據庫管理、目標編譯器、交叉編譯器和 META 編譯器。
一個目標編譯器允許我們使用一個主機 CPU 比如PC機來編寫系統程序。程序可以通過鍵盤編輯和交互式地測試,之后可以把這些程序編譯到目標環境中并產生對應的 ROM 代碼。目標編譯器的一個功能就是剔除目標系統中不需要的代碼,比如編輯器、編譯器和匯編器。通過這些工作,運行系統的 ROM 開銷可以從開發系統所占用的 8K 字節減少到大約 600 個字節。
交叉編譯器與目標編譯器類似,它允許用戶在主機上開發和測試代碼,然后交叉編譯器將像目標編譯器一樣編譯 Forth 系統,只是交叉編譯器是使用不同的機器語言、為不同的目標 CPU 產生代碼。這個特點允許快速地為新的 CPU 開發新的 Forth 系統,由于 Forth 系統主要是用 Forth 語言編寫的,所以我們只需要為新的處理器編寫一個匯編器,然后為新的處理器進行 Forth 系統的交叉編譯就可以了。大多數的 Forth 系統就是用這種方式開發的,結果, Forth 通常成為一個新處理器上的首選語言之一。
寫一個 Forth 編譯器的過程也被稱為 META 編譯。
13. 多任務
多任務在 Forth 中從一開始時就有了。這些系統不僅僅是語言處理器,而且包含操作系統的特點,許多集成系統完全是獨立運行的,執行所有操作系統的功能。
Forth 的操作環境運行速度快,所以基于 Forth 的系統就能夠支持多用戶和多任務,甚至在那些看似不能實現這些功能的計算機硬件上也是這樣。例如,一個電話交換板的生產商在一個 Z80 上執行 50 個任務。在 IBM PC 上也有幾個多任務產品,有些甚至能夠支持多用戶。在一般支持多用戶操作的計算機上,可以支持的用戶數就更多了,一個運行在單個 MC68000 處理器上的數據庫應用系統能夠支持 100 個終端更新和數據庫請示,而運行速度卻沒有明顯的降低。
多用戶系統可以支持多個程序員同時工作,每個程序員都有自己的私有字典、堆棧和一系列變量來控制任務。私有字典連接到一個共享的、可再入的、包含全部標準 Forth 功能的字典。私有字典可以用來開發應用程序代碼,這些代碼以后可以加入到共享字典中。
圖 6 給出了 Forth 系統實現多任務的典型方法。這是一個“輪循調度算法” 調度器,是 Forth 系統中實現多任務最常用的方法。然而,有一些實現使用時間片調度或者基于優先級的調度以及其它可剝奪的算法,在這樣的系統中每個任務都有自己的用戶區以保存控制變量、私有字典和堆棧。用戶區的第一個字段是 STATUS 變量。這個變量有兩個可能的值:喚醒或者休眠。
圖 6 在循環調度隊列中的 4 個任務
可以被選擇調度執行的任務必須處于喚醒狀態。當任務被選擇執行時它的狀態就被復位到休眠狀態。任務一直執行直到調度器執行到字 PAUSE ,這將把任務的狀態置為喚醒,控制重新返回到調度器。當調度器再次輪循到這個任務時,將從 PAUSE 的指令之后繼續執行。
除了 PAUSE 字之外,任務也可以執行 STOP 字將控制返回到調度器。這與 PAUSE 類似,但是任務的狀態并不切換到喚醒狀態。這樣,當調度器再次輪循到這個任務時,當前的狀態仍然是休眠。這意味著這個任務不能再被執行了,除非它的狀態被另外的任務或者中斷設置為喚醒。
系統以這種方式編程并允許中斷。當一個中斷發生時,一些與機器有關的代碼將指定的任務狀態置為喚醒,這樣當調度器再次到達這些任務時它們將被執行。當任務執行時, STATUS 變量被置為休眠,這就允許一個任務執行時可以發生中斷。因此,如果一個任務執行了 STOP 指令而它的狀態沒有改變,在它執行中一個中斷設置了它的狀態為喚醒,它就可以再次被調度,于是我們能夠緩沖一個中斷。然而,這也就意味著當一個任務主動放棄處理器并希望下一次調度繼續執行時,它必須把狀態設為喚醒。
輪循調度器使用存儲在 LINK 用戶變量中的地址作為下一個任務的地址。如果這個任務的 STATUS 是喚醒的,該任務將被調度執行,否則,調度器取出它的 LINK 地址轉到下一個任務。
這種方法有兩個主要問題:
?? 當一個任務為了其它任務可以運行而主動放棄處理器時,從放棄到再次得到處理器的時間是不確定的;
?? 中斷設置一個任務為喚醒狀態到這個任務實際執行之間的時間也是不可知的。
通過小心地使用 PAUSE ,再加上 Forth 的運行速度很快,已經在主要的應用系統中克服了這些問題。
14.Forth 硬件
早在1980年,ROCKWELL公司就生產了65F11處理器,這是一個6502處理器的變型,它在6502芯片的 ROM 中固化了 Forth 原語,這個芯片被成功地應用到了許多嵌入式系統中。
1981年, Chuck Moore開始設計一個 Forth 虛擬機芯片。這個工作首先在 Forth,INC. 進行,后來專門成立了一家公司來開發這個芯片。 1984 完成設計, 1985 年生產了第一個樣片。后來, HARRIS(INTERSIL) ,Johns Hopkins University 和其它人也開發 Forth 硬件。基于 Forth 的芯片提供了極高的性能,一般可與 RSIC 芯片相比,但是它沒有傳統 RISC 的程序設計復雜性。
15. 標準
Forth 界認識到需要一個標準,使得應用和擴展都以此為基礎。第一個這樣的標準從上個世紀 70 年代中期 FIG(Forth 興趣組織 ) 開始,這個標準后來變成了 FIG-Forth 標準。
第一個主要的 Forth 標準來自于 1977 年在 Utrecht 召開的一次會議,與會者提出了一個原始的標準并同意以后繼續舉行會議討論, 1978 年的會議包括了 FIG 成員,經過一系列由用戶和開發商參加的會議,產生了一個更加廣泛的標準,稱為 Forth-79.
盡管 Forth-79 標準的影響力是巨大的,但是許多 Forth 用戶和開發商發現這個標準中有一些致命缺點。 1983 年,兩次進一步的會議產生了 Forth-83 標準。
受到 Forth-83 標準被廣泛接受的鼓舞,一組用戶和開發商從 1986 開始討論美國國家標準的可行性。美國國家標準 Forth 技術委員會,也稱為 ANS ASC X3/X3J14 委員會,于 1987 年召開了第一次會議,目標是“達到一個可接受的標準,被 Forth 產品主要開發商接受,對現有在用產品的不利影響最小”。 1994 年,也就是大約 7 年之后,新的標準最終產生了,這是所有標準中走得最遠的。使用來自 5 個國家的說明,通過開發商向社會公開。兩年之后,國際標準化組織接受這個標準為國際標準。
16. 研討會和定期出版物
由于人們使用 Forth 進行工作并不斷做出有益的擴展,所以 Forth 語言也在不斷地發展。有三個年會關注著 Forth 語言的發展:
Forth Modification Laboratory (FORML)
held at Mt. View in California and organised by the Forth Interest Group.
Rochester Forth Conference (RFC)
held at the University of Rochester in New York and organised by the Institute for Applied Forth Research Inc.
European Forth Conference (euroForth)
held in a different location each year. This is the only conference to provide a refereed (peer reviewed) section. Originally organised by the European Forth Interest Group, but now organised by various European based Forth vendors.
對于 Forth 的許多新的思想最先在這些 Forth 相關的雜志上出現:
Forth Dimensions (ISSN 0884-0822)
published six times a year by the Forth Interest Group for its members.
Journal of Forth Application and Research (ISSN 0738-2022)
published irregularly by the Institute for Applied Forth Research Inc. This is the only peer review (refereed) journal directed to the Forth language. The Journal is now published electronically on the Internet. A paper version of the Journal will be published at irregular intervals.
17. 總結
FROTH 可以被看成是有兩個堆棧(參數棧和返回棧)的、有可擴展匯編語言的處理器。 Forth 解釋器可以看成是這個抽象處理器的完全宏匯編器和完全集成的操作系統。
這就給我們提供了一個交互式的調試環境,使我們可以增加新的宏(高級定義)和新的指令(低級 CODE 定義)。它甚至允許我們通過定義新的數據類型(使用定義字 CREATE …… DOES> )擴展宏系統本身。因為這個解釋器也是一個全功能的操作系統,所以程序員只需要學習一種工具。
Forth 有四個直接的優點:親善、直接、可擴展和經濟。它還有兩個間接的優點:可理解和符號化。
Forth 不僅僅是一種語言,它更是一種解決問題的哲學思想。這可以用縮寫 K.I.S.S 來概括( Keep It Simple and Stupid ,保持它的簡潔和易用)。我們可以引用 Jerry Boutelle (owner of Nautilus Systems in Santa Cruz, California) 的話,當被問及“使用 Forth 是怎么影響你的思維”時,他回答:
“Forth 以許多方式改變了我的思維。從學習 Forth 開始,我已經使用了各種語言編程,包括匯編、 BASIC 、 FORTRAN 。我發現我一直在使用 Forth 的問題分解方式,通過創建字的方式把它們組合在一起。例如,在處理字符串的時候,我會像 Forth 的 CMOVE 、 -TRAILING 、 FILL 那樣來定義子程序。更基本地, Forth 堅定了我對簡單性的信念。在面對一個問題的時候,許多人使用特別復雜的工具,但是簡單的工具也可以使用而且更有用。我試著簡化我生活的方方面面。”
這里我引用中國哲學家老子的一句話:
“為學日益,為道日損”
或者引用 Antoine Lavoisier (1789) 的話:
“把科學和語言分離是不可能的,因為每一項自然科學總是包含三件事情:科學所基于的一系列現象,在頭腦中命名這些現象的抽象概念,表達這些概念的詞匯。為了說明一個概念,我們需要一個詞匯;為了描繪一個現象,我們需要一個概念。所有這三件事情都反映了同一個現實。”
這就是包含在 Forth 語言背后的哲學。
18. 參考文獻
略 ( 可參見原文 )
總結
以上是生活随笔為你收集整理的Forth 语言概要的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 渗透实战(周三):Ettercap·AR
- 下一篇: web基础学习