匯編開(kāi)發(fā)(八):結(jié)構(gòu)體與宏

1. 結(jié)構(gòu)體

結(jié)構(gòu)是給予邏輯相關(guān)的變量組的模板或模式拿愧。 結(jié)構(gòu)中的變量稱為字段丑慎。 程序語(yǔ)句可以作為單個(gè)實(shí)體訪問(wèn)結(jié)構(gòu)裹唆,也可以訪問(wèn)單個(gè)字段号杏。 結(jié)構(gòu)通常包含不同類型的字段婴氮。 聯(lián)合還將多個(gè)標(biāo)識(shí)符組合在一起,但標(biāo)識(shí)符與內(nèi)存中的相同區(qū)域重疊盾致。

  • COORD 結(jié)構(gòu)體
    COORD 結(jié)構(gòu)在Windows API中定義屏幕的坐標(biāo)X和Y主经,字段X的偏移為0,字段Y的偏移為2.
COORD STRUCT
    X WORD ? ; offset 00
    Y WORD ? ; offset 02
COORD ENDS
1). 定義結(jié)構(gòu)體

定義結(jié)構(gòu)體使用STRUCTENDS, 結(jié)構(gòu)體內(nèi)部庭惜,使用相同的語(yǔ)法定義變量罩驻。

name STRUCT
    field-declarations
name ENDS
  • 字段初始化
    當(dāng)結(jié)構(gòu)字段具有初始值設(shè)定項(xiàng)時(shí),將在創(chuàng)建結(jié)構(gòu)變量時(shí)分配值护赊。字段初始化的類型如下:
    I. Undefined: 使用惠遏?標(biāo)識(shí)未定義
    II. String literals: 用引號(hào)括起來(lái)的字符串
    III. Integers: 整數(shù)常量或整數(shù)表達(dá)式
    IV. Arrays: DUP初始化的數(shù)組

示例:

Employee STRUCT
    IdNum BYTE "000000000"
    LastName BYTE 30 DUP(0)
    Years WORD 0
    SalaryHistory DWORD 0,0,0,0
Employee ENDS

內(nèi)存占用布局:

structure’s memory layout.png
  • 對(duì)齊結(jié)構(gòu)體字段
    為獲得最佳內(nèi)存I / O性能,結(jié)構(gòu)成員應(yīng)與匹配其數(shù)據(jù)類型的地址對(duì)齊骏啰。 否則节吮,CPU將需要更多時(shí)間來(lái)訪問(wèn)成員。 例如判耕,雙字成員應(yīng)在雙字邊界上對(duì)齊透绩。ALIGN datatype
Alignment of Structure Members.png
2). 定義結(jié)構(gòu)體變量

可以聲明結(jié)構(gòu)變量,并可選擇使用特定值進(jìn)行初始化壁熄。

identifier structureType < initializer-list >

示例:

.data
point1 COORD <5,10>     ; X = 5, Y = 10
point2 COORD <20>       ; X = 20, Y = ?
point3 COORD <>         ; X = ?, Y = ?
worker Employee <>      ; (default initializers)

person1 Employee <"555223333">      ; 初始化IdNum
person2 Employee {"555223333"}      ; 與上一行作用相同
person3 Employee <,"dJones">        ; 初始化LastName
person4 Employee <,,,2 DUP(20000)>  ; 初始化SalaryHistory
  • 結(jié)構(gòu)體數(shù)組
    使用DUP操作指令創(chuàng)建一個(gè)結(jié)構(gòu)體數(shù)組帚豪。
NumPoints = 3
AllPoints COORD NumPoints DUP(<0,0>)
  • 對(duì)齊結(jié)構(gòu)體變量
    為獲得最佳處理器性能,請(qǐng)將內(nèi)存邊界上的結(jié)構(gòu)變量與最大結(jié)構(gòu)成員對(duì)齊草丧。
data
ALIGN DWORD
person Employee <>
3). 引用結(jié)構(gòu)體變量

