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

CleanDoc 1.2:組合語言實作的「開始功能表文件」清理工具

     編輯:組合語言

前言:DOS 時代的系統維護小工具

Windows 9x 將「最近使用文件」捷徑儲存在 Windows\Recent 目錄。隨時間增長,此目錄會佔用大量磁碟空間並拖慢開始功能表開啟速度。CleanDoc 1.2 是一個極精簡 (僅約 1KB) 的 DOS 組合語言程式,專門清空此目錄。它展示了:環境變數查找 (CLEANDIR)、目錄切換、檔案枚舉 (INT 21h, 4Eh/4Fh)、檔案刪除 (INT 21h, 41h Unlink)、錯誤處理與資源恢復等核心檔案系統操作技巧。

程式架構與流程

  1. 初始化:設定 DTA (Disk Transfer Area)、取得當前磁碟機與完整路徑 (INT 21h, 47h) 保存以便最後恢復。
  2. 環境變數檢查:掃描 PSP 環境區塊 (ES:[2Ch]) 尋找 CLEANDIR=路徑。找到則切換至該目錄;否則使用預設 Windows\Recent (相對當前磁碟機)。
  3. 刪除迴圈:FindFirst (4Eh, *.* ) → Unlink (41h) 刪除 → FindNext (4Fh) 直到無檔案。
  4. 恢復與結束:切回原始目錄,INT 21h, 4C00h 退出。

關鍵技術細節

1. 環境變數區掃描 (GETENV)

push es
push ds
mov es, [es:2Ch]   ; ES 指向環境區段 (段落對齊)
xor di, di
floop:
cmp byte [es:di], 0
jne goon
cmp byte [es:di+1], 0  ; 雙重 0 = 環境區結束
je eout
goon:
equal: ... 逐字元比對 "CLEANDIR" ...
sign: inc di ; 略過 '='
mov ax, es
mov ds, ax
mov si, di
mov bx, si
mov dx, bx
mov ah, 3Bh       ; CHDIR 至找到的路徑
int 21h
jnc envok
mov dx, 0         ; 失敗則用預設
eout:
pop ds
pop es
ret

環境區結構:VAR=VALUE\0 VAR2=VALUE2\0 ... \0\0 (雙重 0 結束)。程式手工實作字串比對,無 CMPSB / SCASB,展示極簡邏輯。

2. 檔案枚舉與刪除 (FINDFILE/DELIT)

findfile:
mov ah, 4Eh       ; Find First
mov cx, 0Fh       ; 所有屬性 (含隱藏/系統/唯讀/子目錄)
mov dx, files     ; "*.*"
int 21h
jnc delit
jmp goback        ; 無檔案或錯誤
found:
mov dx, files
mov ah, 4Fh       ; Find Next
int 21h
jc goback
delit:
mov ah, 41h       ; Unlink (刪除)
mov dx, mydta
add dx, 30        ; DTA+30h = 檔名欄位
int 21h
jnc found         ; 成功繼續下一個
; 失敗處理:顯示錯誤訊息、檔名、換行
mov bx, errt2
call write
mov bx, mydta
add bx, 30
call write
mov bx, linefeed
jmp errout

DTA 結構 (標準 43 位元組) 中,偏移 1Eh (30) 起為 ASCIIZ 檔名。Unlink 直接刪除,不進回收桶 (DOS 無此機制)。

3. 字串輸出子程式 (WRITE)

write:
pusha
mov si, bx
mov cx, 0
wloop:
lodsb
cmp al, 0
je lwrite
inc cx
jmp wloop
lwrite:
mov dx, bx
mov bx, 1         ; StdOut Handle
mov ah, 40h       ; Write File/Device
int 21h
popa
ret

使用 INT 21h, AH=40h (Handle 寫入) 而非 AH=09h (字串列印),支援任意長度、無需 $ 結尾,更通用。

4. 錯誤處理與資源恢復

所有錯誤路徑均透過 errout 顯示訊息,再跳 quit:xor eax,eax / mov ax,4C00h / int 21h。確保目錄切換失敗、刪除失敗時能優雅退出。

完整原始碼 (NASM 語法)

[BITS 16]
[ORG 100h]
kbd equ 16h
msdos equ 21h
... (等價定義) ...
main:
mov ah, 1Ah ; Set DTA
mov dx, mydta
int msdos
mov ah, 19h ; Get default drive
int msdos
add al, 41h
mov byte [curdir], al
mov byte [path], al
mov word [curdir+1], ":"
mov si, curdir
add si, 3
mov ah, 47h ; Get current dir
mov dl, 0
int msdos
jnc diskok
mov bx, errt0
jmp errout
diskok:
call getenv
cmp dx, -1
je findfile
mov dx, path
mov ah, 3Bh
int msdos
jnc findfile
mov bx, errt1
jmp errout
findfile:
mov ah, 4Eh
mov cx, 0Fh
mov dx, files
int msdos
jnc delit
jmp goback
found:
mov dx, files
mov ah, 4Fh
int msdos
jc goback
delit:
mov ah, 41h
mov dx, mydta
add dx, 30
int msdos
jnc found
mov bx, errt2
call write
mov bx, mydta
add bx, 30
call write
mov bx, linefeed
jmp errout
goback:
mov ah, 3Bh
mov dx, curdir
int msdos
jnc quit
mov bx, errt1
errout: call write
quit:
xor eax, eax
mov ax, 4C00h
int msdos
... (getenv, write 子程式) ...
comseg: dw 0
extseg: dw 0
utext: db "CleanDoc V1.2 (C) 1997 RonSoft",13,10,0
errt0: db "Could not find current directory !",13,10,0
errt1: db "Directory not found.",13,10,0
errt2: db "Could not delete ",0
path: db " :WINDOWS\RECENT",0
files: db "*.*",0
linefeed: db 13,10,0
mydta times 128 db 0
curdir times 68 db 0
END

教學價值與現代映照

  • 環境變數解析:手工掃描 PSP:2Ch 環境區,理解 Windows 將環境變數以區塊形式傳遞給子程序的機制。
  • DTA 管理:INT 21h, 1Ah 設定自訂 DTA 緩衝區,避免覆寫系統預設 DTA (PSP:80h),多執行緒/TSR 程式的必備技巧。
  • 檔案系統 API:FindFirst/FindNext/Unlink/ChDir/GetCurDir 組合完成目錄樹操作,現代 FindFirstFile/FindNextFile/DeleteFile/SetCurrentDirectory 的直接前身。
  • 極簡程式設計:無執行期庫、無堆疊框架、手工字串處理、ORG 100h COM 格式,最終產出 < 1KB 可執行檔,展現組合語言在資源受限環境的極致優勢。

CleanDoc 雖小,五臟俱全。它以組合語言實作了完整的「掃描 → 過濾 → 刪除 → 報告」檔案維護流程,是學習 DOS 檔案系統 API、環境區操作、錯誤處理流程控制的極佳實戰範例。

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