在早期的 DOS 年代,程式設計師習慣直接操作硬體,透過 int 13h 中斷服務來讀寫磁碟磁區。隨著 Windows 9x/NT 核心架構的建立,應用程式不再擁有 Ring 0 的最高執行權限,直接呼叫 BIOS 中斷成為歷史。本文將深入探討如何在 Windows 環境下,透過 DeviceIoControl 與 VWIN32 虛擬裝置驅動程式(VxD)橋接,實現對磁碟第 0 軌第 1 磁區(啟動磁區)的讀取、寫入與格式化操作。
在 16 位元的 DOS 環境中,程式碼簡潔直接:
char buffer[512];
reg.x.dx = 0; // 磁碟機 A:
reg.x.cx = 0x0001; // 柱面 0,磁區 1(啟動磁區)
reg.x.bx = fp_off(buffer); // 緩衝區偏移
sreg.es = fp_seg(buffer); // 緩衝區段地址
reg.x.ax = 0x0201; // AH=02h 讀取,AL=01h 磁區數
int86x(0x13, ®, ®, &sreg); // 呼叫 BIOS int 13h
這段程式碼直接操作暫存器,將控制權交給 BIOS,完成實體磁碟存取。然而,這在受保護模式的 Windows 下已不可行。
Windows 9x 提供了 \\.\VWIN32 裝置介面,允許 Ring 3 的應用程式透過 DeviceIoControl 發送模擬的 int 21h 或 int 13h 請求給 VxD 執行。核心在於定義一個對應 CPU 暫存器的結構體:
#pragma pack(push, 1)
struct DIOC_REGISTERS {
DWORD reg_ebx;
DWORD reg_edx;
DWORD reg_ecx;
DWORD reg_eax;
DWORD reg_edi;
DWORD reg_esi;
DWORD reg_flags;
};
#pragma pack(pop)
CreateFile("\\\\.\\VWIN32", ...) 取得裝置控制代碼。AX=0x0000 的 int 13h 重設命令。AX=0x0C00 的尋軌命令,CX 指定柱面/磁區,DX 指定磁頭/磁碟機。AX=0x0201(讀取)或 0x0301(寫入),EBX 指向資料緩衝區。// 開啟裝置
hDevice = CreateFile("\\\\.\\VWIN32", 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL);
// 1. 重設軟碟機
reg.reg_eax = 0x0000;
reg.reg_edx = driveNumber;
reg.reg_flags = 0x0001; // 預設 carry flag 為錯誤
DeviceIoControl(hDevice, VWIN32_DIOC_DOS_INT13, ®, sizeof(reg), ®, sizeof(reg), &cb, 0);
// 2. 尋軌
reg.reg_eax = 0x0C00;
reg.reg_ecx = (cylinder << 8) | sector;
reg.reg_edx = (head << 8) | driveNumber;
DeviceIoControl(hDevice, VWIN32_DIOC_DOS_INT13, ®, sizeof(reg), ®, sizeof(reg), &cb, 0);
// 3. 讀取啟動磁區
reg.reg_eax = 0x0201;
reg.reg_ebx = (DWORD)&buffer;
DeviceIoControl(hDevice, VWIN32_DIOC_DOS_INT13, ®, sizeof(reg), ®, sizeof(reg), &cb, 0);
if (!dwResult || (reg.reg_flags & 0x0001)) {
// 處理錯誤:carry flag 為 1 表示失敗
}
\\.\PhysicalDriveX 或 \\.\VWIN32 通常需要系統管理員權限。IOCTL_DISK_READ/WRITE 直接對實體磁碟操作。reg_flags 中的 Carry Flag (bit 0) 為 1 代表操作失敗,AH (reg_eax 高位元組) 會包含 BIOS 錯誤碼。從 DOS 的 int 13h 到 Windows 的 DeviceIoControl + VWIN32,核心邏輯未變——設定暫存器參數、發送中斷命令、檢查狀態旗標——但執行環境從實模式移植到虛擬 86 模式監控下。理解這層映射關係,不僅有助於維護舊有系統,更能深入掌握作業系統如何虛擬化硬體資源。對於現代 Windows 開發,建議改用 Win32 API (ReadFile/WriteFile 配合 \\.\PhysicalDriveX) 或儲存體管理介面,以獲得更好的相容性與安全性。