可以使用TYPE和SIZEOF運(yùn)算符來(lái)引用結(jié)構(gòu)變量和結(jié)構(gòu)名稱.

  • 獲取所占字節(jié)數(shù)
TYPE Employee   ; 60
SIZEOF Employee ; 60
SIZEOF worker   ; 60
  • 引用成員
    對(duì)命名結(jié)構(gòu)成員的引用需要結(jié)構(gòu)變量作為限定符狸臣。
TYPE Employee.SalaryHistory     ; 4
LENGTHOF Employee.SalaryHistory ; 4
SIZEOF Employee.SalaryHistory   ; 16
TYPE Employee.Years             ; 2
  • 使用OFFSET操作
mov edx,OFFSET worker.LastName
  • 間接索引操作數(shù)
    間接操作數(shù)允許使用寄存器(例如ESI)來(lái)尋址結(jié)構(gòu)成員。 間接尋址提供了靈活性昌执,特別是在將結(jié)構(gòu)地址傳遞給過(guò)程或使用結(jié)構(gòu)數(shù)組時(shí)烛亦。
mov esi,OFFSET worker
mov ax,(Employee PTR [esi]).Years
  • 索引操作數(shù)
    我們可以使用索引操作數(shù)來(lái)訪問(wèn)結(jié)構(gòu)體數(shù)組诈泼。
.data
    department Employee 5 DUP(<>)
.code
    mov esi,TYPE Employee       ; index = 1
    mov department[esi].Years, 4
  • 循環(huán)數(shù)組
    循環(huán)可以與間接或索引尋址一起使用來(lái)操縱結(jié)構(gòu)數(shù)組。
; 循環(huán)數(shù)組
INCLUDE Irvine32.inc

NumPoints = 3
.data
    ALIGN WORD
    AllPoints COORD NumPoints DUP(<0, 0>)

.code
main PROC
    mov edi, 0              ; 數(shù)組索引
    mov ecx, NumPoints      ; 循環(huán)計(jì)數(shù)
    mov ax, 1               ; 開(kāi)始X, Y的值

L1:
    mov (COORD PTR AllPoints[edi]).X, ax
    mov (COORD PTR AllPoints[edi]).Y, ax
    add edi, TYPE COORD
    inc ax
    LOOP L1
    exit
main ENDP
END
4). 示例: 顯示系統(tǒng)時(shí)間
; 顯示時(shí)間
INCLUDE Irvine32.inc

; 相關(guān)結(jié)構(gòu)體在SmallWin.inc中

.data
    sysTime SYSTEMTIME <>
    XYPos COORD <10, 5>
    consoleHandle DWORD ?
    colonStr BYTE ":", 0
.code
main PROC
    ; 獲取Win32控制臺(tái)標(biāo)準(zhǔn)輸出句柄
    INVOKE GetStdHandle, STD_OUTPUT_HANDLE
    mov consoleHandle, eax

    ; 設(shè)置光標(biāo)位置和獲取系統(tǒng)時(shí)間
    INVOKE SetConsoleCursorPosition, consoleHandle, XYPos
    INVOKE GetLocalTime, ADDR sysTime

    ; 顯示系統(tǒng)時(shí)間(hh:mm:ss)
    movzx eax, sysTime.wHour
    call WriteDec
    mov edx,OFFSET colonStr
    call WriteString
    movzx eax, sysTime.wMinute
    call WriteDec
    call WriteString
    movzx eax, sysTime.wSecond
    call WriteDec

    call Crlf
    call WaitMsg
    exit
main ENDP
END
ShowTime 效果.png
5). 結(jié)構(gòu)體包含結(jié)構(gòu)體

結(jié)構(gòu)體可以在內(nèi)部字段中包含其他結(jié)構(gòu)體此洲。

Rectangle STRUCT
    UpperLeft COORD <>
    LowerRight COORD <>
Rectangle ENDS

定義及初始化:

rect1 Rectangle < >
rect2 Rectangle { }
rect3 Rectangle { {10,10}, {50,20} }
rect4 Rectangle < <10,10>, <50,20> >
6). 定義和使用共用體

雖然結(jié)構(gòu)中的每個(gè)字段都具有相對(duì)于結(jié)構(gòu)的第一個(gè)字節(jié)的偏移量厂汗,但聯(lián)合中的所有字段都以相同的偏移量開(kāi)始。 union的存儲(chǔ)大小等于其最長(zhǎng)字段的長(zhǎng)度呜师。

格式:

unionname UNION
    union-fields
unionname ENDS

如果在結(jié)構(gòu)體定義共用體娶桦,則格式如下

structname STRUCT
    structure-fields
    UNION unionname
        union-fields
    ENDS
structname ENDS
  • 始終如一
    先定義一個(gè)Integer共用體,再定義myInt共用體變量汁汗,此時(shí)未進(jìn)行初始化衷畦,那么myInt.D, myInt.W, myInt.B的值都為1
Integer UNION
    D DWORD 1
    W WORD 5
    B BYTE 8
Integer ENDS

.data
    myInt Integer <>
  • 結(jié)構(gòu)體中包含共用體
    可以在結(jié)構(gòu)體中包含一個(gè)在外部定義的共用體或者在結(jié)構(gòu)體內(nèi)部定義共用體。
; 結(jié)構(gòu)體外部定義共用體
FileInfo STRUCT
    FileID Integer <>
    FileName BYTE 64 DUP(?)
FileInfo ENDS

; 結(jié)構(gòu)體內(nèi)部定義共用體
FileInfo STRUCT
    UNION FileID
        D DWORD ?
        W WORD ?
        B BYTE ?
    ENDS
    FileName BYTE 64 DUP(?)
FileInfo ENDS
  • 定義和使用共用體變量
    union變量的聲明和初始化方式與結(jié)構(gòu)變量的方式大致相同知牌,但有一個(gè)重要區(qū)別:允許的初始值不超過(guò)一個(gè)祈争。
val1 Integer <12345678h>
val2 Integer <100h>
val3 Integer <>

共用體中也可以包含結(jié)構(gòu)體

INPUT_RECORD STRUCT
    EventType WORD ?
    ALIGN DWORD
    UNION Event
        KEY_EVENT_RECORD <>
        MOUSE_EVENT_RECORD <>
        WINDOW_BUFFER_SIZE_RECORD <>
        MENU_EVENT_RECORD <>
        FOCUS_EVENT_RECORD <>
    ENDS
INPUT_RECORD ENDS

; 其中KEY_EVENT_RECORD結(jié)構(gòu)
KEY_EVENT_RECORD STRUCT
    bKeyDown DWORD ?
    wRepeatCount WORD ?
    wVirtualKeyCode WORD ?
    wVirtualScanCode WORD ?
    UNION uChar
        UnicodeChar WORD ?
        AsciiChar BYTE ?
    ENDS
    dwControlKeyState DWORD ?
KEY_EVENT_RECORD ENDS

2. 宏

宏過(guò)程是匯編語(yǔ)言語(yǔ)句的命名塊。 一旦定義角寸,就可以根據(jù)需要在程序中多次調(diào)用(調(diào)用)它菩混。 當(dāng)您調(diào)用宏過(guò)程時(shí),其代碼的副本將直接插入到調(diào)用它的位置的程序中扁藕。

  • 位置
    宏定義通常出現(xiàn)在程序源代碼的開(kāi)頭沮峡,或者它們被放在一個(gè)單獨(dú)的文件中,并通過(guò)INCLUDE指令復(fù)制到程序中亿柑。 在匯編程序的預(yù)處理步驟中擴(kuò)展宏

定義格式:

PrintX MACRO
    mov al,'X'
    call WriteChar
ENDM
1). 宏定義

宏定義使用 MACROENDM.

格式:

macroname MACRO parameter-1, parameter-2...
    statement-list
ENDM
  • 宏參數(shù)
    宏參數(shù)被命名為傳遞給調(diào)用者的文本參數(shù)的占位符, 參數(shù)可以是整數(shù)邢疙,變量或其他值,預(yù)處理器將它們視為文本望薄。

  • mPutchar 示例

mPutchar MACRO char
    push eax
    mov al,char
    call WriteChar
    pop eax
ENDM
2). 調(diào)用宏

通過(guò)在程序中插入宏來(lái)調(diào)用宏疟游,可能后跟宏參數(shù)。

macroname argument-1, argument-2, ...

調(diào)用mPutchar代碼:mPutchar 'A'

3). 其他宏功能
  • 必要參數(shù)
    使用REQ修飾符痕支,標(biāo)記宏參數(shù)是必要的颁虐。
mPutchar MACRO char:REQ
    push eax
    mov al,char
    call WriteChar
    pop eax
ENDM
  • 宏注釋
    每次擴(kuò)展宏時(shí),都會(huì)出現(xiàn)宏定義中出現(xiàn)的普通注釋行卧须。 如果要從宏擴(kuò)展中省略注釋聪廉,請(qǐng)?jiān)谇懊婕由想p分號(hào)(;;)
mPutchar MACRO char:REQ
    push eax            ;; reminder: char must contain 8 bits
    mov al,char
    call WriteChar
    pop eax
ENDM
  • ECHO 指令
    當(dāng)程序匯編時(shí),ECHO指令將字符串寫入標(biāo)準(zhǔn)輸出.
mPutchar MACRO char:REQ
    ECHO Expanding the mPutchar macro
    push eax
    mov al,char
    call WriteChar
    pop eax
ENDM
  • LOCAL 指令
    為避免標(biāo)簽重新定義導(dǎo)致的問(wèn)題故慈,可以將LOCAL指令應(yīng)用于宏定義內(nèi)的標(biāo)簽。 當(dāng)標(biāo)簽標(biāo)記為L(zhǎng)OCAL時(shí)框全,預(yù)處理器會(huì)在每次擴(kuò)展宏時(shí)將標(biāo)簽名稱轉(zhuǎn)換為唯一標(biāo)識(shí)符察绷。
makeString MACRO text
    LOCAL string
    .data
        string BYTE text,0
ENDM
  • 宏包含變量和代碼
mWrite MACRO text
    LOCAL string ;; local label
    .data
        string BYTE text,0 ;; define the string
    .code
        push edx
        mov edx,OFFSET string
        call WriteString
        pop edx
ENDM
  • 嵌套宏
    從另一個(gè)宏調(diào)用的宏稱為嵌套宏。
mWriteln MACRO text
    mWrite text
    call Crlf
ENDM
4). Macro 庫(kù)(32位)
Macros in the Macros.inc Library.png
  • mDumpMem
    mDumpMem宏在控制臺(tái)窗口中顯示一塊內(nèi)存津辩。
.data
array DWORD 1000h,2000h,3000h,4000h

mDumpMem OFFSET array, LENGTHOF array, TYPE array

宏實(shí)現(xiàn):

;------------------------------------------------------
mDumpMem MACRO address:REQ, itemCount:REQ, componentSize:REQ
; Displays a dump of memory, using the DumpMem procedure.
; Receives: memory offset, count of the number of items
; to display, and the size of each memory component.
; Avoid passing EBX, ECX, and ESI as arguments.
;------------------------------------------------------
    push ebx
    push ecx
    push esi
    mov esi,address
    mov ecx,itemCount
    mov ebx,componentSize
    call DumpMem
    pop esi
    pop ecx
    pop ebx
ENDM
  • mDump
    mDump 宏用十六進(jìn)制顯示變量的地址和值拆撼。
.data
    diskSize DWORD 12345h   
.code
    mDump diskSize      ; no label
    mDump diskSize,Y    ; show label

宏實(shí)現(xiàn):

;----------------------------------------------------
mDump MACRO varName:REQ, useLabel
;
; Displays a variable, using its known attributes.
; Receives: varName, the name of a variable.
; If useLabel is nonblank, the name of the
; variable is displayed.
;----------------------------------------------------
    call Crlf
    IFNB <useLabel>
        mWrite "Variable name: &varName"
    ENDIF
    mDumpMem OFFSET varName, LENGTHOF varName, TYPE varName
ENDM
  • mGotoxy
    mGotoxy宏將光標(biāo)定位在控制臺(tái)窗口緩沖區(qū)中的特定列和行位置容劳。
mGotoxy 10,20 ; immediate values
mGotoxy row,col ; memory operands
mGotoxy ch,cl ; register values

宏實(shí)現(xiàn):

;------------------------------------------------------
mGotoxy MACRO X:REQ, Y:REQ
;
; Sets the cursor position in the console window.
; Receives: X and Y coordinates (type BYTE). Avoid
; passing DH and DL as arguments.
;------------------------------------------------------
    push edx
    mov dh,Y
    mov dl,X
    call Gotoxy
    pop edx
ENDM
  • mReadString
    mReadString宏從鍵盤輸入一個(gè)字符串,并將該字符串存儲(chǔ)在緩沖區(qū)中闸度。
.data
    firstName BYTE 30 DUP(?)
.code
    mReadString firstName

宏實(shí)現(xiàn):

;------------------------------------------------------
mReadString MACRO varName:REQ
;
; Reads from standard input into a buffer.
; Receives: the name of the buffer. Avoid passing
; ECX and EDX as arguments.
;------------------------------------------------------
    push ecx
    push edx
    mov edx,OFFSET varName
    mov ecx,SIZEOF varName
    call ReadString
    pop edx
    pop ecx
ENDM
  • mShow
    mShow宏以調(diào)用者選擇的格式顯示任何寄存器或變量的名稱和內(nèi)容竭贩。
mov ax,4096
mShow AX        ; default options: HIN
mShow AX,DBN    ; unsigned decimal, binary, newline
  • mShowRegister
    mShowRegister宏以十六進(jìn)制顯示單個(gè)32位寄存器的名稱和內(nèi)容。
mShowRegister EBX, ebx

宏實(shí)現(xiàn):

;---------------------------------------------------
mShowRegister MACRO regName, regValue
LOCAL tempStr
;
; Displays a register's name and contents.
; Receives: the register name, the register value.
;---------------------------------------------------
    .data
        tempStr BYTE " &regName=",0
    .code
        push eax
        ; Display the register name
        push edx
        mov edx,OFFSET tempStr
        call WriteString
        pop edx
        ; Display the register contents
        mov eax,regValue
        call WriteHex
        pop eax
ENDM
  • mWriteSpace
    mWriteSpace宏在控制臺(tái)輸出一個(gè)或多個(gè)空格莺禁。
; 默認(rèn)為1
mWriteSpace 5

宏實(shí)現(xiàn):

;------------------------------------------------------
mWriteSpace MACRO count:=<1>
;
; Writes one or more spaces to the console window.
; Receives: an integer specifying the number of spaces.
; Default value of count is 1.
;------------------------------------------------------
    LOCAL spaces
    .data
        spaces BYTE count DUP(' '),0
    .code
        push edx
        mov edx,OFFSET spaces
        call WriteString
        pop edx
ENDM
  • mWriteString
    mWriteString宏向控制臺(tái)輸出一個(gè)字符串變量的值留量。
.data
    str1 BYTE "Please enter your name: ",0
.code
    mWriteString str1

宏實(shí)現(xiàn):

;------------------------------------------------------
mWriteString MACRO buffer:REQ
;
; Writes a string variable to standard output.
; Receives: string variable name.
;------------------------------------------------------
    push edx
    mov edx,OFFSET buffer
    call WriteString
    pop edx
ENDM
5). 示例:包裝
; Macros 包裝程序 
; 使用Macros庫(kù)中的:mGotoxy, mWrite, mWriteString
; mReadString, and mDumpMem.

INCLUDE Irvine32.inc
INCLUDE Macros.inc          ; macro 定義

.data
    array DWORD 1, 2, 3, 4, 5, 6, 7, 8
    firstName BYTE 31 DUP(?)
    lastName BYTE 31 DUP(?)

.code 
main PROC
    mGotoxy 0, 0
    mWrite <"Sample Macro Program", 0dh, 0ah>
    
    ; 輸出用戶信息
    mGotoxy 0, 5
    mWrite "Please enter your first name: "
    mReadString firstName
    call Crlf

    mWrite "Please enter your last name: "
    mReadString lastName
    call Crlf

    ; 顯示用戶姓名
    mWrite "Your name is "
    mWriteString firstName
    mWriteSpace
    mWriteString lastName
    call Crlf

    ; 顯示整型數(shù)組
    mDumpMem OFFSET array, LENGTHOF array, TYPE array
    
    call WaitMsg
    call Crlf
    exit
main ENDP
END
Wraps.png

3. 條件裝配指令

許多不同的條件匯編指令可以與宏結(jié)合使用,以使它們更加靈活哟冬。

IF condition
    statements
[ELSE
    statements]
ENDIF
Conditional-Assembly Directives.png
1). 檢查丟失的參數(shù)

宏可以檢查它的任何參數(shù)是否為空。 通常,如果宏接收到空白參數(shù)恰力,則在預(yù)處理器擴(kuò)展宏時(shí)會(huì)產(chǎn)生無(wú)效指令岸售。

mWriteString MACRO string
    IFB <string>
        ECHO -------------------------------------------
        ECHO * Error: parameter missing in mWriteString
        ECHO * (no code generated)
        ECHO -------------------------------------------
        EXITM
    ENDIF
    push edx
    mov edx,OFFSET string
    call WriteString
    pop edx
ENDM
2). 參數(shù)的默認(rèn)值

宏可以設(shè)置參數(shù)的默認(rèn)值,如果用戶沒(méi)有為參數(shù)設(shè)置值翰灾,則使用該參數(shù)的默認(rèn)值缕粹。

paramname := < argument >

示例:

mWriteln MACRO text:=<" ">
    mWrite text
    call Crlf
ENDM
3). Boolean 表達(dá)式
LT Less than
GT Greater than
EQ Equal to
NE Not equal to
LE Less than or equal to
GE Greater than or equal to
4). IF, ELSE, and ENDIF 指令

IF指令必須后跟一個(gè)常量布爾表達(dá)式。 表達(dá)式可以包含整數(shù)常量纸淮,符號(hào)常量或常量宏參數(shù)平斩,但不能包含寄存器或變量名稱。

IF expression
    statement-list
ENDIF

IF expression
    statement-list
ELSE
    statement-list
ENDIF

示例:

;-----------------------------------------------------
mGotoxyConst MACRO X:REQ, Y:REQ
;
; Sets the cursor position at column X, row Y.
; Requires X and Y coordinates to be constant expressions
; in the ranges 0 <= X < 80 and 0 <= Y < 25.
;------------------------------------------------------
    LOCAL ERRS ;; local constant
    ERRS = 0
    IF (X LT 0) OR (X GT 79)
        ECHO Warning: First argument to mGotoxy (X) is out of range.
        ECHO ******************************************************
        ERRS = 1
    ENDIF
    IF (Y LT 0) OR (Y GT 24)
        ECHO Warning: Second argument to mGotoxy (Y) is out of range.
        ECHO ******************************************************
        ERRS = ERRS + 1
    ENDIF
    IF ERRS GT 0 ;; if errors found,
        EXITM;; exit the macro
    ENDIF
    push edx
    mov dh,Y
    mov dl,X
    call Gotoxy
    pop edx
ENDM
5). IFIDN 和 IFIDNI 指令

IFIDNI指令在兩個(gè)符號(hào)(包括宏參數(shù)名稱)之間執(zhí)行不區(qū)分大小寫的匹配萎馅,如果它們相等則返回true双戳。 IFIDN指令執(zhí)行區(qū)分大小寫的匹配。 當(dāng)您想要確保宏的調(diào)用者沒(méi)有使用可能與宏內(nèi)的寄存器使用沖突的寄存器參數(shù)時(shí)糜芳,前者很有用飒货。

IFIDNI <symbol>, <symbol>
    statements
ENDIF

使用:

;------------------------------------------------------
mReadBuf MACRO bufferPtr, maxChars
;
; Reads from the keyboard into a buffer.
; Receives: offset of the buffer, count of the maximum
; number of characters that can be entered. The
; second argument cannot be edx or EDX.
;------------------------------------------------------
    IFIDNI <maxChars>,<EDX>
        ECHO Warning: Second argument to mReadBuf cannot be EDX
        ECHO **************************************************
        EXITM
    ENDIF
    push ecx
    push edx
    mov edx,bufferPtr
    mov ecx,maxChars
    call ReadString
    pop edx
    pop ecx
ENDM
6). 特殊的運(yùn)算符
Special Operators.png
  • Substitution Operator (&)
    substitution(&)運(yùn)算符解決了宏中參數(shù)名稱的模糊引用。
.code
mShowRegister ECX

mShowRegister MACRO regName
.data
tempStr BYTE " &regName=",0

打印結(jié)果:
EAX = 00000101

效果用于顯示寄存器名
  • Expansion Operator (%)
    擴(kuò)展運(yùn)算符(%)擴(kuò)展文本宏或?qū)⒊A勘磉_(dá)式轉(zhuǎn)換為其文本表示形式峭竣。
count = 10
sumVal TEXTEQU %(5 + count) ; = "15"
  • Literal-Text Operator (< >)
    Literal-Text Operator(<>)將一個(gè)或多個(gè)字符和符號(hào)分組到單個(gè)文本文本中塘辅。
mWrite <"Line three", 0dh, 0ah>
  • Literal-Character Operator (!)
    Literal-Character Operator (!)的發(fā)明與文字文本運(yùn)算符的目的大致相同:它強(qiáng)制預(yù)處理器將預(yù)定義的運(yùn)算符視為普通字符皆撩。
BadYValue TEXTEQU <Warning: Y-coordinate is !> 24> 
ShowWarning MACRO message
mWrite "&message"
ENDM

;打印結(jié)果:
Warning: Y-coordinate is > 24
7). 宏函數(shù)

宏函數(shù)類似于宏過(guò)程扣墩,因?yàn)樗鼮閰R編語(yǔ)言語(yǔ)句列表指定名稱。 它的不同之處在于它總是通過(guò)EXITM指令返回一個(gè)常量(整數(shù)或字符串)扛吞。

IsDefined MACRO symbol
    IFDEF symbol
        EXITM <-1> ;; True
    ELSE
        EXITM <0> ;; False
    ENDIF
ENDM

4. 定義重復(fù)塊

MASM有許多循環(huán)指令用于生成重復(fù)的語(yǔ)句塊:
WHILE呻惕,REPEAT,F(xiàn)OR和FORC滥比。 與LOOP指令不同亚脆,這些指令僅在匯編時(shí)工作,使用常量值作為循環(huán)條件和計(jì)數(shù)器:

  • WHILE指令基于布爾表達(dá)式重復(fù)語(yǔ)句塊盲泛。
  • REPEAT指令根據(jù)計(jì)數(shù)器的值重復(fù)語(yǔ)句塊濒持。
  • FOR指令通過(guò)迭代符號(hào)列表來(lái)重復(fù)語(yǔ)句塊键耕。
  • FORC指令通過(guò)迭代一串字符來(lái)重復(fù)語(yǔ)句塊。
1). WHILE 指令

WHILE指令基于布爾表達(dá)式重復(fù)語(yǔ)句塊柑营。

WHILE constExpression
    statements
ENDM

示例:

.data
    val1 = 1
    val2 = 1
    DWORD val1 ; first two values
    DWORD val2
    val3 = val1 + val2
    WHILE val3 LT 0F0000000h
        DWORD val3
        val1 = val2
        val2 = val3
        val3 = val1 + val2
    ENDM
2). REPEAT 指令

REPEAT指令根據(jù)計(jì)數(shù)器的值重復(fù)語(yǔ)句塊屈雄。

REPEAT constExpression
    statements
ENDM

示例:

WEEKS_PER_YEAR = 52
WeatherReadings STRUCT
    location BYTE 50 DUP(0)
    REPEAT WEEKS_PER_YEAR
        LOCAL rainfall, humidity
        rainfall DWORD ?
        humidity DWORD ?
    ENDM
WeatherReadings ENDS
3). FOR 指令

FOR指令通過(guò)迭代符號(hào)列表來(lái)重復(fù)語(yǔ)句塊。

FOR parameter,<arg1,arg2,arg3,...>
    statements
ENDM

示例:

COURSE STRUCT
    Number BYTE 9 DUP(?)
    Credits BYTE ?
COURSE ENDS

; A semester contains an array of courses.
SEMESTER STRUCT
    Courses COURSE 6 DUP(<>)
    NumCourses WORD ?
SEMESTER ENDS

.data
    Fall2013 SEMESTER <>
    Spring2014 SEMESTER <>
    Summer2014 SEMESTER <>
    Fall2014 SEMESTER <>
    FOR semName,<Fall2013,Spring2014,Summer2014,Fall2014>
        semName SEMESTER <>
    ENDM
4). FORC 指令

FORC指令通過(guò)迭代一串字符來(lái)重復(fù)語(yǔ)句塊官套。

FORC parameter, <string>
    statements
ENDM

示例:

Delimiters LABEL BYTE
FORC code,<@#$%^&*!<!>>
    BYTE "&code"
ENDM
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酒奶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虏杰,更是在濱河造成了極大的恐慌讥蟆,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纺阔,死亡現(xiàn)場(chǎng)離奇詭異瘸彤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)笛钝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門质况,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人玻靡,你說(shuō)我怎么就攤上這事结榄。” “怎么了囤捻?”我有些...
    開(kāi)封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵臼朗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蝎土,道長(zhǎng)视哑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任誊涯,我火速辦了婚禮挡毅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暴构。我一直安慰自己跪呈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布取逾。 她就那樣靜靜地躺著耗绿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪砾隅。 梳的紋絲不亂的頭發(fā)上缭乘,一...
    開(kāi)封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼堕绩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邑时,可吹牛的內(nèi)容都是我干的奴紧。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晶丘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼黍氮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起浅浮,我...
    開(kāi)封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沫浆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后滚秩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體专执,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年郁油,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了本股。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桐腌,死狀恐怖拄显,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情案站,我是刑警寧澤躬审,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站蟆盐,受9級(jí)特大地震影響承边,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舱禽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一炒刁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧誊稚,春花似錦翔始、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至疾瓮,卻和暖如春脖镀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狼电。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工蜒灰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弦蹂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓强窖,卻偏偏與公主長(zhǎng)得像凸椿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翅溺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,378評(píng)論 0 5
  • 一脑漫、Python簡(jiǎn)介和環(huán)境搭建以及pip的安裝 4課時(shí)實(shí)驗(yàn)課主要內(nèi)容 【Python簡(jiǎn)介】: Python 是一個(gè)...
    _小老虎_閱讀 5,734評(píng)論 0 10
  • 概要 64學(xué)時(shí) 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,146評(píng)論 0 3
  • 在現(xiàn)時(shí)代的需求下,基因型產(chǎn)業(yè)也需要定制營(yíng)銷商業(yè)模式咙崎,跟隨時(shí)代的發(fā)展优幸,其中江西宇駿就是其中的代表之一。據(jù)悉褪猛,宇駿高科...
    HEIBAO閱讀 160評(píng)論 0 0
  • 東岳西麓有仙境网杆, 素稱泰山小江南。 清溪縈繞乃天寶握爷, 彩石繽紛為物華跛璧。 臨入石溪桃花峪, 石溪深處桃花源新啼。 渾然天...
    風(fēng)月無(wú)色閱讀 211評(píng)論 0 0