Win32 組合語言程式設計常被視為高門檻的領域,但只要掌握核心概念與工具鏈,其實並不困難。本文將以一個最簡單的「Hello World」訊息框程式為例,帶領讀者從原始碼撰寫、編譯連結,一步步優化至符合實務開發的標準架構。
以下是一個最基礎的 Win32 組合語言程式,功能僅是彈出一個訊息框:
; 檔名:3.asm
.386
.model flat, stdcall
NULL equ 0
MB_OK equ 0
ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD, :DWORD, :DWORD, :DWORD
includelib kernel32.lib
includelib user32.lib
.data
szText db "Hello, world!", 0
szCaption db "Win32Asm", 0
.code
start:
push MB_OK
lea eax, szCaption
push eax
lea eax, szText
push eax
push NULL
call MessageBoxA
xor eax, eax
push eax
call ExitProcess
end start
INVOKE 指令時進行參數檢查。kernel32.lib 與 user32.lib,解析 ExitProcess 與 MessageBoxA 的外部符號。push,最後 call。使用 MASM (ml.exe) 與連結器 (link.exe) 分兩階段建置:
ml /c /coff 3.asm
link /subsystem:windows /libpath:d:\masm7\lib 3.obj
/c:僅編譯產生 .obj,不連結。/coff:輸出 COFF 格式目標檔。/subsystem:windows:指定為 Windows GUI 子系統(無主控台視窗)。/libpath:指定匯入庫搜尋路徑。為避免每次連結都輸入路徑,可在原始碼中直接指定完整路徑:
includelib d:\masm7\lib\kernel32.lib
includelib d:\masm7\lib\user32.lib
或設定環境變數 LIB:set LIB=d:\masm7\lib,連結指令即可簡化為 link /subsystem:windows 3.obj。
手寫常數與函數原型既繁瑕又易錯。MASM32 SDK 提供 windows.inc 內含海量常數、結構定義,以及各 DLL 對應的 .inc 檔(如 user32.inc, kernel32.inc)提供函數原型。配合 option casemap:none 區分大小寫,程式碼可大幅精簡:
; 最終版本
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
.data
szText db "Hello, world!", 0
szCaption db "Win32Asm", 0
.code
start:
invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK
invoke ExitProcess, NULL
end start
關鍵改進:
INVOKE 取代 push/call:自動依原型檢查參數個數與型別,錯誤在組譯階段即可發現。addr 運算子:自動取得變數位址,等同 lea eax, var / push eax。MASM 支援一條指令完成編譯連結:
ml /coff /I d:\masm7\include 3.asm /link /subsystem:windows /libpath:d:\masm7\lib
若原始碼已以完整路徑 include / includelib,更可簡化為:
ml /coff 3.asm /link /subsystem:windows
Win32 組合語言的入門關鍵在於:理解 stdcall 堆疊呼叫慣例、善用 INVOKE 進行參數檢查、以及引入 MASM32 標準標頭檔 以提升開發效率與程式碼可維護性。掌握這些基礎後,即可進一步探索視窗程式、GDI 繪圖、多執行緒等進階主題。