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

FREESPACE:組合語言實作的磁碟剩餘空間查詢工具

     編輯:組合語言

前言:DOS 系統管理的基礎查詢 — 磁碟空間

在無圖形介面的 DOS 環境,查詢磁碟剩餘空間是批次檔、安裝程式、備份工具的常見需求。FREESPACE.ASM (Ray Duncan, 1984) 實作一個獨立 `.COM` 程式:接受命令列參數指定磁碟機 (如 `FREESPACE C:`),呼叫 INT 21h, AH=36h 取得幾何資訊,計算並以位元組為單位顯示剩餘空間。程式展示了命令列解析、DOS 版本檢查、32 位元無號除法、二進位轉十進位 ASCII、錯誤處理等核心系統工具技巧。

程式流程

  1. 版本檢查:INT 21h, AH=30h 取得 DOS 版本,需 ≥ 2.0 (支援 36h)。
  2. 取得磁碟機代號:解析 PSP 預設 FCB (PSP:5Ch) 的驅動器欄位;若為 0 (預設) 則呼叫 INT 21h, AH=19h 取得當前磁碟機。
  3. 查詢磁碟空間:INT 21h, AH=36h, DL=驅動器代號,回傳:
    • AX = 每叢集扇區數
    • BX = 可用叢集數
    • CX = 每扇區位元組數
    • DX = 總叢集數
    • AX = -1 (0xFFFF) 表示無效驅動器
  4. 計算剩餘位元組數:FreeBytes = AX * CX * BX (扇區/叢集 × 位元組/扇區 × 可用叢集)。以 32 位元無號整數 (DX:AX) 儲存結果。
  5. 轉換為十進位字串並輸出:呼叫 bin_to_asc 將 DX:AX 轉 ASCII,填入輸出緩衝區,INT 21h, AH=09h 列印。

關鍵演算法:32 位元除法與 ASCII 轉換

1. 通用 32 位元除法

divide 子程式實現 DX:AX / CX → DX:AX = 商, BX = 餘數:

divide proc near
 jcxz div1           ; 除數為 0 → 直接返回
 push ax             ; 保存低 16 位
 mov ax, dx          ; 高 16 位 → AX
 xor dx, dx
 div cx              ; DX:AX / CX → AX=商1, DX=餘1
 mov bx, ax          ; BX = 商1
 pop ax              ; 恢復低 16 位
 div cx              ; 餘1:AX / CX → AX=商2, DX=餘2
 xchg bx, dx         ; DX:AX = 商1:商2, BX = 餘2
div1: ret

利用兩次 16 位元除法合成 32 位元除法,避免商溢位 (如 100,000 / 2)。

2. 二進位轉十進位 ASCII (bin_to_asc)

bin_to_asc proc near
 mov byte ptr [si], '0'  ; 至少輸出一位
 or dx, dx
 pushf                   ; 保存符號
 jns bin1
 not dx                  ; 負數 → 取二補數
 not ax
 add ax, 1
 adc dx, 0
bin1:
 mov bx, ax
 or bx, dx
 jz bin3                 ; 值為 0 → 結束
 call divide             ; 除以基數 (CX=10)
 add bl, '0'             ; 餘數轉 ASCII
 cmp bl, '9'
 jle bin2
 add bl, 'A'-'9'-1       ; 支援 16 進位 (A-F)
bin2:
 mov [si], bl
 dec si
 jmp bin1
bin3:
 popf
 jns bin4
 mov byte ptr [si], '-'  ; 負號
bin4: ret

支援有號 32 位元整數、任意基數 (預設 10)、最小寬度保證、緩衝區反向填充 (SI 從尾部遞減)。

完整原始碼

name free
page 60,132
title 'FREE --- Report free space on disk'
cr equ 0dh
lf equ 0ah
blank equ 20h
eom equ '$'
psp segment para public 'PSP'
org 05ch
fcb label byte
org 080h
command label byte
psp ends
cseg segment para public 'CODE'
assume cs:cseg,ds:psp,es:data,ss:stack
get_drive proc near
mov al, fcb
or al, al
jnz get_drive1
mov ah, 19h
int 21h
inc al
get_drive1: ret
get_drive endp
free proc far
push ds
xor ax, ax
push ax
mov ax, data
mov es, ax
mov ah, 30h
int 21h
cmp al, 2
jae free1
mov dx, offset msg2
mov ax, es
mov ds, ax
jmp free4
free1: call get_drive
push es
pop ds
assume ds:data
mov dl, al
add al, 'A'-1
mov outputb, al
mov ah, 36h
int 21h
cmp ax, -1
je free3
mul cx
mul bx
mov si, offset (outputa+9)
mov cx, 10
call bin_to_asc
mov dx, offset output
jmp free4
free3: mov dx, offset msg1
free4: mov ah, 9
int 21h
ret
free endp
bin_to_asc proc near ... endp
divide proc near ... endp
cseg ends
data segment para public 'DATA'
output db cr,lf
outputa db 10 dup (blank)
db ' bytes free on drive '
outputb db 'x:',cr,lf,eom
msg1 db cr,lf,'That disk drive does not exist.',cr,lf,eom
msg2 db cr,lf,'Requires DOS version 2 or greater.',cr,lf,eom
data ends
stack segment para stack 'STACK'
db 64 dup (?)\n />stack ends\n />end free

教學價值

  • 命令列參數解析:透過 PSP FCB 結構 (PSP:5Ch) 取得驅動器代號,兼容 `FREESPACE` (無參數→當前磁碟) 與 `FREESPACE C:` 兩種用法。
  • DOS 版本檢查:INT 21h, AH=30h 確保 API 可用性,良好的相容性實踐。
  • 32 位元算術軟體實作:divide 以雙重 16 位除法合成 32 位除法,bin_to_asc 反覆呼叫其轉換進制 — 8086 無 32 位乘除指令時的標準技巧。
  • 緩衝區反向填充:SI 從字串尾部遞減,避免需先計算位數再正向寫入,簡化邏輯。
  • 錯誤處理集中化:所有錯誤路徑匯聚至 free4 列印訊息並退出,結構清晰。

FREE.ASM 以約 150 行程式碼,實作了專業級磁碟空間查詢工具,其「參數解析 → 系統查詢 → 多精度計算 → 格式化輸出 → 錯誤處理」完整流程,是 DOS 系統工具開發的教科書級範例,亦為現代 CLI 工具開發 (參數解析、系統呼叫、單位轉換、人類可讀輸出) 提供永恆的設計參考。

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