?--------------------------------------------------------------------------------------------------------------------
嗯?? 上個星期到現在?? 把Win32ASM基礎匯編復習了下?? 在網上找到了? 這個不錯系列
于是就轉載過來了?? 其中? 根據我自己的水平? 刪減了一些內容?或者增加了一些內容
如果要看原來的內容的?? 請訪問原創:http://www.cnblogs.com/del/category/121079.html?
?--------------------------------------------------------------------------------------------------------------------
宏可定義在源程序的任意位置, 但一般放在 .data 前面.
有些簡單的宏可以用 equ、textequ 或 = 來代替, 但宏有更復雜的功能.
"宏" 的本質是 "替換", 但又像極了 "子過程";
所以即有宏過程(macro procedure)、也有宏函數(macro function).
它既以有參數(可以是: 常數、變量、寄存器、指令、表達式), 有時也需要像子過程一樣聲明.
宏可以指定哪些參數是必須的, 還可以給參數默認值.
宏可以包含數據(.data)和代碼(.code)、還可以嵌套.
宏中的注釋使用 ;; 如果只用 ; 將會被一起替換到代碼中.
宏的功能很強大, 現在常用的 PrintDec、PrintHex、PrintString、PrintText 等等都是宏.
再強大它也只是 "文本替換".
"宏" 和 "子程序" 相比:
1、宏展開后順序執行, 不像調用子程序跳來跳去, 這樣程序會更 "快";
2、宏展開后會讓代碼量增大, 導致程序變 "大".
--------------------------------------------------------------------------------------------------------------------
一個簡單的宏:
--------------------------------------------------------------------------------------------------------------------
; Test34_1.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;定義一個 mExit 宏
mExit macro
??? PrintLine
??? ret
endm
.code
sum proc v1, v2, v3
??? mov eax, v1
??? add eax, v2
??? add eax, v3
??? ret
sum endp
;
main proc
??? invoke sum, 11, 22, 33
??? PrintDec eax ;66
??? ;PrintLine
??? ;ret
??? mExit ;mExit 將被替換為上面兩行代碼
main endp
end main
--------------------------------------------------------------------------------------------------------------------
一個代替求和函數的宏:
--------------------------------------------------------------------------------------------------------------------
; Test34_2.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
mSum macro v1, v2, v3
??? mov eax, v1
??? add eax, v2
??? add eax, v3
endm
.code
main proc
??? mSum 11, 22, 33
??? PrintDec eax ;66
??? PrintLine
??? mSum 11, 22, 33, 44, 55 ;多余的參數會被忽略
??? PrintDec eax ;66
??? PrintLine
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
宏參數的默認值:
--------------------------------------------------------------------------------------------------------------------
; Test34_3.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;參數 v1、v2 通過 REQ 標識說明是必備參數
;參數 v3、v4 給出了默認值
mSum macro v1:req, v2:req, v3:=<33>, v4:=<44>
??? mov eax, v1
??? add eax, v2
??? add eax, v3
??? add eax, v4
endm
.code
main proc
??? mSum 11, 22
??? PrintDec eax ;110
??? PrintLine
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
EXITM: 退出宏
--------------------------------------------------------------------------------------------------------------------
; Test34_4.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
mPrint macro
??? PrintText '第一行'
??? PrintText '第二行'
??? exitm
??? PrintText '第三行'
endm
.code
main proc
??? mPrint ;只會輸出前兩行
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
PURGE: 取消宏
--------------------------------------------------------------------------------------------------------------------
; Test34_5.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
mPrint macro
??? PrintText '第一行'
??? PrintText '第二行'
??? PrintText '第三行'
??? PrintLine
endm
.code
main proc
??? mPrint
??? mPrint
??? purge mPrint ;可用逗號隔開取消多個宏
??? mPrint?????? ;這個宏不會展開了
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
宏中 local 的使用:
--------------------------------------------------------------------------------------------------------------------
; Test34_6.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;從三個數中求最大數的宏
mMax macro v1, v2, v3
??? LOCAL L1, L2 ;;如沒有這句, 宏在多次展開時會讓 L1、L2 重名, 這樣宏會把標號名稱協調好
??? mov eax, v1
??? cmp eax, v2
??? jge L1
??? mov eax, v2
L1: cmp eax, v3
??? jge L2
??? mov eax, v3
L2:
endm
.code
main proc
??? mMax 11, 22, 33
??? PrintDec eax? ;33
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
靈活的參數, 用到 & 操作符:
--------------------------------------------------------------------------------------------------------------------
; Test34_7.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;求最數中的最大值:
mMax macro v1, v2
??? LOCAL L1
??? mov eax, v1
??? cmp eax, v2
??? jge L1
??? mov eax, v2
L1:
endm
;求最數中的最小值:
mMin macro v1, v2
??? LOCAL L1
??? mov eax, v1
??? cmp eax, v2
??? jle L1
??? mov eax, v2
L1:
endm
;能把 JGE 或 JLE 做參數:
mCom1 macro XX, v1, v2
??? LOCAL L1
??? mov eax, v1
??? cmp eax, v2
??? XX L1
??? mov eax, v2
L1:
endm
;能通過參數讓 J*E 變為 JGE 或 JLE:
mCom2 macro X, v1, v2
??? LOCAL L1
??? mov eax, v1
??? cmp eax, v2
??? J&X&E L1??? ;;這里用到特殊操作符 &
??? mov eax, v2
L1:
endm
.code
main proc
??? mMax 11, 22
??? PrintDec eax ;22
???
??? mMin 11, 22
??? PrintDec eax ;11
???
??? mCom1 JGE, 11, 22
??? PrintDec eax ;22
???
??? mCom1 JLE, 11, 22
??? PrintDec eax ;11
???
??? mCom2 G, 11, 22
??? PrintDec eax ;22
???
??? mCom2 L, 11, 22
??? PrintDec eax ;11
??? ret
main endp
end main
--------------------------------------------------------------------------------------------------------------------
特殊操作符: &、<>、%、!
--------------------------------------------------------------------------------------------------------------------
&? ;替換操作符
<> ;字符串傳遞操作符
%? ;表達式操作符, 也用于得到一個變量或常量的值
!? ;轉義操作符
--------------------------------------------------------------------------------------------------------------------
; Test34_8.asm
.386
.model flat, stdcall
include??? windows.inc
include??? kernel32.inc
include??? masm32.inc
include??? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
;自定義的宏
mPrint macro Text
??? PrintText '* &Text& *'
endm
.code
main proc
??? ;該宏會把參數直接替換過去
??? mPrint 1234??? ;* 1234 *
???
??? ;要保證參數的完整應該使用 <>
??? mPrint 12,34?? ;* 12 *
??? mPrint <12,34> ;* 12,34 *
???
??? ;需要計算結果應該使用 %()
??? mPrint 34+12?? ;* 34+12 *
??? mPrint %(34+12)?? ;* 46 *
???
??? ;用到 &、<、>、%、! 應該使用 ! 轉義
??? mPrint 10 !% 2 = %(10/2)!! ;* 10 % 2 = 5! *
??? ret
main endp
end main
?