本文收錄 Ray Duncan 1983 年編寫的 CLEAN.ASM,功能為過濾文字檔:移除控制碼 (保留 LF/CR/FF)、去除高位元、展開 Tab 為空白、附加 EOF 標記。支援區塊讀寫 (1KB 緩衝區)、命令列參數解析、錯誤處理、進度顯示。展示了 DOS 2.0 檔案控制代碼 API (INT 21h AH=3Ch/3Dh/3Fh/40h/3Eh)、緩衝區管理、字元級處理邏輯、模組化程式結構。
.CLN讀字元 → AND 7Fh (去高位)
→ 若 >= 20h : 正常字元 → 寫入、欄位計數++
→ 若控制碼 :
EOF(1Ah) : 結束
Tab(09h) : 展開至下一 8 欄位倍數 (送空白)
CR/LF/FF : 寫入、欄位歸零
其他 : 捨棄
→ 緩衝區滿寫入磁碟
; 讀取區塊
read_block:
mov bx, input_handle
mov cx, blksize (1024)
mov dx, offset input_buffer
mov ah, 3fh
int 21h
; 寫入區塊
write_block:
mov bx, output_handle
mov cx, blksize
mov dx, offset output_buffer
mov ah, 40h
int 21h
get_char/put_char 管理緩衝區指標,滿/空時呼叫區塊讀寫。EOF (1Ah) 標記,簡化主迴圈判斷。CY=1 表示磁碟已滿。clean5: ; 處理 Tab
mov ax, column
cwd
mov cx, 8
idiv cx ; AX=商, DX=餘數
sub cx, dx ; 8 - 餘數 = 需補空白數
add column, cx ; 更新欄位計數
clean55:
push cx
mov al, 20h ; 空白
call put_char
pop cx
loop clean55
將目前欄位數對 8 取餘,補足至下一個 8 的倍數。
infile:跳過前導空白,複製至 CR 或空白前,存入 input_name。outfile:複製 input_name,掃描 '.' 或結尾,強制改為 .CLN。CY 旗標,失敗顯示對應訊息 (msg1~msg5)。sign_on 顯示標題、版權、輸入/輸出檔名。pasciiz 列印 ASCIIZ 字串 (以 0 結尾),並將大寫轉小寫顯示。cseg segment ... ; 程式碼段
clean proc far ; 進入點
infile, outfile ; 檔名處理
open_input, open_output ; 檔案開啟
init_buffs ; 緩衝區初始化
sign_on ; 顯示資訊
clean3: ; 主過濾迴圈
get_char, put_char ; 緩衝字元存取
read_block, write_block ; 區塊磁碟 I/O
flush_buffs ; 寫入剩餘緩衝資料
close_input, close_output
sign_on, pasciiz ; 訊息顯示
cseg ends
data segment ... ; 資料段
input_name, output_name ; 檔名緩衝
input_handle, output_handle
input_ptr, output_ptr ; 緩衝區指標
column ; 欄位計數 (Tab用)
msg1~msg9 ; 各類訊息
input_buffer, output_buffer (1024 bytes each)
data ends
stack segment ... ; 堆疊段
stack ends
end clean
| 功能 | AH | 輸入 | 輸出 |
|---|---|---|---|
| 建立/截斷檔案 | 3Ch | DS:DX=檔名, CX=屬性 | AX=控制代碼 |
| 開啟檔案 | 3Dh | DS:DX=檔名, AL=模式 | AX=控制代碼 |
| 讀取檔案 | 3Fh | BX=控制代碼, CX=位元組數, DS:DX=緩衝區 | AX=實際讀取位元組數 |
| 寫入檔案 | 40h | BX=控制代碼, CX=位元組數, DS:DX=緩衝區 | AX=實際寫入位元組數 |
| 關閉檔案 | 3Eh | BX=控制代碼 | 無 |
| CLEAN 技術 | 現代對應 |
|---|---|
| 1KB 區塊緩衝 I/O | 標準庫 fread/fwrite、BufferedReader/Writer、mmap |
| 字元級過濾管線 | 串流處理 (Stream API、Reactive Streams、Pipes) |
| Tab 展開演算法 | 編輯器/終端機渲染引擎核心邏輯 |
| 命令列解析 | getopt/argparse/CLI11 |
| 錯誤碼旗標檢查 | 例外處理 / Result/Either 型別 / errno |
| ASCIIZ 字串處理 | C 風格字串 / std::string_view / Rust &str |
INT 21h 3Ch/3Dh/3Fh/40h/3Eh 完整流程PROC、參數透過全域變數/堆疊傳遞CLEAN.ASM 是 DOS 時代實用工具程式的典範:功能明確、結構清晰、錯誤處理完善、緩衝區管理高效、使用者介面友善。其核心演算法 (字元過濾管線、Tab 展開、區塊 I/O) 在現代文字處理、編輯器、編譯器前端、日誌清洗工具中依然是基礎建構塊。研讀此碼,可深入理解「資料流處理」的本質邏輯,跨越時代與平台。