利用 PE 格式的 Stub 機制:同一個 EXE 檔案在 DOS 下執行 Stub 代碼,在 Windows 下執行 PE 主程式。本程式實現兩套邏輯:
INT 21h/30h 獲取 DOS 版本,並透過檢查中斷向量 INT 08h、INT 43h 的偏移地址識別具體 DOS 產品(MS-DOS 7.0/7.1、UCDOS、PDOS95 等)GetVersionEx API 獲取詳細版本資訊(平台 ID、主/次版本號、建置號、CSD 版本)os_type.asm)MOV AH, 30H
INT 21H ; AL=主版本, AH=次版本
; 轉換為 ASCII 顯示
MOV AX, 3508H
INT 21H ; 獲取 INT 08h 向量 -> ES:BX
CMP BX, 1FH ; MS-DOS 7.00
JE @END
CMP BX, 18DEH ; MS-DOS 7.10
JE @END
CMP BX, 1AEBH ; UCDOS 98
JE @REPORT_UCDOS98
CMP BX, 1AF3H ; UCDOS
JE @REPORT_UCDOS
CMP BX, 0A50H ; PDOS95
JE @REPORT_PDOS95
; ... 顯示對應字串
關鍵子程式 bin2dec:將 AH 中的二進制版本號轉為十進制 ASCII 字串(除 10 取餘疊代)。
StubDemo.asm).386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
szMsgBoxTitle db '當前作業系統',0
szWin31 db 'Windows 3.1',0
szWin9x db 'Windows 95',0
szWinNT db 'Windows NT',0
szFormat db '%lu.%lu.%lu',0
szFail db '取得作業系統資訊失敗!',0
.data?
OsVer OSVERSIONINFO <>
szOsVerInfo db 255 dup(?)
szOsVerInfoTmp db 255 dup(?)
.code
start:
MOV OsVer.dwOSVersionInfoSize, SIZEOF OSVERSIONINFO
INVOKE GetVersionEx, ADDR OsVer
.IF EAX
MOV EAX, OsVer.dwPlatformId
.IF EAX == VER_PLATFORM_WIN32s
MOV ESI, OFFSET szWin31
AND OsVer.dwBuildNumber, 0FFFFH
.ELSEIF EAX == VER_PLATFORM_WIN32_WINDOWS
MOV ESI, OFFSET szWin9x
AND OsVer.dwBuildNumber, 0FFFFH
.ELSE
MOV ESI, OFFSET szWinNT
.ENDIF
INVOKE lstrcpy, ADDR szOsVerInfo, ESI
INVOKE wsprintf, ADDR szOsVerInfoTmp, ADDR szFormat, \
OsVer.dwMajorVersion, OsVer.dwMinorVersion, OsVer.dwBuildNumber
INVOKE lstrcat, ADDR szOsVerInfo, ADDR szOsVerInfoTmp
INVOKE lstrcat, ADDR szOsVerInfo, ADDR OsVer.szCSDVersion
MOV EDI, OFFSET szOsVerInfo
MOV ESI, MB_OK OR MB_ICONINFORMATION
.ELSE
MOV EDI, OFFSET szFail
MOV ESI, MB_OK OR MB_ICONWARNING
.ENDIF
INVOKE MessageBox, NULL, EDI, ADDR szMsgBoxTitle, ESI
INVOKE ExitProcess, NULL
END start
; 1. 編譯 DOS Stub
tasm os_type.asm
tlink os_type.obj
exe2bin os_type.exe stub.exe ; 轉為 .COM 格式作為 Stub
; 2. 編譯 Windows 主程式
ml /c /coff StubDemo.asm
link /subsystem:windows /stub:stub.exe StubDemo.obj
執行生成的 StubDemo.exe:
INT 08h/43h 向量地址固定,作為可靠指紋UseStack、bDetailInfo 控制堆疊段與顯示詳略/STUB 選項無縫融合兩套代碼此範例展示了組合語言在底層系統資訊獲取與跨環境相容性上的獨特優勢,是學習混合模式程式設計的經典教材。