<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      這篇文章是我花了一個晚上作的總結,從一個比較本質的角度解釋了一些宏的行為,不是教科書設置是Programmer Guide達到的程度??雌饋肀容^沒有味道,但是如果你要用起宏來你會發現我幾乎沒有說廢話。不是教你怎么去用宏,但是你看過之后也不用學了,自己試驗一下就可以寫了。雖然沒有幾個家伙還在用MASM,更少人用MACRO了,可能這個就是我另類的風格吧。

      MASM宏使用總結

      導語

      MASM(Macro Assembler)是由微軟公司提供的匯編工具,雖然有些年頭了,但是仍然存在于 vc.net這樣比較新的工具中。有很多匯編教科書以這個為對象,講述了如何用匯編去設計一個程序,作為計算機科學系學生的基礎課。但是,講述的內容大體上還是停留在5.1版,而且停留在DOS的時代。雖然提到了win32下的匯編,但是并沒有放在首要的位置。另一個被忽視的是作為MASM最大特色的宏,怎么去看待匯編工具中提供的強大的宏,以及怎么和在什么場合下使用宏,語焉不詳。本文是作者在大量使用MASM宏,搭建了一個匯編環境下的OOP系統后,作的一個總結。

      善用宏,能夠減少重復編碼,以及構建強大的功能,是重用代碼,美化代碼的一個有力的工具。宏在高級語言中是一個應該被極力避免的東西,在低級語言中確未必如此。

      宏就是預處理

      宏就是在代碼被匯編成為obj文件之前進行的預處理。由于發生在匯編期(Assembly-Time, 和高級語言中的編譯期是一個意思),所以不會給執行期帶來負擔,可以用作代碼生成工具,設置和C++中的模板一樣,用作meta-programming的工具。在MASM中宏可以分為兩種:1、 Text Macro 2、Procedure (Function) Macro。第一種宏就是和#define pi 31415926這樣的簡單的文本替換的宏,第二種就是那種帶參數,可以有局部變量,可以返回值這樣的可以看作函數或者過程的宏。下面就先從Text Macro入手,看看如何使用簡單的宏。

      簡單的文本宏

      你可以給一個字符序列指定一個符號名,然后在源代碼的其余部分用這個名字來代替這個字符序列。這個指定了名字的文本就是文本宏。說白了就是文本替換。用TEXTEQU來定義一個這樣的宏。

        name TEXTEQU <text>
        name TEXTEQU textvar
        name TEXTEQU %numvar
      

      我這里給出的使用說明和MASM Programmer Guide中給出的不大一樣,但是這個更能說明問題。我在這兒只解釋第一個用法,后面的用法將在講了“匯編期變量”之后再講。舉一些使用的例子。

        pi TEXTEQU <3.1416>
        DWPTR TEXTEQU <WORD PTR>
        arg1 TEXTEQU <[bp+4]>
      

      然后在代碼中就可以用pi這些名字來代替3.1416這些。<>表示他們是字符串,如果把不加<> 則會把你給出的字符串當作一個匯編期的文本變量來進行求值,而這樣的話會出錯的。

      匯編期的變量與常量

      這個幾個東西其實都有自己的名字,其實按照用法來說就是匯編期的常量與變量的意思。比如Text Macro(對,就是前面的文本宏)用作匯編期的文本常量,Name Assignment用作匯編期的數值變量。

      1. 定義匯編期常量

        什么是匯編期常量呢?其實也就是常量的意思,因為無論在編譯期還是執行期它都是靜態的,一旦定義之后其值不能改變?;貞浽贑中,你用#define來定義常量。但是#define可以改變一個宏所等于的值,也就是說常量與否需要你的維護(編譯器會給出一個警告)。在MASM 中有一個關鍵字專門用來定義常量,嘗試改變常量的值會得到一個錯誤提示。

          name EQU expression
          name EQU <text>
        

        第一個是用作定義個“數值”常量,第二個是用作定義“文本”常量。以后要特別區分開文本和數值。

      2. 定義匯編期文本變量

        匯編期文本變量是對“text macro”的另外一個看法。其實它們是同一個事情。當你定義了一個文本宏之后,你可以把那個宏名看作匯編期文本變量的名字,被宏名替換的文本內容作為變量的文本值。

        那么前面說過的第二種用法:name TEXTEQU textvar就很好理解了。就是讓把一個文本變量賦給另一個文本變量。比如:

          talent TEXTEQU <genius>
          taowen TEXTEQU talent
        

        第一行定義了一個名字為talent的匯編期文本變量,第二行把talent的值賦給了名為 taowen的變量。從結果上看這個和:

          talent TEXTEQU <genius>
          taowen TEXTEQU <talent>
        

        是一樣的,但是第二種做法是先因為文本宏替換的作用把talent變成了genius。實際的效果是這樣的:

          taowen TEXTEQU <genius>
        
      3. 顯示文本變量的內容

        在C中經常用printf,在運行期顯示一些變量的內容來進行調試。而在MASM中則用echo來在匯編期顯示文本變量的內容。

          china TEXTEQU <great country>
          %echo china
        

        這樣會在匯編時的命令行中出現great country。如果你把%號去掉,則顯示的是china。你應該可以推測出%是干什么的了,就是對一個變量進行求值。

      4. 定義匯編期數值變量

        常量有兩種那么變量也應該有兩種。這里就介紹匯編期數值變量的用法。

          name = expression
        

        expression是一個數值表達式,比如:

          val = 3+4
        

        此時val就是一個數值變量,其值為7。你也可以這么寫:

          valexp TEXTEQU <3+4>
          val = valexp
        

        看上去好像式把一個文本變量賦給了數值變量,進行了類型轉換(呵呵,效果是一樣的)。其實實際上是把3+4寫到了valexp處,因為文本宏進行了文本替換。

      5. 把數值變量賦給文本變量

        前面我們看到了如何“把文本變量賦給數值變量”,那么反過來呢?

          val = 3+4
          valexp TEXTEQU val
        

        結果是提示錯誤:STest.asm(15) : error A2051: text item required。匯編器說需要文本項,那么我們加上<>就好了。

          val = 3+4
          valexp TEXTEQU 
        

        用%echo valexp檢查一下你就會發現,并不是如你所愿的顯示的是7,而是val。這個是因為<>使得匯編器認為val是一個字符串,由于數值變量不是文本替換的宏,并不會把val替換為7,所以當然顯示的是val。正確的做法是:

          val = 3+4
          valexp TEXTEQU %val
        

        %號和前面的用法一樣,是用作求值。回憶一開始介紹的文本宏的用法中的第三條就是: name TEXTEQU %numvar。這個用法就是讓一個數值變量的值賦給文本變量,經常用作顯示一個數值變量的值。調試的時候這么寫。

          pi = 3.1415926
          temp TEXTEQU %pi
          %echo temp
        

        這個是一個很重要的調試技巧。

      宏過程和宏函數

      前面從簡單的文本宏引出匯編期的常量與變量。如果僅僅是用在宏外的代碼中,一個文本宏作一些簡單的替換就足夠了。它們更多的是用在復雜的宏中,這些宏可以看作過程和函數。同匯編期的變量一樣,它們是用在匯編期的。

      下面將不再把text macro視為宏,而把它視為文本變量。宏直接指宏過程或者宏函數。宏過程是不帶返回值的宏,而宏函數是帶返回值的宏。它們都可以帶參數,也都可以有局部變量。其實可以統一的成為宏函數,或者匯編期函數

      用如下的格式創建一個簡單的宏

        name MACRO
       statements
        ENDM
      

      statements中可以進行判斷或者循環,可以說是非常的全功能。但是匯編期的函數和執行期的函數是很不一樣的,一個是發生在匯編期的預處理,另一個是把執行期的執行位置改變,執行一段代碼之后返回。

        clear_eax_m MACRO
         xor eax, eax
        ENDM
        clear_eax_p Proc
       xor eax, eax
       ret
        clear_eax_p Endp
      

      關于這個兩者的區別,我假定你已經理解了,如果不理解可以參考任何一本匯編教科書,上面有完整的匯編代碼說明為什么不同。

      給宏傳遞參數

      參數對于函數的重要性不言而喻,對于宏的參數如下定義。

        name MACRO parameterlist
        statements
        ENDM
      

      簡單情況下,對于parameterlist就是參數名字用,號格開,比如:

        clear_reg MACRO reg
       xor reg, reg
        ENDM
      

      調用的時候,用這種格式:

        clear_reg eax
      

      對于宏過程,這個是唯一的調用格式。

      參數的傳遞和執行期的函數的參數傳遞也是很不一樣的。參數是被直接替換的。你可以作這么一個試驗:

        TestMacro MACRO param
       echo param
       %echo param
        ENDM
        TextVar TEXTEQU <Hello>
        TestMacro TextVar
      

      輸出的結果是TextVar和Hello。到底是怎么回事就不用我多說了。你甚至可以進一步測試:

        TestMacro MACRO param
       param TEXTEQU <How are you>
        ENDM
        TextVar TEXTEQU <Hello>
        TestMacro TextVar
        %echo TextVar
      

      輸出的結果是How are you??梢娝^的參數不過就是替換。參數名會被引數名給替換(引數就是調用時候傳遞過去的那些參數)。由于MASM中宏這個系統中,所有的這些變量名的符號都是在一個共同的空間之中(呵呵,怎么聽起來像數學術語?),都是全局的東西。

      對于參數可以進行一些限定修飾,比如讓你調用的時候一定要傳遞這個參數:

        Clear_reg MACRO reg:REQ
       xor reg, reg
        ENDM
      

      或者指定一個缺省值:

        Clear_reg MACRO reg:=<eax>
       xor reg, reg
        ENDM
      

      或者讓參數個數成為一個變數。

        Clear_reg MACRO regs:VARARG
       FOR reg, <regs>
        xor reg, reg
       ENDM
        ENDM
      

      不過要注意的是VARARG修飾的參數必須是參數中的最后一個。

      讓宏返回一個值

      宏過程和宏函數的區別在于是否有返回值。當然這里的返回值和執行期的函數的返回值也是很不一樣的。執行期的函數是通過eax來傳遞返回值的。而這里,也不過是直接替換而已。返回值的語法是這樣的:

      EXITM textitem
      

      一個宏函數可以有多個EXITM,就像C中的函數可以有多個return一樣。不過必須返回值一致。看一個簡單的例子

        Who MACRO
       EXITM <taowen>
        ENDM
        %echo Who()
      

      結果是顯示taowen。如果把()去掉,則顯示的是who??梢妼τ诤旰瘮档恼{用一定要加上 ()。而調用宏過程則不能加()??匆粋€有趣的例子:

        Who MACRO temp
       %echo temp
        ENDM
        Who()
      

      顯示的結果是()。說明()被當作傳遞給宏過程的參數了。

      可以比較隨意的使用返回值,可以把返回值這么用。

        Who MACRO
       EXITM <taowen>
        ENDM
        Who() TEXTEQU <genius>
      

      這樣就定義了匯編期文本變量,值為genius??梢姾旰瘮悼梢杂迷谌魏挝谋咀兞靠梢猿霈F的地方,很多地方可以把高級語言中函數中那些類推過來。

      局部變量

      宏中可以有局部變量,它看起來像局部的,實際上不過是一些名稱上的小技巧。

      對于局部變量有兩點事實:1、在函數外無法訪問,2、在對函數的不同次的調用中其值應該不受前次調用的影響。

        TestMacro MACRO
        LOCAL LocalVar
       %echo LocalVar
       LocalVar TEXTEQU <Hello>
        ENDM
      

      如果對于函數的調用每次之間會互相影響,那么這么調用:

        TestMacro
        TestMacro
      

      第一次會產生一個未定義變量的錯誤,而第二次就會輸出Hello。事實上,由于LocalVar 是LOCAL的。所以兩次都是未定義錯誤。這個就體現了局部變量的多次調用的獨立性。

      下面我們來揭穿局部變量的底牌。不用我多敘述,直接看看這個你就明白了:

        TestMacro MACRO
        LOCAL LocalVar
       echo LocalVar
        ENDM
        TestMacro
        TestMacro
      

      輸出的結果是:??0000與??0001。這個就是局部變量的實際名字。局部變量就是通過怪怪的名字讓外部無法訪問(你不知道它是什么名字),然后在每次展開同一個宏的時候用不同的名字替換局部變量的名字,使得多次調用之間不會互相影響。

      其實你可以試驗一下這個:

        ??0000 TEXTEQU <Hello>
        TestMacro MACRO
        LOCAL LocalVar
       %echo LocalVar
        ENDM
        TestMacro
      

      顯示的結果是Hello,這樣就在一個宏過程(函數)的外部訪問了局部變量。

      文本操作

      MASM內置了兩套文本操作功能,一個是宏函數,另一個是Directive。功能是一樣的,但是提供了表達上的靈活性。

      name CATSTR [[textitem1 [[, textitem2]] ...]]
      name INSTR [[position,]] textitem1, textitem2
      name SIZESTR textitem
      name SUBSTR textitem, position [[, length]]
      

      這一套是Directive,作用分別是:連接文本,查找子文本,獲得文本長度,取子文本。

      @CatStr( string1 [[, string2...]] )
      @InStr( [[position]], string1, string2 )
      @SizeStr( string )
      @SubStr( string, position [[, length]] )
      

      這一套是宏函數。用一個例子顯示兩套其實是一樣的:

      taowen TEXTEQU @CatStr(<He is >, <genius>)
      %echo taowen
      
      taowen CATSTR <He is >, <genius>
      %echo taowen
      

      可以看到兩個例子輸出的都是He is genius。有兩點需要注意:1、@CatStr這樣的宏函數可以作為左值,被用來賦值。2、@CatStr這樣的宏函數對于參數并不自動求值,當行為和你想的不一樣的時候,加上%。

      對于具體的使用不是很難,試驗一下就可以知道了。一點就是第一個字符的索引是1,而不是C中的0。

      %與求值

      %可能是最難使用的語法了。一般就是行為和你想的不一樣的時候,加上%試驗一下。%與 <>與!等,構成了一團糟。

      一般情況下,你不用%號。用%可以把數值變量轉變為文本變量。可以用%號強制取出文本的值。比如:

        Index = 0
        NameT CATSTR <Person>, %Index
        %NameT TEXTEQU <taowen>
        %echo Person0
      

      先對Index用%就是把數值變成文本,第二個%就是把NameT變成Person0。這里也演示了一個產生變量名的很重要的技巧,只要把Index進行一些遞增,就能夠構建一個變量的數組了。

      <>可以一定程度上放置被求值,不過大部分情況下由于文本宏的替換不受影響,所以仍然取到的是替換后的值。!用來取消符號原有的意思。比如:

        Symbol CATSTR <Go >, <!,>, <Go>
        %echo Symbol
      

      輸出的結果是Go, Go。如果不加!則,號會導致錯誤。有趣的是如果你在第二個Go后面加上 !本來應該是Go, Go!。結果確實一個缺少右尖括號的錯誤,原來是!把>的原有意思變化了,不再表示結束了。如果你這樣:

        Symbol CATSTR <Go >, <!,>, <Go!>>
        %echo Symbol
      

      得出的就是Go, Go>??闯鰜硎窃趺椿厥铝税?。要產生!,就這么寫:

        Symbol CATSTR <Go >, <!,>, <Go!!>
        %echo Symbol
      

      關于什么時候用<>什么時候不用,我的看法是最好能用<>就用<>。具體為什么,是因為能夠加大適用范圍。

      在宏中進行循環

      循環有四種:WHILE,REPEAT,FOR,FORC。語法如下:

        WHILE expression
       statements
        ENDM
        REPEAT expression
       statements
        ENDM
        FOR parameter [[:REQ | :=default]] , <argument [[, argument]]...>
       statements
        ENDM
        FORC parameter, <string>
       statements
        ENDM
      

      WHILE與REPEAT從用法到效果是一樣的,至少我認為是一樣的。expression要求值為一個數值,可以用EQ(等于),LT(小于)這些判斷Operator來比較數值。

        I = 0
        WHILE I LT 10
       Temp TEXTEQU %I
       %echo Temp
       I = I + 1
        ENDM
      

      輸出的結果就是0一直到9。

      FOR與FORC是專門用途的循環,一個是用于取得一個參數列表中的各個參數,另一個是逐個取出一個字符串中的每個字符。各舉兩個例子就可以明白:

        TestMacro MACRO params:VARARG
       FOR param, <params>
        %echo param
       ENDM
        ENDM
        TestMacro arg1, arg2, arg3
      

      顯示的結果是arg1然后是arg2然后是arg3。

        FORC char, <Hello>
       %echo char
        ENDM
      

      分別顯示的是H和e和l和l和o。

      在宏中進行判斷

      判斷很簡單了,不過有很多種IF,IFDEF,IFIDN,IFE,IFNDEF,IFDIF。使用上沒有什么值得注意的都比較簡單。分別是判斷數值,判斷符號是否定義,判斷兩個文本是否一致。

      關于宏還有定義在宏中的宏,OPATTR, SIZEOF, LENGTHOF, 等等許多比較高級的東西。不過我相信有前面講述的基礎,這些東西的使用不過是查查手冊的事情。

      Good luck, that is all.

      posted on 2004-05-24 19:04  taowen  閱讀(3179)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 成人区精品一区二区不卡| 国产草草影院ccyycom| 国产草草影院ccyycom| 精品一区二区中文字幕| 人妻另类 专区 欧美 制服| 国产精选一区二区三区| 精品国产乱码久久久久app下载 | 国产精品青青在线观看爽香蕉| 泗洪县| 日韩精品成人一区二区三| 骚虎三级在线免费播放| 国产成人欧美一区二区三区| 人妻伦理在线一二三区| 日韩精品一区二区亚洲av| 极品少妇被后入内射视| 开心五月婷婷综合网站| 天堂av成人网在线观看| jk白丝喷浆| 北条麻妃42部无码电影| 欧美亚洲国产一区二区三区| 国产日本一区二区三区久久| 99久久亚洲综合精品成人网| 国产午夜大地久久| 久久婷婷五月综合色丁香花| 国产在线视频导航| 永久不封国产av毛片| 国产va在线观看免费| 亚洲区成人综合一区二区| 国内精品久久人妻无码不卡| 天天爽夜夜爱| 99久久久无码国产麻豆| 久久高潮少妇视频免费| 国产精品国产三级国产试看| 乱色熟女综合一区二区三区| 精品国产中文字幕在线看| 亚洲精品一区二区天堂| 丁香五月激情综合色婷婷| 开心五月深深爱天天天操| 久久av色欲av久久蜜桃网| 欧美人与动牲交精品| 泰安市|