這個 MASM32 範例示範如何在 Win32 組合語言中呼叫登錄 API (RegOpenKeyEx, RegQueryValueEx, RegCloseKey) 讀取 WinRAR 安裝路徑,並用訊息方塊顯示。展示了標準 Win32 程式架構、API 錯誤處理、字串緩衝區管理、巨集簡化資料搬移等實用技巧。
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\advapi32.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
GetRarPath PROTO :LPSTR
m_m2m MACRO d1, d2
push d2
pop d1
ENDM
.386/.model flat,stdcall:32 位元平坦模型,stdcall 慣例option casemap:none:區分大小寫 (windows.inc 要求)m_m2m 巨集:以堆疊中轉實現記憶體到記憶體搬移 (x86 無 MOV mem,mem).data
g_szTitle db "WinRAR路徑", 0
g_szRegPath db "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe", 0
g_szFailRegOpenKeyEx db "RegOpenKeyEx失敗!", 0
g_szFailRegQueryValueEx db "RegQueryValueEx失敗!", 0
g_szValueName db "Path", 0
.data?
g_szRarPath db 256 dup(?)
g_hRegKey4IE HKEY ?
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exePath (預設值為空字串,實際路徑存於預設值)g_szRarPath:256 位元組接收緩衝區start:
invoke GetRarPath, ADDR g_szRarPath
.if eax==1
mov eax, OFFSET g_szFailRegOpenKeyEx
.elseif eax==2
mov eax, OFFSET g_szFailRegQueryValueEx
.else
mov eax, OFFSET g_szRarPath
.endif
invoke MessageBox, NULL, eax, OFFSET g_szTitle, MB_OK
invoke ExitProcess, NULL
使用 MASM 高階語法 .if/.elseif/.else/.endif 處理 GetRarPath 返回碼:1=開啟鍵失敗,2=查詢值失敗,0=成功 (EAX=0)。
GetRarPath PROC lpszRarPath: LPSTR
LOCAL dwcbData: dword
invoke RegOpenKey, HKEY_LOCAL_MACHINE, ADDR g_szRegPath, ADDR g_hRegKey4IE
.if eax!=ERROR_SUCCESS
m_m2m eax, 1
ret
.endif
m_m2m dwcbData, SIZEOF g_szRarPath
invoke RegQueryValueEx, g_hRegKey4IE, ADDR g_szValueName, NULL, NULL, ADDR g_szRarPath, ADDR dwcbData
.if eax!=ERROR_SUCCESS
m_m2m eax, 2
.else
xor eax, eax
.endif
invoke RegCloseKey, g_hRegKey4IE
ret
GetRarPath ENDP
RegOpenKeyEx 簡化版):開啟 HKLM 下指定子鍵,句柄存入 g_hRegKey4IE。失敗返回非 ERROR_SUCCESS (0)。lpValueName = "Path"lpReserved = NULLlpType = NULL (不需類型)lpData = g_szRarPath (輸出緩衝區)lpcbData = &dwcbData (輸入緩衝區大小,輸出實際資料大小)| 技巧 | 說明 |
|---|---|
| m_m2m 巨集 | push/pop 實現 mem-to-mov,避免需經暫存器 |
| LOCAL 區域變數 | dwcbData 自動配置堆疊空間,PROC 結束自動釋放 |
| .if/.else 高階語法 | 編譯器自動產生 CMP/Jcc 指令,提升可讀性 |
| ADDR 操作符 | 取得記憶體位址 (相當於 OFFSET,但支援區域變數) |
| ERROR_SUCCESS 常數 | windows.inc 定義為 0,語意化錯誤檢查 |
| 字串緩衝區大小計算 | SIZEOF g_szRarPath 自動計算 256 |
RegOpenKeyEx 替代舊版 RegOpenKey (支援 samDesired 權限控制)dwcbData 確保資料完整HKCU (使用者層級安裝路徑)RegQueryValueExW) 以支援長路徑/國際字元SHGetFolderPath 等 Shell API 作為備選定位方式這個範例以約 60 行核心程式碼完成 Win32 登錄讀取實戰。它展示了 MASM32 在 Windows 系統程式開發中的實力:完整的 API 覆蓋、高階語法支援、標準庫整合、型別安全。對於需要無運行時依賴、極小體積、直接呼叫系統 API 的場合 (如安裝程式、啟動器、系統工具),MASM32 仍是極具競爭力的選擇。