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

結構化程式設計在組合語言中的應用:MASM 高層控制結構指南

     編輯:組合語言

前言

傳統組合語言依賴 JMP、LOOP 搭配標號實現流程控制,程式碼難讀、難維護。MASM (Microsoft Macro Assembler) 從 6.0 版起引入高層控制結構指令(.IF、.WHILE、.REPEAT、PROC/INVOKE 等),讓組合語言能以類 C/Pascal 的結構化風格撰寫,大幅提升可讀性與開發效率。本文系統整理這些指令的語法、屬性與實用範例。

1. 變數宣告與資料型別

支援帶正負號的位元組/字/雙字/四字/十字節,以及浮點型別:

[變數名] 型別指示符 初始值[, 初始值]...
; 型別: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(?)

2. .MODEL 偽指令:定義記憶體模型與呼叫慣例

.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

3. 程式進入點與結束:.STARTUP / .EXIT

.STARTUP          ; 依 .MODEL 產生啟動代碼,初始化 DS/SS/SP,定義進入點標號
; ... 程式碼 ...
.EXIT [expr]      ; 產生結束程式代碼,expr 為傳回作業系統的退出碼
END               ; 不需在 END 指定開始標號

4. 選擇結構:.IF / .ELSEIF / .ELSE / .ENDIF

.IF 條件1
    陳述區塊1
[.ELSEIF 條件2
    陳述區塊2]...
[.ELSE
    陳述區塊n]
.ENDIF
  • 條件為邏輯運算式,運算子同 C:== != > >= < <= & ! && ||。
  • 運算元可為:變數、暫存器、常數、旗標符號(CARRY? OVERFLOW? PARITY? SIGN? ZERO? 分別對應 CF, OF, PF, SF, ZF = 1)。
  • 結果非 0 為真,0 為假。求值順序左至右,可用括號改變優先序。
  • 支援巢狀。

5. 迴圈結構

結構 1:.WHILE ... .ENDW (前測試,WHILE 型)

.WHILE 條件
    陳述區塊
.ENDW

結構 2:.REPEAT ... .UNTIL 條件 (後測試,UNTIL 型)

.REPEAT
    陳述區塊
.UNTIL 條件

結構 3:.REPEAT ... .UNTILCXZ [條件] (帶 ECX 計數器)

.REPEAT
    陳述區塊
.UNTILCXZ [條件]   ; ECX--,若 ECX=0 或條件為真則跳出
  • 迴圈本體可使用 .BREAK [.IF 條件] 無條件/有條件跳出,.CONTINUE [.IF 條件] 跳過本輪剩餘代碼進入下一輪。
  • 所有迴圈支援巢狀。

6. 程序定義、原型宣告與呼叫:PROC / PROTO / INVOKE

程序定義

name PROC [distance] [language] [USES reglist] [, param[:tag]]... [LOCAL varlist]
    ; 程序本體
name ENDP
  • distance:NEAR / FAR
  • language:呼叫慣例(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 呼叫優勢

INVOKE expression [, arguments]
  • 自動依原型將實參壓堆(順序、型別轉換皆正確)。
  • 返回時自動清理堆疊(依呼叫慣例)。
  • 參數可為暫存器對(eax::edx)、運算式、ADDR 符號(取位址)。
  • 編譯期參數個數/型別檢查,避免 CALL 手動壓堆易出錯。

7. 綜合範例:計算當月天數

.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 組語程式,更能在底層除錯、效能關鍵路徑、殼代碼開發等領域發揮組語的極致效能優勢。

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