弦外之音
曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
2 July 2025
這一次,我不談程式,改談 Forth 的哲理。哲理的範圍很廣,我縮小到只談 Forth 系統變數(user's variable)。我也不談各個系統變數的定義,只談整體的意義。
初學 Forth 的人在基礎教材中見不到這方面的論述,基礎教材通常只教標準指令的用法。也不談 Forth 的系統架構,因為各個 Forth 的系統架構大都不同,難談。
如果您想把 Forth 學得很好,將來想要大肆利用 Forth 發展出自己的抱負,Forth 哲理中的每個項目就都應該搞得清清楚楚。系統變數只是眾多哲理中的一個項目,它有必須存在之宏觀的理由,個別系統變數都有必須建立它的道理。這種哲理看似是在學習 Forth 時的弦外之音, 實則是使用者必需學會的基本觀念,碰到它時,不要逃避,不要排擠。
我們在 1984 年 4 月創辦的『FORTH期刊』p.19 中就有一篇諶其騮作者所寫的『FORTH系統變數簡介』,該文可以提供永久性的參考。即使後來其他系統的系統變數已有大量的變化,系統變數的使用觀念則沒有改變,是系統所需,也是使用者設計程式時經常非要用到不可的東西。
系統變數有幾項特色。
首先是通常被集中處裡,除了能讓系統結構整齊外,它另有幾方面隱含的性質。
古老的 Forth 強調多工(multi-task)性能,有少數幾個系統變數就是單工被執行時非得獨立起來使用不可的單套變數,例如:兩個堆疊指標 S0 及 R0 就是。它們都是能讓工多而不亂的變化根據。在 Forth 系統中,所謂的一工,可能只是一個程式,也可以是一位使用者(user),Forth 也因此把系統變數稱為使用者變數。
Forth 系統具有可以長出標的系統(target system)的固有性能,但不是每個系統的作者都能將這種性能設計得出來。所以,我在挑選可用系統時,會將這項要求列為首要考慮條件,以便自己長期努力發展出來的成果能被永久性的固定下來。Forth 系統無論是在初次以各種其他工具語言發展出來,或者是就憑祖代系統憑藉蛻變編譯(meta compile)能力產生新的子代系統,在系統長成的最後階段,都得對系統變數進行最後的調整修訂,如此,子代系統運行時,才能有正確的系統變數內容可用。
系統變數的放置方式有秩序性,不可前後隨便對調,這也是多工設計時的一項簡明要求。Forth 系統內的自有多功能力,在規劃出新的一工(task)時,第一個記憶體單元放的是此工是否要睡著(sleep down)不被執行時的跳躍指令,跳到下一工去。否則就該醒來(wake up)執行本工的第一件處置工作,那就是找到自己的回返堆疊指標,在那裡取得執行碼。因此,緊隨是否該跳躍的指令碼後,第一個系統變數就放此工總系統變數的指標,叫 U0 ,然後,緊隨著的就是 S0 和 R0 ,這種秩序絕不能變。
系統變數通常有幾十個,以現行的 ciForth 為例,Fig-Forth 是它的前身,系統變數大約有四十個。這些系統變數又可化分成兩大類,一類是多工狀況執行時要求至少必須獨立分出來的系統變數,在 ciForth 中選出了十一個。另一類系統變數則是分工程式被執行時還必須與它工共用的系統變數,成立新工時,就可以不必另外宣告出記憶體空間來放置此類系統變數。因此,成立新工的宣告過程,必定包含了需要宣告出多少個單元來存放該工之系統變數的用量。
傳統的 Forth 多工,是根據一種被稱為知更鳥輪唱(round Robin)法設計出來的多工方式,跟現行作業系統固有的多工運作方式不同,現行作業系統採用一種所謂的先佔式(temptative)多工來運作,那一工先被喚醒就先執行那一工,多 CPU 的時代,不再熱衷於傳統 Forth 的多工設計,逐漸地,大家也不設計傳統的多工程式了。
我們在 32 位元的 Win32Forth 系統中還能見得到純用 Forth 設計出來的多工範例,在 64 位元的 ciForth 中沒有這方面的需求。我需要時,也改採 Linux OS 中的多工方式,直接讓 Forth 去叫用另一套 Forth ,執行出另一個工。這在本網頁的貼文中可以看到好幾個使用範例, 凡是有程式執行的展示影片,同時出現有背景音樂的短片內,都依靠用 Forth 叫用另一套 Forth 執行音樂播放之先佔式多工而完成設計。
ciForth 是一個可以自行長出標的系統的好用 Forth,它在處裡出長成的標的系統時,有一段處裡系統變數的工作必須要做,這樣,整個系統的可執行碼檔案中才能固定出新的系統變數規格,這是一個很有效率的作法,卻不是其他 Forth 系統能辦得到的設計,是作者熟悉 Linux OS 使用環境後的創意設計。也請注意 ciForth 在各種作業系統中的版本,並非全部都具有此項功能,微軟的 Wina64 就不具有,沒有此項功能的系統我就不用。
能讀通系統源程式碼是件痛快的事情,看似弦外之音的系統變數之形成哲理大有意義存在,講述如何研究它? 則超出了貼出一個範例程式的範疇,只能專文討論。我在設計 ciForth 的 ABC Forth 數學計算系統時,動用到它,修改過執行 >NUMBER 時必須隱性影響 DPL (第 20 個系統變數)的方式,特貼此文說明。
黃河
中國所有的兒童都聽過『大禹治水十三年,三過家門而不入』的故事,也曉得故事的意義在強調工作時要用對方法,要堅忍不拔的完成工作,這是四千多年前流傳下來的故事。
大禹是夏朝的第一個皇帝(在位七年,時間為西元前 2205~2198 年,另有在位 27 年之說)。這個故事從此告訴了後人,黃河經常氾濫成災。古人形容邪惡帝王的惡劣統治就像洪水與猛獸,所指的洪水,就有如黃河的氾濫。
中國歷史上,黃河在過去的三千多年內共有高達 1,593 次的氾濫記錄,氾濫使其主幹道改變了 18 次;每次的泛濫也都造成大量傷亡及經濟損失。
近代的四次記錄則為 1410 年黃河氾濫, 1887 年黄河决口, 1921 年宫家决口, 1958 年黄河洪水。
1900 年以後的兩次災情記錄為:
宮家決口也稱宮家壩決口,是民國時期 1921 年 7 月 19 日發生在中國山東利津宮家的一次黃河決口。決口後水災影響到利津、霑化、濱縣、無棣四縣,災民 18.4 萬餘人,受災面積 5400 平方里。
1958 年黃河洪水指的是 1958 年 7 月發生在中華人民共和國黃河中下游地區的水災。此次水災淹沒村莊 1708 個,淹沒耕地 304 萬畝,房屋倒塌 30 萬間,京廣鐵路中斷 14 天,受災人口達 74.08 萬人。據中國政府官方資料顯示,河南、山東兩省出動約 200 萬人進行防汛,確保了黃河下游的防洪安全。
黃河氾濫的起因係上游大量沖積下來的黃沙,沉積在下游出海前的河床上,長久下來,河槽萎縮,造成河床高於地面的懸河現象,直到河堤受不了而潰堤,於是發生規模宏大之河水氾濫的洪災,這是定性的說法。最近我看到中國黃河教育電視台的科普教育新聞報導中,提供了一些近代的定量數據,可以讓大家更深刻的了解黃河。
根據科普新聞報導,現代的黃河,平均每年有 4 億噸泥沙堆積在下游河道裡。下游「地上懸河」現象長達 800 公里,最大懸差 10 公尺。
大禹治水能夠成功,用對的方法是疏導而非築堤圍堵,今人治理黃河,當然也只宜疏導。問題是年產 4 億噸的泥沙可不是個小量的數字, 800 公里的 10 公尺高度是個驚人的河床,就算動用南海吹沙填海的工程機器來幹此活,可能都不是一件輕鬆的工程,因此,最好的疏導方法,仍是讓沙流入海。
中國科普報導則介紹了一種借力使力的方式調沙,利用上下游水庫間歇性的突然大量放水,便可借大量的挾沙水流沖洗河床,這種調水調沙的方式可以清除河床積沙入海。今年一年進行了 26 次,可以沖掉 21 億立方公尺的沙,讓河床平均下切了 3.1 公尺。
文末附貼一部陝西電視台製作的壺口大瀑布記錄短片顯示了大量的黃泥水,另附黃河下游廣闊的河道照片與幾張三門峽水庫與小浪底水庫調水調沙時的壯觀景象。在來沙的源頭執行沙漠造林有利於水土保持,中國做得到,最後展示一張在這一方面成就明顯的照片。