首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

DOS 時代組合語言經典原始碼賞析:CLEANF 標準輸入輸出過濾器

     編輯:組合語言

前言

本文收錄 CLEANF.ASM (Bob Taylor 改自 Ray Duncan 的 CLEAN),功能相同但改為標準輸入/輸出/錯誤過濾器:從 STDIN 讀取、過濾後寫入 STDOUT、錯誤訊息輸出 STDERR。支援管道重導向 (type file.txt | cleanf > clean.txt),體現 Unix 哲學「做一件事、做好、支援管道」。程式極精簡 (約 100 行),展示 DOS 2.0 預定義控制代碼、字元級管線處理、最小化資源佔用。

核心設計差異:CLEAN vs CLEANF

特性CLEANCLEANF
檔案指定命令列參數標準串流 (STDIN/STDOUT/STDERR)
檔案開啟/關閉明確 3Ch/3Dh/3Eh無需開啟/關閉,繼承自父進程
緩衝區1KB 區塊緩衝單字元緩衝 (input_buffer/output_buffer db 0)
錯誤輸出螢幕訊息框STDERR (控制台)
適用場景獨立檔案處理管道鏈結、腳本自動化

DOS 2.0 預定義控制代碼

stdin  equ 0000   ; 標準輸入
stdout equ 0001   ; 標準輸出
stderr equ 0002   ; 標準錯誤
stdaux equ 0003   ; 標準輔助
stdprn equ 0004   ; 標準列印

子進程繼承父進程的控制代碼,CLEANF 直接使用這些值呼叫 INT 21h AH=3Fh/40h,無需開啟檔案。

完整原始碼

name cleanf
page 55,132
title 'CLEANF - Filter text file'

cr equ 0dh
lf equ 0ah
ff equ 0ch
eof equ 01ah
tab equ 09h
command equ 80h

stdin equ 0000
stdout equ 0001
stderr equ 0002
stdaux equ 0003
stdprn equ 0004

cseg segment para public 'CODE'
 assume cs:cseg,ds:cseg
 org 100H
clean proc far
 push ds
 xor ax,ax
 push ax

clean3: call get_char
 and al,7fh
 cmp al,20h
 jae clean4
 cmp al,eof
 je clean6
 cmp al,tab
 je clean5
 cmp al,cr
 je clean35
 cmp al,lf
 je clean35
 cmp al,ff
 jne clean3
clean35:
 mov column,0
 jmp clean45
clean4: inc column
clean45: call put_char
 jnc clean3
 mov bx,stderr
 mov dx,offset err_msg
 mov cx,err_msg_len
 mov ah,40h
 int 21h
 ret
clean5: mov ax,column
 cwd
 mov cx,8
 idiv cx
 sub cx,dx
 add column,cx
clean55: push cx
 mov al,20h
 call put_char
 pop cx
 loop clean55
 jmp clean3
clean6: call put_char
 ret
clean endp

get_char proc near
 mov bx,stdin
 mov cx,1
 mov dx,offset input_buffer
 mov ah,3fh
 int 21h
 or ax,ax
 jz get_char1
 mov al,input_buffer
 ret
get_char1: mov al,eof; ret
get_char endp

put_char proc near
 mov output_buffer,al
 mov bx,stdout
 mov cx,1
 mov dx,offset output_buffer
 mov ah,40h
 int 21h
 cmp ax,1
 jne put_char1
 clc; ret
put_char1: stc; ret
put_char endp

input_buffer db 0
output_buffer db 0
column dw 0
err_msg db cr,lf,'clean: Disk is full.',cr,lf
err_msg_len equ (this byte)-(offset err_msg)
cseg ends
end clean

關鍵流程解析

  1. 主迴圈 clean3:呼叫 get_char → 去高位 (AND 7Fh) → 分類處理 → put_char → 檢查 CY (磁碟滿) → 循環。
  2. get_char:INT 21h AH=3Fh, BX=0 (STDIN), CX=1 讀 1 位元組。若 AX=0 (EOF) 返回 EOF (1Ah)。
  3. put_char:INT 21h AH=40h, BX=1 (STDOUT), CX=1 寫 1 位元組。成功清 CY,失敗置 CY。
  4. Tab 展開:同 CLEAN,以 column 追蹤欄位,補空白至 8 的倍數。
  5. 控制碼保留:CR(0Dh)/LF(0Ah)/FF(0Ch) 寫入並歸零 column;其他控制碼捨棄。
  6. 錯誤處理:put_char 失敗 (磁碟滿) → 寫入 STDERR (BX=2) → 返回 DOS。

管道重導向實例

C:\> type source.txt | cleanf > filtered.txt
C:\> cleanf < source.txt > filtered.txt
C:\> dir | cleanf | more

父進程 (CMD/COMMAND.COM) 建立管道,將左側程式 STDOUT 接管道寫端,右側程式 STDIN 接管道讀端。CLEANF 完全不知情,只操作標準控制代碼 0/1/2。

現代對應與啟發

CLEANF 概念現代對應
標準串流過濾器Unix stdin/stdout/stderr、Windows 控制台控制代碼、System.Console
管道組合Shell 管道 |、PowerShell 管道、subprocess.Popen、Node.js stream.pipe
單字元無緩衝 I/O非緩衝 I/O、read(STDIN_FILENO, &c, 1)、getchar()
錯誤輸出分離stderr 重導向、日誌框架、log.Error()
最小化依賴單一職責原則、微服務、Unix 哲學

學習重點

  • DOS 2.0 繼承控制代碼機制:子進程自動擁有父進程的 0/1/2/3/4
  • 標準串流過濾器架構:不開啟檔案、不解析檔名、只處理串流
  • 極簡錯誤處理:CY 旗標傳遞、STDERR 輸出、立即退出
  • 字元級處理迴圈:get_char → filter → put_char 管線模式
  • .COM 程式結構:ORG 100h、PUSH DS; XOR AX,AX; PUSH AX 返回 DOS

總結

CLEANF.ASM 是管道過濾器模式在 DOS 組合語言的純粹實現:100 行、零檔案操作、零命令列解析、專注字元轉換。它證明了「小而美、可組合、標準介面」的設計哲學在 1980 年代的 16 位實模式下同樣成立。今日我們在微服務、Serverless、資料管線中談論的「單一職責、標準輸入輸出、可組合性」,其靈魂早已在這段精簡代碼中完美呈現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved