掌握 Win32 組合語言的第一步,是理解其程式結構與基本語法。不同於 DOS 時代的多種記憶體模型,Win32 採用扁平模式,配合標準呼叫慣例,使程式編寫更為直觀。本文以一個最精簡的彈出訊息框程式為例,逐行解析各指令用途。
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
szCaption db 'Win32組語範例',0
szText db 'Win32組語,簡單而強大!',0
.code
start:
invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK
invoke ExitProcess, NULL
end start
指示組譯器啟用對應處理器指令集。32 位程式需使用 32 位暫存器(EAX, EBX...),故至少需 .386。若用到特權指令,可加 P 後綴(如 .386p)。
以 MessageBox 為例,C 宣告為:
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
組語手動調用需:
push uType
push lpCaption
push lpText
push hWnd
call MessageBox
invoke 巨集自動完成壓棧與參數個數檢查,寫法更簡潔:
invoke MessageBox, hWnd, lpText, lpCaption, uType
windows.inc:所有 Windows 資料結構與常數定義。xxx.inc:對應 DLL 的 API 原型宣告(如 kernel32.inc, user32.inc)。includelib xxx.lib:告知連結器引入對應的匯入庫,解決外部符號。例如 ExitProcess 在 kernel32.dll,故需 include kernel32.inc 與 includelib kernel32.lib;MessageBox 在 user32.dll,同理需引入 user32 相關檔案。
.data:已初始化資料,佔用 EXE 檔案大小。.data?:未初始化資料,僅預留空間,執行時動態分配,不增大檔案體積。適合大型緩衝區。.code 標示代碼段開始。start: 標號指定程式進入點,end start 告知連結器從此處開始執行。
invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK:顯示模態對話框。addr 取得變數位址,NULL 與 MB_OK 定義於 windows.inc。invoke ExitProcess, NULL:標準進程退出,對應 DOS 的 INT 21h/4Ch。Win32 組語結構清晰:指令集聲明 → 記憶體模型與呼叫慣例 → 引入系統定義與庫 → 資料段 → 代碼段與入口點。善用 invoke 可大幅降低 API 呼叫複雜度。掌握此範本,即可著手開發更豐富的 Windows 應用程式。