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

HDR:MS-DOS 區塊/字元裝置驅動程式標頭與策略/中斷常式框架

     編輯:組合語言

前言:DOS 裝置驅動程式的骨架 — 請求標頭、策略常式、中斷常式

MS-DOS 裝置驅動程式 (`.SYS` 檔) 採用獨特架構:系統透過 **請求標頭 (Request Header)** 傳遞命令,驅動程式提供 **策略常式 (Strategy)** 暫存請求標頭位址,與 **中斷常式 (Interrupt)** 處理實際命令。HDR.ASM (Frank Whaley, 1985) 定義了完整的驅動程式標頭結構、請求標頭模板、策略/中斷常式框架、命令分派表、本地堆疊管理,是撰寫區塊/字元裝置驅動程式的標準範本。

驅動程式標頭結構 (位於檔案開頭, ORG 0)

HDR Proc Far
 DD -1              ; 指向下一個驅動程式 (-1 = 串列結尾)
 DW 8000H           ; 屬性字: Bit 15=1 字元裝置
 DW Strategy        ; 策略常式入口
 DW Interrupt       ; 中斷常式入口
 DB "MON  "         ; 裝置名稱 (8 位元組, 字元裝置)
HDR EndP

屬性字關鍵位:Bit 15=字元/區塊, Bit 14=支援 IOCTL, Bit 13=非 IBM 格式 (區塊), Bit 11=支援 Open/Close/Removable (DOS 3+), Bit 3=Clock, Bit 2=NUL, Bit 1=StdOut, Bit 0=StdIn。

策略常式: 暫存請求標頭指標

DOS 先呼叫 Strategy,將請求標頭位址傳入 ES:BX。Strategy 僅複製指標至本地變數 RHptr,並保存所有暫存器:

Strategy:
 MOV Word Ptr CS:RHptr, BX
 MOV Word Ptr CS:RHptr+2, ES
 PUSHF
 PUSH ES, DS, SI, DI, CX, BX
 MOV SI, BX
 MOV BX, ES
 MOV DS, BX           ; DS:SI -> 請求標頭
 MOV BX, Offset PGROUP:TAIL
 MOV CL, 4
 SHR BX, CL
 MOV CX, CS
 ADD BX, CX
 MOV ES, BX           ; ES = 資料段段值
 MOV DI, Offset DGROUP:ReqHdr
 CLD
 XOR CH, CH
 MOV CL, [SI]         ; 請求標頭長度
 REP MOVSB            ; 複製至本地 ReqHdr 緩衝區
 POP BX, CX, DI, SI, DS, ES
 POPF
 RET

關鍵點:REP MOVSB 複製整個請求標頭至本地資料區 ReqHdr,後續中斷常式直接操作此副本,避免競態條件。

中斷常式: 命令分派與執行

Interrupt 以 ReqHdr+2 (命令碼) 索引分派表 FuncTab,呼叫對應處理常式:

Interrupt:
 PUSH DS, ES, AX, BX, CX, DX, SI, DI, BP
 MOV CS:ssEntry, SS
 MOV CS:spEntry, SP
 ; 切換至本地堆疊 (TAIL 段末尾)
 MOV AX, Offset PGROUP:TAIL
 SHR AX, CL
 ADD AX, CS
 MOV BX, Offset DGROUP:MyStack
 MOV DS, AX, ES, AX, SS, AX
 MOV SP, BX, BP, BX
 ; 分派
 MOV AL, ReqHdr+2
 SHL AL, 1
 CBW
 MOV SI, Offset DGROUP:FuncTab
 ADD SI, AX
 CALL Word Ptr [SI]
 ; 複製回原請求標頭
 LES DI, RHptr
 MOV SI, Offset DGROUP:ReqHdr
 MOV CL, [SI]
 REP MOVSB
 ; 恢復堆疊與暫存器
 MOV SS, CS:ssEntry
 MOV SP, CS:spEntry
 POP BP, DI, SI, DX, CX, BX, AX, ES, DS
 RET

命令分派表

