2025年5月16日 星期五

實踐

實踐


曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
16 May 2025


這一陣子,我在適應 ARM 系統的使用環境,經常會碰到一些問題,使用環境之適應性的建立,全憑身體力行的實踐,別無它法。這種事情已經不是時下青年喜歡做的事情,因為耗時又麻煩,要細讀許多資料,要實作許多設計,逐個度過難關後,才能有點成就。

以前,在發展系統時,沒有注意到摻雜了特例的用法,會給後來改到新環境繼續延用時產生麻煩。因此,重新在新環境發展系統時,我注意到重建的系統應該要注意永續可用的問題,最好不要強加個人偏好性的設計,以免自找麻煩。趁著這次再在 ARM 環境建立 abc Forth 運算系統的機會,把能夠永續使用的設計整理妥善,簡化發展程序,刪除所有個人偏好,不再添加於未來應用。刪除的部份可以另行建檔,需要時才載入系統。

有許多經驗是實踐後才知道的。今天,我在 Raspberry pi4 上完成了一套發展,改到 pi3 去試用,就出現了記憶體分段選址有問題之訊息,系統不能執行。但憑經驗,一看就知道,是因為我將系統容量宣告得太大了的關係,將設定改小就能解決問題。在 pi4 上有 4GB 的 RAM 可用,而 pi3 只有 1GB 的 RAM ,我在 pi4 上發展時,將系統宣告得很大,超出了 1GB 的範圍,就出問題了。由於我設計的 abc Forth 系統需要執行大數計算,它比較耗用記憶體,雖然長成的系統仍然是只有幾百 KB ,運算大數時,可能要耗用 Forth 系統從 HERE 開始算起以上的記憶體。因此,只宣告不到 1MB 的使用量絕對不夠。經過這次產生問題後的經驗告訴我, pi3 上只能用 1GB ,也就是 1000MB ,我若將 Forth 系統的記憶體使用量宣告成 1GB 的十分之一,也就是 100MB ,算是比較妥當。如此一來,我就能在操作上比較方便的 pi4 系統上發展出轉置到 pi3 也能執行的 abc Forth 系統。這件事已經測試完畢。

在家裡獨自發展系統,不易察覺這種單板電腦有什麼使用上的問題,家中若有人同時上網,就能體會出問題。昨天,我小女兒在我這裡使用網路開會,我才發現 pi4 啟動後連編寫程式都有困難,反應慢到無法接受的程度,只能關機停用,待我能夠獨享網路時再搞程式設計。單板電腦採用 WiFi 上網,響應速度當然沒有一般手提電腦的速度快,能分享的無線訊息傳遞必定大受影響。pi3 的運行速度為 1.2GHz ,pi4 為 1.8GHZ ,比起一般電腦為 2.5GHz 的速度,確實差了許多,用時不可不知。

ARM 是 Linux 的作業環境,我在產出基本系統後,必須取用原在 Window's 系統上發展出來的應用程式。程式中有些說明,包括中文,因係 big-5 的編碼,轉到 Linux 採用 utf-8 編碼時無法閱讀,要操作轉碼程式來更換編碼,才能看到中文的內容。每次打字總覺得麻煩,於是自己設計了一個小程式,想將檔案內容的碼轉換時,只須輸入檔案名稱就夠了,會用電腦的人,應該盡量自己設計程式簡化這種問題。這個程式可以在 Linux 作業系統中之 ciForth 系統使用,我用的是 Lina64 Forth。設計要點只是字串操作,然後設法運用以 Forth 轉交 BASH 執行出轉檔程式的技巧,就能完成工作。轉檔程式的名稱叫做 iconv ,它的詳細使用說明,不在此討論,這種 Forth 的使用技巧,則是當下程式發展者應該建立的運用觀念。程式能完成 big-5 與 utf-8 碼間的互換,只須輸入欲轉碼之檔案名稱便可。


 
\ utf8.f

create InputFile 32 cells allot
create OutputFile 32 cells allot

: InputSetup 
  InputFile 32 cells erase
  OutputFile 32 cells erase
  cr ." Input file name : " cr
  input$ InputFile $! 
;

: Utf8Setup
  S" iconv -f big-5 -t utf8 -o utf8-" OutputFile $!
  InputFile $@ OutputFile $+!
  BL OutputFile $c+
  InputFile $@ OutputFile $+!
;

: Big5Setup
  S" iconv -f utf8 -t big5 -o big5-" OutputFile $!
  InputFile $@ OutputFile $+!
  BL OutputFile $c+
  InputFile $@ OutputFile $+!
;
  
: utf8
  InputSetup 
  Utf8Setup
  OutputFile $@ system
;

: big5
  InputSetup 
  Big5Setup
  OutputFile $@ system
;


至聖先師


2025年5月2日 星期五

時基

時基


曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
2 May 2025


取得時基(time base)訊息是一個很古老的電腦技術,卻是一個恆有需要的功能。

使用電腦實測事件發生的時距,在許多場合都有實用價值。它的硬體根據,就是在 CPU 旁邊必須具有能自動運行的系統時脈計數器(system timer)。

我在 40 年前接觸單板電腦時就開始用過這種技術,那時的電腦,沒有現成的時脈計數器,時脈訊號只供 CPU 直接運行使用,沒有計數器來留存時脈的數量。

