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

GETSPACE:BASIC 呼叫組合語言查詢磁碟剩餘空間

     編輯:組合語言

前言:早期 BASIC 擴充系統功能的標準範式

解釋型/編譯型 BASIC (GW-BASIC, QuickBASIC) 內建指令有限,無法直接查詢磁碟剩餘空間。GETSPACE.ASM 實作一個 FAR PROC 供 BASIC 以 CALL GETSPACE(ah, al, bh, bl, ch, cl) 呼叫 (6 個整數參數傳址),內部呼叫 INT 21h, AH=36h 取得磁碟資訊,將結果回填至參數變數。程式展示了 BASIC 參數傳址慣例 (String Descriptor 結構)、DOS 磁碟空間查詢、十六進位轉十進位 ASCII 字串、結果回填等完整流程。

BASIC 參數傳遞機制

BASIC 傳遞 **變數描述子** 位址 (非直接值)。整數變數描述子結構:

; SS:[BP+6] 參數 1 (CL) 描述子位址
; 描述子結構: [類型標誌:WORD][資料位址:DWORD] (近指標模式下段值隱含在 DS)
; 實際資料位址 = DS:[描述子+2]

程式以 MOV BX, [BP+6] / MOV DI, [BX+2] 取得參數變數在 BASIC 資料區的位址 (DI),再 MOV ES:[DI], AX 寫入結果。

核心流程

  1. 建立資料區定址:PUSH DS/ES / MOV AX, datarea / MOV DS, AX 切換至本地資料段。
  2. 取得驅動器代號:從參數 6 (CL) 讀取驅動器號 (0=預設, 1=A, 2=B...),存入 DL。
  3. 呼叫 DOS 36h:MOV AH, 36h / INT 21h,回傳:
    • AX = 每叢集扇區數 (0xFFFF = 錯誤)
    • BX = 可用叢集數
    • CX = 每扇區位元組數
    • DX = 總叢集數
  4. 結果封裝回參數:將 AH, AL, BH, BL, CH, CL 分別存入對應參數位址 (低位元組)。
  5. 十六進位轉十進位字串 (HEXTODEC):對 DX:AX (32 位元無號整數) 反覆除以 10,餘數轉 ASCII 存入參數 1 緩衝區 (預設 8 字元空白預填)。
  6. 恢復段暫存器並返回:POP ES/DS/BP / RET 12 (清除 6 個參數,每個 2 位元組)。

關鍵程式碼片段

1. 參數存取與 DOS 呼叫

push bp
sub ax, ax
mov si, ss:[bp+6]      ; 參數 6 (CL) 描述子位址
mov al, es:[si]        ; 取得驅動器代號
mov dx, ax             ; DL = 驅動器
mov ah, 36h            ; Get Free Space
int 21h

2. 結果拆解至區域變數

xchg dx, ax
sub ax, ax
xchg dx, ax            ; DX=0, AX=原 AX (扇區/叢集)
mov dl, ah
mov ah_ret, dx         ; AH
mov dl, al
mov al_ret, dx         ; AL
mov dl, bh
mov bh_ret, dx         ; BH
mov dl, bl
mov bl_ret, dx         ; BL
mov dl, ch
mov ch_ret, dx         ; CH
mov dl, cl
mov cl_ret, dx         ; CL

3. 回填參數 (逆序對應 BASIC 堆疊順序)

mov ax, cl_ret
mov si, ss:[bp+6]
mov es:[si], ax        ; 回填 CL
mov ax, ch_ret
mov si, ss:[bp+8]
mov es:[si], ax        ; 回填 CH
... (BL, BH, AL, AH 同理) ...

4. HEXTODEC: 32 位元無號整數轉十進位 ASCII

HEXTODEC:
mov si, 10
push ax
mov ax, dx
xor dx, dx
div si                 ; DX:AX / 10 → AX=商, DX=餘數
pop cx
push ax
mov ax, cx
div si
pop si
or dl, 30h             ; 餘數轉 ASCII
mov byte ptr [di], dl
dec di
xchg dx, si
or ax, ax
jnz HEXTODEC

巧妙利用 SI 暫存除數 10,CX 暫存高位商,交替處理高低 16 位,實現 32 位除法 (8086 無 32 位除法指令)。

完整原始碼

get_spa equ 36h
doscall equ 21h
dgroup group datarea
datarea segment para public 'DATA'
ah_ret dw ?
al_ret dw ?
bh_ret dw ?
bl_ret dw ?
ch_ret dw ?
cl_ret dw ?
datarea ENDS
cseg segment 'CODE'
assume cs:cseg
public frespace
frespace proc far
push bp
mov bp,sp
push ds
push es
mov ax,datarea
mov ds,ax
assume ds:datarea
push bp
sub ax,ax
mov si,ss:[bp+6]
mov al,es:[si]
mov dx,ax
mov ah,get_spa
int doscall
xchg dx,ax
sub ax,ax
xchg dx,ax
mov dl,ah
mov ah_ret,dx
mov dl,al
mov al_ret,dx
mov dl,bh
mov bh_ret,dx
mov dl,bl
mov bl_ret,dx
mov dl,ch
mov ch_ret,dx
mov dl,cl
mov cl_ret,dx
pop bp
mov ax,cl_ret
mov si,ss:[bp+6]
mov es:[si],ax
mov ax,ch_ret
mov si,ss:[bp+8]
mov es:[si],ax
mov ax,bl_ret
mov si,ss:[bp+10]
mov es:[si],ax
mov ax,bh_ret
mov si,ss:[bp+12]
mov es:[si],ax
mov ax,al_ret
mov si,ss:[bp+14]
mov es:[si],ax
mov ax,ah_ret
mov si,ss:[bp+16]
mov es:[si],ax
pop es
pop ds
pop bp
ret 12
frespace endp
cseg ends
end

教學價值

  • BASIC 變數描述子結構:理解早期 BASIC 執行期如何管理變數 (類型、位址、長度),為逆向工程 BASIC 程式、撰寫擴充函式庫奠基。
  • DOS 36h 功能詳解:取得磁碟幾何資訊 (扇區/叢集/位元組) 的標準 API,現代 GetDiskFreeSpace 的前身。
  • 32 位元除法軟體實作:HEXTODEC 以 16 位元 DIV 指令模擬 32 位元除法,展示無硬體支援時的多精度運算技巧。
  • 參數回填順序:BASIC 堆疊參數右至左,組合語言需逆序回填 (最後參數最先處理),否則資料錯位。
  • 段暫存器切換與恢復:PUSH DS/ES / MOV DS, 本地段 / ... / POP ES/DS 確保不污染 BASIC 執行期環境。

GETSPACE 以約 100 行程式碼,完整串聯「高階語言介面 → 參數解析 → 系統呼叫 → 多精度運算 → 結果編碼 → 參數回填 → 環境恢復」全鏈路,是學習 DOS 時代混合語言程式設計、系統服務封裝的經典教材。

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