第三章 嵌入式符式作業系統的交叉編譯
3.5 系統常用指令
FORTH ENGINE 的終端機介面是一個有效又很簡單的設計。在執行 BYTE_CHANGE 指令時,UART 暫存器中的 LOW_BYTE 送出 8 位元資料,此時 HIGH_BYTE 位元即被移到 UART 暫存器。但我們將 W (0)送入一個正反器,
而這個正反器的輸出直接就連到一個輸出腳位上,此即 FORTH ENGINE 的終 端機輸出埠。
當執行 BYTE_CHANGE 指令時,我們將終端機輸入腳位的狀態鎖入 W(16) , 這是 W 暫存器的溢位元【Carry】,此即終端機的輸入埠了。終端機的輸入 和輸出,即全由 EMIT 及 KEY 來操控。EMIT 及 KEY 用 50us 及 100us 兩個指 令來延遲到 19200 Baud 的半位元及 1 位元的時序。
﹙n1 n2 n3 -- r q﹚算出 n1*n2/n3 最後的餘數 及商。
表 3-9 乘數指令
這是乘法的基本指令,其他乘法指令皆從它衍生而出。FORTH ENGINE 有單步乘法機器碼 MUL。將 W 清作 O,n1 放在 S 內,n2 放在 A 內,重覆執 行 MUL16 次,即可在 T-A 中得到 32 位元的積。
3.5.3 記 憶 指 令
HERE ﹙-- a﹚ 變數,內容為詞典邊界的最高位址。
PAD ﹙-- a﹚ 變數,內容為字串暫存區的位址。
TIB ﹙-- a﹚ 變數,內容為終端機暫存區的位址。
@EXECUTE ﹙a --﹚ 由 a 中取出執行碼欄地址,然後跳到該處去 執行。
CMOVE ﹙a1 a2 n --﹚ 從 a1 搬 n 個 16 位元字碼到 a2 區。
FILL ﹙a n c --﹚ 將 16 位元數值 c 填入 a 起的 n 字碼區。
>CHAR ﹙c -- c﹚ 將不能印出的字符都改為底線符號_,如此為 防止印表機在紙張上印出亂碼。
表 3-10 記憶指令
3.5.4 壓 縮 字 串 及 解 壓 指 令
PACK$ ﹙b n a -- a﹚ 將在 b 位址的 n 個字符壓縮到 a 區,每 2 個 8 位元字符壓縮到一個 16 位元的字碼中,最 後補 0。
UNPACK$ ﹙a b -- b﹚ 將在 a 地址中的一個壓縮後的字串解壓,並 放在 b 區。
表 3-11 壓縮字串及解壓指令
例如 7 個字符的字串「UNPACK$」,未壓縮時是由 8 個 16 位元之字碼組成,
壓縮後成為 2 個字碼,內容如下:
Bit 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 字碼 0 1 0 1 0 1 0 1 0 1 0 0 1 1 1 0 è 'U' 'N'
字碼 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 1 è 'A' 'C' 字碼 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 è '$' 0
字串壓縮後不但減少了記憶存儲的空間,也顯著地加速了 Forth 系統查字 典的速度。在比對字串時,可一次比較 2 個字符。
3.5.5 數 值 印 出 指 令
FORTH ENGINE 的數值都是以 16 位元方式存在記憶體及暫存器中的,只 有在將數字印出時才須要將其轉成為 ASCII 字串,每字符 8 位元。轉換時 用 BASE 裡所存數值作轉換的基數。所以可以很方便地把數值隨時轉成以十 進制,十六進制,或其他基數的字串形式印出。
數字列印的指令常用的有以下幾個:
. ﹙n--﹚ 將 n 轉換成字串顯示在終端機上。
U. ﹙u--﹚ 將自然數 u 顯示在終端機上。
.R ﹙n1 n2 -- ﹚ 將 n1 顯示在 n2 欄位中,靠右對齊。
U.R ﹙u n --﹚ 將 n1 顯示在 n2 欄位中,靠右對齊。
? ﹙u n --﹚ 將自然數 u 顯示在 n 欄位中,靠右對齊。將 a 地 址中的數值取出,顯示在終端機上。
HEX ﹙--﹚ 將 BASE 基數改為 16,以後數字轉換即十六進制。
DECIMAL ﹙--﹚ 將 BASE 基數改為 10,以後數字 轉換即十進制。
表 3-12 數值印出指令
為要完成以上數值列印的功能,FORTH ENGINE 須要有一系列的支援指令。
使用者也可以自行利用這些指令,設計出更適合特殊不同場合應用的列印 指令。
str ﹙n -- b u﹚ 將數值 n 轉換成字串儲存在 b 區,字串長度是 u。
DIGIT ﹙u -- c﹚ 將一位數的值 u 轉換成其對應的 ASCII 數碼 c。
EXTRACT ﹙n1 base -- n2 c﹚
以基數 BASE 去除 n1,餘數轉成一位的數碼 c,留 下商數 n2,以便繼續數值轉換之程序。
<# ﹙--﹚ 準備轉換,設定 PAD 存所得字串,以 HLD 為指標。
HOLD ﹙c --﹚ 將一位數碼 c 寫到 HLD 所指的位置,並將 HLD 減 1,準備接受下一數碼。
# ﹙u1 -- u2﹚ 由 u1 中轉出一位數碼寫到 PAD 中,商是 u2。
#S ﹙u --o﹚ 將 u 轉出所有數碼字串寫到 PAD 中,最後商是 0。
SIGN﹙n --﹚ 若 n 小於零,則在數碼字串前加負 號。
#> ﹙u1 -- b u2﹚ 丟掉 u1,留下數碼字串的地址 b 及其長度 u2。
表 3-13 列印指令
3.5.6 數 值 輸 入 指 令
由終端機輸入的數字都是 ASCII 數碼字串,須要轉換成對應的 16 位元 數值才能放在堆疊上運用,或是存在記憶體中。將數碼字串轉換成數值的 指令是:
NUMBER? ﹙ a -- n -1 | a 0 ﹚
將在位址 a 的數碼字串轉換成 16 位元的數值 n 及-1 的旗號。若轉換不成功,(字串中有非數字
a 0 ﹚ 碼的符號),則保留地址 a 並留下 0 的旗號。
DIGITS ﹙ c base -- u f ﹚
將一位數碼字符 c 按基數 BASE 轉為數值 u 及 -1,若 c 不是數碼,則保留 c 並留下 0 的旗號。
表 3-14 數值輸入指令
3.5.7 其 他 列 印 指 令
除了列印數值字串外,FORTH ENGINE 也提供一套相當完整的指令,讓 使用者很方便地在終端機上顯示各樣文字資料,排列成整齊美觀的文件,
這套指令是:
SPACE ﹙--﹚ 輸出一個空格。
CR ﹙--﹚ 換行。
CHARS ﹙n c --﹚ 輸出 n 個 ASCII 碼 c 所對應的字符。
TYPE ﹙a u --﹚ 從地址 a 取 u 個 ASCII 碼字符輸出。
Do$ ﹙-- a﹚ 將編碼在程式中的字串解壓縮到 TEXT 區,並將 TEXT 區的地址 a 放上堆疊。 $"| ﹙-- a﹚ 將編 碼在此指令後的字串解壓,存到 a 區。
." | ﹙--﹚ 將編碼在此指令後的字串解壓,並印出。
表 3-15 其他列印指令