在 6502 CPU 盛行的時代,我們採用專屬的 6522 晶片解決問題,其中就有一個 32 位元的計時器,如果嫌其留存的計數量不足,還能串接兩個 6522 晶片來使用。我曾用它來測量原子爐停爐棒的跌降時間,精確度可以達到微秒,實際需求只須百分之一秒。有一篇討論 Forth 指令精確執行時間的文章在 FORTH 期刊第 2 期中刊出,標題為: FORTH 程式執行速度之定量評鑑,也用這套技術。我還曾為一家地磅公司提供電腦內的自動時鐘,也用這套功能,那個年代的個人電腦不附帶這種功能,需要自己設計程式。

衛星定位系統能夠提供精確的定位、速度、時間等訊息,其工作原理也離不開這套技術,系統的時基越精確,訊息就跟著精確。

今日的電腦,內附現成的時鐘是基本配備,使用者已經不需要另外加裝硬體就能取得標準時基。我在使用 Lina64 Forth 時,為系統添加了一個低階設計的指令 getticks ,以備不時之需。
getticks 的整個添加內容,與一個簡單的 main 程式,及 main 被執行出來的視窗畫面,展示如下 :


#  **************
#  * GETTICKS   *  ( -- n )
#  **************
#
        .balign    8,0x00
N_CLOCKFET:
        .quad      8
        .ASCII      "GETTICKS"
        .balign    8,0x00
CLOCKFET:
        .quad    CLOCKFET+HEADSIZE
        .quad    CLOCKFET+HEADSIZE
        .quad    0x0
        .quad    INVERT
        .quad    N_CLOCKFET
        .quad    0
        .quad    0

	rdtsc
	shl	%rdx, 32
	or	%rdx, %rax
	push	%rdx

	LODSQ                  # NEXT
        JMP     QWORD PTR[%RAX]   

\ display Time-Stamp Counter

: main
  !xy
     begin
           0 40 gotoxy 
           getticks 
           0 20 D.R
     key?
     until
  @xy 
;




透過幾千年的時基,認識北京、周公與召公。

時基尺度以千年計量時,考古證據顯示,北京建城已有三千多年的歷史。當時老是被孔子尊稱的周公又是何等人物?他很能代表中國很古的名人。

引用的照片取材自中國新華社供圖,展示北京房山縣琉璃河遺址出土的五件青銅禮器 : 尊、卣(音永)、爵(音決)、觶(音至)、鼎。

五個禮器上都各刻有七處的四字銘文「太保墉燕」實證了北京已有三千多年的建城歷史。這是重要的事情,所以說了七遍!

「太保」是西周成王時期的召公 奭(音是),「燕」指琉璃河遺址所在的燕地,「墉」意為「築城」。
「太保墉燕」,意為「太保召公來到燕地建設都城」。

北京在民國時期被平民老百姓稱為北平,文人墨客寫作時喜稱燕京,解放後被稱為北京。

召公是太保,周公是太師。比照現在,太保召公,他相當於國防部長,另有太師周公,他相當於行政院長。這兩人是輔佐周朝各個帝王,直至西周成王的重臣。

孔子說周公制禮作樂,我們都能朗朗上口,那麼,召公就應該是克商(朝)平亂了。後來,周公管陝東,召公管陝西。

後人恭維文官周公時,似乎也不該忘了武官召公,要尊敬軍人才有國本。


時基另有妙用

我在設計亂數產生函數時,特別喜歡取用硬體計時器的內容來當作產生亂數的起始種子數字, abcLina64 Forth 系統就這樣使用時基。

三月份,我從台灣回到紐西蘭後,便打算在 ARM 系統上再度發展出 ciForth 的等效版本。我有 Raspberry Pi3 及 pi4 的單板電腦,試用一段時間後發現,在 pi3 上安裝 Ubuntu 20.04 mate OS ,用起來性能還算可以,只是 1.2 GHz 的速度太慢,滑鼠在視窗作業環境響應太慢容易當機。 pi4 則安裝了 Debian OS ,1.8 GHz 的運行速度,讓滑鼠的響應勉強跟得上需要,編寫程式時比較方便。我已在兩套單板上試跑過 ciForth ,只在文字視窗中運行,沒有問題。我的目標是設計出與 Lina64 性能相當的 abc Forth 數學計算系統。很不幸,在設計與 getticks 功能相同的指令時遭遇到困難。

ARM 系統發展與應用的生態環境尚不健全,出現問題時,網上能獲得的資源相當有限,現行軟、硬體資料能夠提供的說明比較含糊,發展起來確實有點吃力。甚至於在已公佈的ciForth 源程式中,也明白的提示了有那些指令還暫時不能正常使用。想讓系統發揮作用,還得努力。

相關資料顯示,ARM CPU 從系統計數器(system counter)抓取時基的指令是 MRS ,但文件也提示,這個指令在使用者模式時不能執行, 必須在特權模式狀態下才能執行。

關於這方面的問題,我暫時抱持著觀望的態度,靜待有比較好的範例可以採用時再行引用。

把亂數產生程式中的起始種子數亂化一下的方法很簡單,可以將 getticks 取得之值直接就存進種子變數。
也可以把 getticks 隨時取得的數字當種子數來亂化一次,再回存於種子數。這樣做,就能憑硬體計時器低效部份之內容高速變化的不確定性,產生另一組亂數群。
採用硬體來亂化種子數的效果是非凡的做法,尤其在 64 位元的時代,運用起來幾乎不可能被任何使用者猜得到第一個亂數函數產生的新亂數會是多少。
亂化的方法可以如下列這麼一個簡單的程式而已:

: RANDOMIZE ( -- )
GETTICKS GETTICKS * RANDOM ( n1 -- n2 ) SEED ! ;

時基的運用還有許多例子可舉。所以,無論是誰在建造新的 cpu 時,都應該考慮到,硬體計時器,是一種在系統應用方面常常需要的設置。