FuncTab Label Word
 DW Offset PGROUP:Init          ; 0  初始化
 DW Offset PGROUP:MediaChe      ; 1  媒體檢查 (區塊)
 DW Offset PGROUP:BuildBPB      ; 2  建立 BPB (區塊)
 DW Offset PGROUP:IoCtlIn       ; 3  IOCTL 輸入
 DW Offset PGROUP:Input         ; 4  讀取
 DW Offset PGROUP:ndInput       ; 5  非破壞性讀取
 DW Offset PGROUP:InputSta      ; 6  輸入狀態
 DW Offset PGROUP:InputFlu      ; 7  清空輸入緩衝
 DW Offset PGROUP:Output        ; 8  寫入
 DW Offset PGROUP:OutVerif      ; 9  寫入並驗證
 DW Offset PGROUP:OutStatu      ; 10 輸出狀態
 DW Offset PGROUP:OutFlush      ; 11 清空輸出緩衝
 DW Offset PGROUP:IoCtlOut      ; 12 IOCTL 輸出
 DW Offset PGROUP:DevOpen       ; 13 開啟裝置 (DOS 3+)
 DW Offset PGROUP:DevClose      ; 14 關閉裝置 (DOS 3+)
 DW Offset PGROUP:RemMedia      ; 15 可移動媒體 (DOS 3+)

請求標頭結構定義 (Request Struc)

Request struc
Rlength db ?          ; 標頭長度
Unit db ?             ; 單元號
Command db ?          ; 命令碼
Status dw ?           ; 回傳狀態字
Reserve db 8 dup (?)  ; 保留
Media db ?            ; 媒體描述符
Address dd ?          ; 傳輸緩衝區位址
Count dw ?            ; 位元組/扇區計數
Sector dw ?           ; 起始扇區
Request ends

狀態字:Bit 15=錯誤, Bit 9=忙碌, Bit 8=完成, Bit 0-7=錯誤碼 (0=寫保護, 1=未知單元, 2=未就緒, 3=未知命令, 4=CRC, 5=錯誤長度, 6=尋找錯誤, 7=未知媒體, 8=扇區未找到, 9=缺紙, 10=寫入故障, 11=讀取故障, 12=一般失敗, 15=無效磁碟變更 DOS 3+)。

初始化常式

Init:
 PUSH ES, DI
 MOV AH, 9
 MOV DX, Offset Ident
 INT 21h              ; 列印簽名訊息
 POP DI, ES
 MOV Word Ptr ES:[DI.Address], Offset Init
 MOV Word Ptr ES:[DI.Address+2], CS
 JMP Done             ; 回傳完成狀態,記憶體釋放至 Init 之後

初始化常式列印版權訊息,將首個可用記憶體位址設為 Init 自身位址 (即釋放初始化碼佔用的記憶體),並回傳狀態字 Done (AH=1)。

完整原始碼架構

PGROUP Group PROG, TAIL
DGROUP Group DATA, DTAIL
PROG Segment ... EndS
DATA Segment ... EndS
Assume CS:PROG, DS:DATA, ES:DATA, SS:DATA
PROG Segment
Extrn Init, MediaChe, BuildBPB, ...
ORG 0
HDR Proc Far ... EndP
Strategy ...
Interrupt ...
PROG EndS
TAIL Segment ... EndS
DATA Segment
Public ReqHdr
DB StkSiz Dup (?)
MyStack Label Word
FuncTab ...
ReqHdr DB 256 Dup (?)\n />DATA EndS
DTAIL Segment ... EndS
END HDR

教學價值與現代映照

  • 驅動程式模型:DOS 驅動程式為「無行程上下文」的服務提供者,所有狀態由請求標頭傳遞,策略/中斷分離設計避免重入問題 — 現代 Windows WDM/KMDF 的 `IRP` (I/O Request Packet) + `Dispatch Routines` 架構即源自於此。
  • 請求標頭複製:Strategy 複製至本地緩衝區,Interrupt 再複製回 — 確保原子性、支援多重佇列請求,對應現代 `IRP` 複製/完成機制。
  • 本地堆疊切換:Interrupt 切換至驅動程式私有堆疊 (MyStack),執行完恢復 — 避免破壞呼叫者 (DOS 核心) 堆疊,現代驅動程式同樣擁有私有堆疊。
  • 命令碼分派表:以陣列索引替代巨大 `switch`,效能高、擴展易 — 現代驅動程式 `MajorFunction` 陣列同樣採用此模式。
  • 屬性字/狀態字位定義:標準化錯誤碼與能力協商,奠定裝置驅動程式介面契約基礎。

HDR.ASM 雖為 1985 年產物,其架構哲學 — **請求封裝、無狀態處理、分派表、私有堆疊、屬性協商** — 歷經三十餘年演變,仍清晰可見於 Windows WDM、Linux `file_operations`、FreeBSD `cdevsw`、UEFI Driver Binding Protocol 等現代驅動模型中。研讀此框架代碼,即是窺見作業系統 I/O 子系統設計的基因起源。

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