?? 宏.txt
字號:
MASM宏使用總結(jié)
導(dǎo)語
MASM(Macro Assembler)是由微軟公司提供的匯編工具,雖然有些年頭了,但是仍然存在于 vc.net這樣比較新的工具中。有很多匯編教科書以這個為對象,講述了如何用匯編去設(shè)計一個程序,作為計算機(jī)科學(xué)系學(xué)生的基礎(chǔ)課。但是,講述的內(nèi)容大體上還是停留在5.1版,而且停留在DOS的時代。雖然提到了win32下的匯編,但是并沒有放在首要的位置。另一個被忽視的是作為MASM最大特色的宏,怎么去看待匯編工具中提供的強(qiáng)大的宏,以及怎么和在什么場合下使用宏,語焉不詳。本文是作者在大量使用MASM宏,搭建了一個匯編環(huán)境下的OOP系統(tǒng)后,作的一個總結(jié)。
善用宏,能夠減少重復(fù)編碼,以及構(gòu)建強(qiáng)大的功能,是重用代碼,美化代碼的一個有力的工具。宏在高級語言中是一個應(yīng)該被極力避免的東西,在低級語言中確未必如此。
宏就是預(yù)處理
宏就是在代碼被匯編成為obj文件之前進(jìn)行的預(yù)處理。由于發(fā)生在匯編期(Assembly-Time, 和高級語言中的編譯期是一個意思),所以不會給執(zhí)行期帶來負(fù)擔(dān),可以用作代碼生成工具,設(shè)置和C++中的模板一樣,用作meta-programming的工具。在MASM中宏可以分為兩種:1、 Text Macro 2、Procedure (Function) Macro。第一種宏就是和#define pi 31415926這樣的簡單的文本替換的宏,第二種就是那種帶參數(shù),可以有局部變量,可以返回值這樣的可以看作函數(shù)或者過程的宏。下面就先從Text Macro入手,看看如何使用簡單的宏。
簡單的文本宏
你可以給一個字符序列指定一個符號名,然后在源代碼的其余部分用這個名字來代替這個字符序列。這個指定了名字的文本就是文本宏。說白了就是文本替換。用TEXTEQU來定義一個這樣的宏。
name TEXTEQU
name TEXTEQU textvar
name TEXTEQU %numvar
我這里給出的使用說明和MASM Programmer Guide中給出的不大一樣,但是這個更能說明問題。我在這兒只解釋第一個用法,后面的用法將在講了“匯編期變量”之后再講。舉一些使用的例子。
pi TEXTEQU <3.1416>
DWPTR TEXTEQU
arg1 TEXTEQU <[bp+4]>
然后在代碼中就可以用pi這些名字來代替3.1416這些。<>表示他們是字符串,如果把不加<> 則會把你給出的字符串當(dāng)作一個匯編期的文本變量來進(jìn)行求值,而這樣的話會出錯的。
匯編期的變量與常量
這個幾個東西其實都有自己的名字,其實按照用法來說就是匯編期的常量與變量的意思。比如Text Macro(對,就是前面的文本宏)用作匯編期的文本常量,Name Assignment用作匯編期的數(shù)值變量。
定義匯編期常量
什么是匯編期常量呢?其實也就是常量的意思,因為無論在編譯期還是執(zhí)行期它都是靜態(tài)的,一旦定義之后其值不能改變。回憶在C中,你用#define來定義常量。但是#define可以改變一個宏所等于的值,也就是說常量與否需要你的維護(hù)(編譯器會給出一個警告)。在MASM 中有一個關(guān)鍵字專門用來定義常量,嘗試改變常量的值會得到一個錯誤提示。
name EQU expression
name EQU
第一個是用作定義個“數(shù)值”常量,第二個是用作定義“文本”常量。以后要特別區(qū)分開文本和數(shù)值。
定義匯編期文本變量
匯編期文本變量是對“text macro”的另外一個看法。其實它們是同一個事情。當(dāng)你定義了一個文本宏之后,你可以把那個宏名看作匯編期文本變量的名字,被宏名替換的文本內(nèi)容作為變量的文本值。
那么前面說過的第二種用法:name TEXTEQU textvar就很好理解了。就是讓把一個文本變量賦給另一個文本變量。比如:
talent TEXTEQU
taowen TEXTEQU talent
第一行定義了一個名字為talent的匯編期文本變量,第二行把talent的值賦給了名為 taowen的變量。從結(jié)果上看這個和:
talent TEXTEQU
taowen TEXTEQU
是一樣的,但是第二種做法是先因為文本宏替換的作用把talent變成了genius。實際的效果是這樣的:
taowen TEXTEQU
顯示文本變量的內(nèi)容
在C中經(jīng)常用printf,在運(yùn)行期顯示一些變量的內(nèi)容來進(jìn)行調(diào)試。而在MASM中則用echo來在匯編期顯示文本變量的內(nèi)容。
china TEXTEQU
%echo china
這樣會在匯編時的命令行中出現(xiàn)great country。如果你把%號去掉,則顯示的是china。你應(yīng)該可以推測出%是干什么的了,就是對一個變量進(jìn)行求值。
定義匯編期數(shù)值變量
常量有兩種那么變量也應(yīng)該有兩種。這里就介紹匯編期數(shù)值變量的用法。
name = expression
expression是一個數(shù)值表達(dá)式,比如:
val = 3+4
此時val就是一個數(shù)值變量,其值為7。你也可以這么寫:
valexp TEXTEQU <3+4>
val = valexp
看上去好像式把一個文本變量賦給了數(shù)值變量,進(jìn)行了類型轉(zhuǎn)換(呵呵,效果是一樣的)。其實實際上是把3+4寫到了valexp處,因為文本宏進(jìn)行了文本替換。
把數(shù)值變量賦給文本變量
前面我們看到了如何“把文本變量賦給數(shù)值變量”,那么反過來呢?
val = 3+4
valexp TEXTEQU val
結(jié)果是提示錯誤:STest.asm(15) : error A2051: text item required。匯編器說需要文本項,那么我們加上<>就好了。
val = 3+4
valexp TEXTEQU
用%echo valexp檢查一下你就會發(fā)現(xiàn),并不是如你所愿的顯示的是7,而是val。這個是因為<>使得匯編器認(rèn)為val是一個字符串,由于數(shù)值變量不是文本替換的宏,并不會把val替換為7,所以當(dāng)然顯示的是val。正確的做法是:
val = 3+4
valexp TEXTEQU %val
%號和前面的用法一樣,是用作求值。回憶一開始介紹的文本宏的用法中的第三條就是: name TEXTEQU %numvar。這個用法就是讓一個數(shù)值變量的值賦給文本變量,經(jīng)常用作顯示一個數(shù)值變量的值。調(diào)試的時候這么寫。
pi = 3.1415926
temp TEXTEQU %pi
%echo temp
這個是一個很重要的調(diào)試技巧。
宏過程和宏函數(shù)
前面從簡單的文本宏引出匯編期的常量與變量。如果僅僅是用在宏外的代碼中,一個文本宏作一些簡單的替換就足夠了。它們更多的是用在復(fù)雜的宏中,這些宏可以看作過程和函數(shù)。同匯編期的變量一樣,它們是用在匯編期的。
下面將不再把text macro視為宏,而把它視為文本變量。宏直接指宏過程或者宏函數(shù)。宏過程是不帶返回值的宏,而宏函數(shù)是帶返回值的宏。它們都可以帶參數(shù),也都可以有局部變量。其實可以統(tǒng)一的成為宏函數(shù),或者匯編期函數(shù)
用如下的格式創(chuàng)建一個簡單的宏
name MACRO
statements
ENDM
statements中可以進(jìn)行判斷或者循環(huán),可以說是非常的全功能。但是匯編期的函數(shù)和執(zhí)行期的函數(shù)是很不一樣的,一個是發(fā)生在匯編期的預(yù)處理,另一個是把執(zhí)行期的執(zhí)行位置改變,執(zhí)行一段代碼之后返回。
clear_eax_m MACRO
xor eax, eax
ENDM
clear_eax_p Proc
xor eax, eax
ret
clear_eax_p Endp
關(guān)于這個兩者的區(qū)別,我假定你已經(jīng)理解了,如果不理解可以參考任何一本匯編教科書,上面有完整的匯編代碼說明為什么不同。
給宏傳遞參數(shù)
參數(shù)對于函數(shù)的重要性不言而喻,對于宏的參數(shù)如下定義。
name MACRO parameterlist
statements
ENDM
簡單情況下,對于parameterlist就是參數(shù)名字用,號格開,比如:
clear_reg MACRO reg
xor reg, reg
ENDM
調(diào)用的時候,用這種格式:
clear_reg eax
對于宏過程,這個是唯一的調(diào)用格式。
參數(shù)的傳遞和執(zhí)行期的函數(shù)的參數(shù)傳遞也是很不一樣的。參數(shù)是被直接替換的。你可以作這么一個試驗:
TestMacro MACRO param
echo param
%echo param
ENDM
TextVar TEXTEQU
TestMacro TextVar
輸出的結(jié)果是TextVar和Hello。到底是怎么回事就不用我多說了。你甚至可以進(jìn)一步測試:
TestMacro MACRO param
param TEXTEQU
ENDM
TextVar TEXTEQU
TestMacro TextVar
%echo TextVar
輸出的結(jié)果是How are you。可見所謂的參數(shù)不過就是替換。參數(shù)名會被引數(shù)名給替換(引數(shù)就是調(diào)用時候傳遞過去的那些參數(shù))。由于MASM中宏這個系統(tǒng)中,所有的這些變量名的符號都是在一個共同的空間之中(呵呵,怎么聽起來像數(shù)學(xué)術(shù)語?),都是全局的東西。
對于參數(shù)可以進(jìn)行一些限定修飾,比如讓你調(diào)用的時候一定要傳遞這個參數(shù):
Clear_reg MACRO reg:REQ
xor reg, reg
ENDM
或者指定一個缺省值:
Clear_reg MACRO reg:=
xor reg, reg
ENDM
或者讓參數(shù)個數(shù)成為一個變數(shù)。
Clear_reg MACRO regs:VARARG
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -