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

Windows 9x VxD 程式設計入門:靜態/動態載入、控制訊息與服務呼叫完整教學

     編輯:組合語言

前言

承接上篇 LE 格式與架構基礎,本文深入實戰:靜態與動態 VxD 的載入機制、初始化/結束控制訊息處理、函數建構慣例、呼叫慣例與位址運算,助您撰寫可正常運作的 VxD 核心模組。

靜態 VxD 載入與初始化序列

載入觸發條件

  • 實模式 TSR 呼叫 INT 2Fh AX=1605h
  • 登錄檔:HKLM\System\CurrentControlSet\Services\VxD\key\StaticVxD=路徑
  • SYSTEM.INI [386Enh] 區段:device=路徑(開發建議,易於 DOS 下修復)

三階段初始化控制訊息

訊息時機用途處理建議
Sys_Critical_InitVMM 進入保護模式、開啟中斷前搶佔中斷向量、初始化其他 VxD 依賴的服務極速完成,避免硬體中斷遺失
Device_Init中斷已開啟大多數初始化工作(硬體偵測、記憶體配置等)可執行耗時操作
Init_Complete所有 VxD 完成 Device_Init、釋放 ICODE/RCODE 前極少數 VxD 需要(如最終資源檢查)可選處理

回傳值規則:EAX=0 成功;非零 = 錯誤碼 → VMM 終止載入。

結束控制訊息(反初始化順序)

  • System_Exit2:Windows 關機,僅剩系統 VM,CPU 仍在保護模式,Kernel32 已卸載。
  • Sys_Critical_Exit2:中斷關閉後,準備轉實模式。
  • Device_Reboot_Notify2 / Crit_Reboot_Notify2:重開機通知(中斷開啟/關閉)。

「2」尾碼表示反初始化順序發送(先載入的後結束),保證相依服務仍可用。舊版無「2」訊息不保證順序,新版 VxD 應忽略。

動態 VxD:隨需載入的核心擴充

轉換關鍵

; .DEF 檔
VXD MYVXD DYNAMIC   ; 僅加上 DYNAMIC 關鍵字

三種載入管道

  1. \WINDOWS\SYSTEM\IOSUBSYS\:由 IOS 載入,需支援分層驅動,非通用。
  2. VxDLDR 服務:其他 VxD 或 16 位程式碼呼叫。
  3. Win32 CreateFile:最通用,應用程式呼叫 CreateFile("\\.\Path\To\VxD.vxd", ..., FILE_FLAG_DELETE_ON_CLOSE, 0),關閉控制代碼即卸載。

動態 VxD 專屬控制訊息

  • Sys_Dynamic_Device_Init:首次 CreateFile 載入時(取代靜態三階段)。
  • Sys_Dynamic_Device_Exit:最後一個控制代碼關閉時。
  • W32_DeviceIoControl:CreateFile 成功後首次觸發,必須處理並回傳 EAX=0;後續 DeviceIoControl 也送此訊息。

除上述三訊息外,動態 VxD 仍接收所有系統控制訊息(VM 建立/銷毀、電源管理等)。

VxD 內部函數建構規範

段選擇原則

  • 必須常駐(硬體 ISR、共享服務)→ VxD_LOCKED_CODE_SEG
  • 一般功能 → VxD_PAGEABLE_CODE_SEG(預設最佳選擇)

函數定義巨集

VxD_PAGEABLE_CODE_SEG
BeginProc MyFunction
    ; 函數本體
    ; 可加參數:BeginProc MyFunction, CCALL, PUBLIC
EndProc MyFunction
VxD_PAGEABLE_CODE_ENDS
  • BeginProc/EndProc 取代傳統 PROC/ENDP,支援呼叫慣例、參數聲明、堆疊框架自動建構。
  • CCALL:C 呼叫慣例(參數由呼叫者清理堆疊),W32_DeviceIoControl 回呼必須使用。

VxD 程式設計慣例

暫存器使用

  • 可自由使用 EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP。
  • FS, GS 可用但需謹慎。
  • 嚴禁修改 CS, SS,除非完全掌握後果。
  • DS, ES 可用,返回前必須恢復原值。
  • 方向旗標 DF 與中斷旗標 IF:修改後必須恢復,不可長時間關閉中斷。

參數傳遞與服務呼叫

呼叫巨集語法

; 暫存器呼叫
VMMCall Get_Cur_VM_Handle

; 堆疊呼叫(參數用角括號包裹)
VMMCall _HeapAllocate, <<SIZE mybuffer>, HeapLockedIfDP>
; 注意:運算式參數需雙重角括號
  • VMMCall:呼叫 VMM 匯出服務
  • VxDCall:呼叫其他 VxD 匯出服務
  • 兩者皆展開為 INT 20h + 服務序數(雙字)

平坦位址與 OFFSET32

舊版工具 OFFSET 產生錯誤位址,慣用 OFFSET FLAT: 或 OFFSET32 巨集。MASM 6.14+ 已修正,但為相容性建議仍用 OFFSET32。

完整動態 VxD 架構範例

.386p
include vmm.inc
include vwin32.inc

DECLARE_VIRTUAL_DEVICE DYNAVXD, 1, 0, DYNAVXD_Control, \
    UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_Control_Dispatch DYNAVXD
    Control_Dispatch W32_DeviceIoControl, OnDeviceIoControl
End_Control_Dispatch DYNAVXD

VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl, CCALL
    ArgVar RefData, DWORD
    ArgVar TheFlag, DWORD
    EnterProc
    assume esi:ptr DIOCParams
    .if [esi].dwIoControlCode == DIOC_Open
        xor eax, eax          ; 成功
    .endif
    LeaveProc
    Return
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS
end

總結

VxD 開發的關鍵在於:正確選擇靜態/動態模型、在適當的控制訊息中完成初始化/清理、遵循暫存器與呼叫慣例、善用 BeginProc/EndProc 建構健壯函數、掌握 VMMCall/VxDCall 服務呼叫機制。動態 VxD 搭配 CreateFile + DeviceIoControl,為 Win32 應用程式提供了通往 Ring-0 的標準橋樑,是系統級功能擴充的最佳選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型命名特徵參數傳遞回傳值範例
暫存器呼叫無底線開頭暫存器暫存器VMMCall Service
堆疊呼叫底線開頭 _Service堆疊(右→左)EAXVMMCall _Service, <arg1, arg2>