傳統組合語言依賴 JMP、LOOP 搭配標號實現流程控制,程式碼難讀、難維護。MASM (Microsoft Macro Assembler) 從 6.0 版起引入高層控制結構指令(.IF、.WHILE、.REPEAT、PROC/INVOKE 等),讓組合語言能以類 C/Pascal 的結構化風格撰寫,大幅提升可讀性與開發效率。本文系統整理這些指令的語法、屬性與實用範例。
支援帶正負號的位元組/字/雙字/四字/十字節,以及浮點型別:
[變數名] 型別指示符 初始值[, 初始值]...
; 型別:BYTE/SBYTE, WORD/SWORD, DWORD/SDWORD, QWORD, TBYTE, REAL4/8/10
; 範例:
count DWORD 10
temps REAL4 3.14, 2.71, 1.41
buffer BYTE 256 DUP(?)
.MODEL memory_model [, language] [, OS_type] [, stack_option]
; memory_model: TINY, SMALL, COMPACT, MEDIUM, LARGE, HUGE, FLAT
; language: C, PASCAL, BASIC, FORTRAN, STDCALL, SYSCALL
; stack_option: NEARSTACK (SS=DS) 或 FARSTACK (SS!=DS)
; Win32 典型用法:
.MODEL flat, stdcall
.STARTUP ; 依 .MODEL 產生啟動代碼,初始化 DS/SS/SP,定義進入點標號
; ... 程式碼 ...
.EXIT [expr] ; 產生結束程式代碼,expr 為傳回作業系統的退出碼
END ; 不需在 END 指定開始標號
.IF 條件1
陳述區塊1
[.ELSEIF 條件2
陳述區塊2]...
[.ELSE
陳述區塊n]
.ENDIF
== != > >= < <= & ! && ||。CARRY? OVERFLOW? PARITY? SIGN? ZERO? 分別對應 CF, OF, PF, SF, ZF = 1)。.WHILE 條件
陳述區塊
.ENDW
.REPEAT
陳述區塊
.UNTIL 條件
.REPEAT
陳述區塊
.UNTILCXZ [條件] ; ECX--,若 ECX=0 或條件為真則跳出
.BREAK [.IF 條件] 無條件/有條件跳出,.CONTINUE [.IF 條件] 跳過本輪剩餘代碼進入下一輪。name PROC [distance] [language] [USES reglist] [, param[:tag]]... [LOCAL varlist]
; 程序本體
name ENDP
distance:NEAR / FARlanguage:呼叫慣例(C, STDCALL, SYSCALL, PASCAL...),決定參數壓堆順序、誰清理堆疊、名稱修飾。USES:列出需保存的暫存器,自動在入口 PUSH、出口 POP。param[:tag]:參數名與型別(BYTE, WORD, DWORD, 結構名...),VARARG 表可變參數(需 C/STDCALL/SYSCALL)。LOCAL:在堆疊配置區域變數,可名稱存取,退出自動釋放。name PROTO [distance] [language] [, [param]:tag]...
宣告後即可用 INVOKE 呼叫。
INVOKE expression [, arguments]
eax::edx)、運算式、ADDR 符號(取位址)。CALL 手動壓堆易出錯。.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
prompt db "Enter year (1900-2100): ", 0
prompt2 db "Enter month (1-12): ", 0
resultMsg db "Days in month: %d", 0
year DWORD ?
month DWORD ?
days DWORD ?
.code
start:
; 取得年份
invoke StdOut, addr prompt
invoke StdIn, addr year, 10
; 取得月份
invoke StdOut, addr prompt2
invoke StdIn, addr month, 10
; 計算天數
.if month == 2
.if (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
mov days, 29
.else
mov days, 28
.endif
.elseif month == 4 || month == 6 || month == 9 || month == 11
mov days, 30
.else
mov days, 31
.endif
invoke wsprintf, addr buffer, addr resultMsg, days
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK
invoke ExitProcess, 0
end start
MASM 的高層控制結構(.IF/.WHILE/.REPEAT)、程序機制(PROC/PROTO/INVOKE/USES/LOCAL)與資料宣告,讓組合語言脫離「指令堆砌」的刻板印象,擁有接近高階語言的結構化表達力。善用這些特性,不僅能寫出清晰、可維護的 Win32 組語程式,更能在底層除錯、效能關鍵路徑、殼代碼開發等領域發揮組語的極致效能優勢。