首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

MASM 入門實戰:從零撰寫 Win32 訊息框程式

     編輯:組合語言

Win32 組語開發基礎架構

Windows API 函數儲存在系統 DLL 中(kernel32.dll、user32.dll、gdi32.dll 等)。組語程式透過匯入庫(.lib)在連結階段解析函數位址,執行時由載入器動態連結。開發流程:

  1. 撰寫 .asm 原始碼
  2. ml.exe 編譯產生 .obj
  3. link.exe 連結產生 .exe

最小框架程式

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

.code
start:
    invoke ExitProcess, 0
end start
  • .386:啟用 80386 指令集
  • .model flat, stdcall:平坦記憶體模型,stdcall 呼叫慣例(Win32 標準)
  • option casemap:none:區分大小寫(標號、API 名稱)
  • include:插入標頭檔(常數、結構、巨集)
  • includelib:告訴連結器引入哪個 .lib
  • invoke:高層呼叫指令,自動處理參數壓堆疊與類型檢查

編譯連結指令

ml /c /coff /Cp msgbox.asm
link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib msgbox.obj
  • /c:僅編譯不連結
  • /coff:產生 COFF 格式目標檔
  • /Cp:保留使用者定義符號大小寫
  • /SUBSYSTEM:WINDOWS:指定 GUI 子系統(無主控台視窗)

呼叫 MessageBox 顯示對話框

API 原型

MessageBox PROTO hWnd:DWORD, lpText:DWORD, lpCaption:DWORD, uType:DWORD
  • hWnd:父視窗控制代碼,NULL 表示無擁有者
  • lpText:訊息字串位址(以 0 結尾)
  • lpCaption:標題列字串位址
  • uType:圖示與按鈕樣式(MB_OK, MB_ICONINFORMATION 等)

完整程式碼

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

.data
MsgCaption db "Iczelion Tutorial No.2", 0
MsgText    db "Win32 Assembly is Great!", 0

.code
start:
    invoke MessageBox, NULL, addr MsgText, addr MsgCaption, MB_OK
    invoke ExitProcess, 0
end start

關鍵概念深度解析

addr vs offset

運算子適用範圍處理時機區域變數支援
offset全域/靜態標號編譯期不支援
addr全域/靜態/區域變數執行期 (區域變數)支援 (產生 LEA 指令)
; 全域變數:兩者皆可
invoke MessageBox, NULL, offset MsgText, addr MsgCaption, MB_OK

; 區域變數 (在 PROC 內用 LOCAL 宣告):
LOCAL szBuf[128]:BYTE
invoke lstrcpy, addr szBuf, addr SrcText  ; 必須用 addr
; invoke lstrcpy, offset szBuf, ...       ; 錯誤:offset 無法處理執行期位址

字串與字元集

  • ANSI 版 API 尾碼 A(如 MessageBoxA),字串為單位元組字元,以 0 結尾。
  • Unicode 版 API 尾碼 W(如 MessageBoxW),字串為雙位元組寬字元。
  • 標頭檔中透過巨集切換:#ifdef UNICODE ... #define MessageBox MessageBoxW ...
  • MASM32 範例多使用 ANSI 版,字串定義用 db "text", 0。

呼叫慣例:stdcall

  • 參數由右至左壓入堆疊
  • 被呼叫者負責清理堆疊 (RET n)
  • 返回值放在 EAX
  • EBX, ESI, EDI, EBP, ESP, 段暫存器必須保存

invoke 會自動產生正確的壓堆疊與清理代碼,避免手寫 push/call 易出錯。

常見錯誤與除錯技巧

  1. 忘記 includelib:編譯通過,連結報錯 unresolved external symbol。
  2. 參數型別不符:invoke 會檢查,call 不會 → 執行期崩潰。
  3. 字串未以 0 結尾:API 會讀取垃圾資料直到遇到 0,導致顯示亂碼或存取違規。
  4. 子系統設定錯誤:GUI 程式用 /SUBSYSTEM:CONSOLE 會多出主控台視窗;主控台程式用 WINDOWS 會看不到輸出。
  5. 大小寫敏感:option casemap:none 時,Start 與 start 是不同標號。

進階:模組化開發

大型專案應將常用常數、結構、巨集、函數原型集中在 .inc 檔,實作碼分散在多個 .asm,連結時一併輸入:

; main.asm
include mylib.inc
includelib mylib.lib
; ...
; mylib.asm
; 實作函數
; 編譯: ml /c /coff mylib.asm
; 建立靜態庫: lib /OUT:mylib.lib mylib.obj

總結

Win32 組語開發的核心在於:理解 PE 載入機制、熟悉 API 呼叫慣例、善用 invoke 與標頭檔進行型別安全開發。本文的訊息框範例雖簡單,但包含了完整的開發流程、關鍵指令與常見坑點,是進階學習視窗程式、GDI 繪圖、多執行緒、網路程式設計的堅實基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved