; 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
ml /c /coff 3.asm ; 僅編譯產生 COFF 格式 3.obj
link /subsystem:windows /libpath:d:\masm7\lib 3.obj ; 聯結生成 3.exe
/c 僅編譯不聯結;/coff 產生 COFF 目標檔。/subsystem:windows 指定 Windows 子系統;/libpath 指定匯入庫路徑(Masm32 安裝目錄下的 Lib)。執行 3 即彈出訊息框,體驗真正 Win32 程式。
原始碼中 call MessageBoxA、call ExitProcess 呼叫的是 API 函數,非自寫子程式。參數型態與個數由原型定義:
ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD, :DWORD, :DWORD, :DWORD
Win32 參數透過堆疊傳遞,.model flat, stdcall 指定:
stdcall 慣例)。add sp, 值。對照 MSDN 定義:
int MessageBox(
HWND hWnd, // 視窗控制代碼
LPCTSTR lpText, // 訊息字串位址
LPCTSTR lpCaption,// 標題字串位址
UINT uType // 風格
);
對應壓栈順序:uType → lpCaption → lpText → hWnd,即程式碼中的 push MB_OK / push szCaption / push szText / push NULL。
手動壓栈易漏參數致命錯誤。INVOKE 可自動檢查參數個數與型態,聯結器回報錯誤:
invoke MessageBoxA, NULL, addr szText, addr szCaption, MB_OK
常數(NULL、MB_OK)、結構定義繁多,Hutch 整理的 windows.inc 囊括 Win32 所需常數與結構,一行 include windows.inc 全搞定。但函數原型在獨立標頭檔(user32.inc、kernel32.inc 等),需額外 include。使用 windows.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
ml /c /coff /I d:\masm7\include 3.asm
link /subsystem:windows /libpath:d:\masm7\lib 3.obj
或在源碼中指定完整路徑:
includelib d:\masm32\lib\kernel32.lib
includelib d:\masm32\lib\user32.lib
include d:\masm32\include\windows.inc
則聯結簡化為 ml /coff 3.asm /link /subsystem:windows。環境變數 Set include=... Set lib=... 亦可簡化操作。