NASM手冊閱讀筆記(3) - 預處理器之宏定義


簡要說明

  所謂預處理器,就是在編譯階段由編譯器解釋執行的代碼,所以代碼的結果應該是在編譯階段就能確定,否則就會報錯。
  強大的預處理器可以簡化和增強匯編代碼的能力。
 

 單行宏

%define / %idefine 

基本格式:

  %define     a           mov ax,1
  %define     a(p1,p2)    mov p1,p2
       %define    a(p1,p2,p3) P3 p1,p2

說明:

宏可以重載,也就是說可以定義米子相同參數不同的宏,使用的時候編譯器會根據參數類確定用哪一個,但是如果定義了不帶參數的,那么就不能重載了    
%define 是區分大小寫的所以
%define Foo 和 %define foo 是不一樣的
%idefine 是忽略大小寫的版本
    

%xdefine/%ixdefine

說明:

與%define的區別是展開的時機不同
%define 是在使用的時候展開
%xdefine 是在定義的時候被展開,其中的區別可以用如下代碼演示
 

舉例1:

#define a   1    ; A=1
#define b   a    ; 因為是調用時展開,所以具體的內容得調用的時候確定A的內容后才能展開
#define a  0   ; A被重定義 = 0
    
mov  ax, b
此時展開b
step1.  mov ax, a
step2. mov ax, 0
    

舉例2

使用%xdefine 在定義是展開
#xdefine a   1    ; A=1
#xdefine b   a    ; 定義時展開,所以實際上就是  #xdefine b 1
#xdefine a  0   ; A被重定義 = 0
    
mov  ax, b
此時展開b
step1.  mov ax, b
step2. mov ax, 1
    

%+

  說明:

字符連接,相當於MASM和C中的 & 的作用
舉例
#define   a(b)        student. %+ b
a(id)   =>     student.id
 

%undef

說明:

取消宏定義

 

%assign/%iassign

說明:

定義常數的專用的%define
區別就在於%assign只能用於定義常數,同時定義形式可以是可以是表達式,
比如
%assign   x   1       ; x=1
%assign   x  x+1  ;他會計算表達式的值所以  x=2 不是 1+1
    

多行宏

%macro / %imacro

  基本格式:

%macro  宏名稱 參數數量                      
        push    ebp                
        mov     ebp,esp                
        sub     esp,%1               
%endmacro

  說明:

參數數量是一個數字,表示這個宏接收幾個參數 
在宏定義中用 %數字來表示 第幾個參數,比如
%1 表示第一個參數 %2 表示第二個參數,索引從1 開始,%0表示的是參數的個數
可以重載帶不同參數數量的宏,因為就算不帶參數也是 寫 0 所以這里沒有不帶參數的宏定義后就不能重載的限制

使用

宏名字   參數1, 參數2 ,{  我是帶, 逗號的參數,需要使用括號括起來表示一個整體}
    

宏中的本地標簽

在MASM中宏中的本地標簽用的是.label的形式,nasm中使用 %%label的形式,這里注意區別

普通代碼中的本地標簽: .LABEL

宏定義中的本地標簽:  %%LABEL    

%macro a 0 
  jnz    %%skip
  ret
  %%skip:
%endmacro
    

貪婪宏定義

    在宏定義的參數數量后邊加上 + 加號,就表示這是一條貪婪宏定義
    其含義就是多出來的參數被當成一個整體作為最后一個參數傳入
    
比如我如下兩個宏的定義
%macro   M1  2+
%macro M2 2
    
那么
M1    PARAM1,PARAM2,PARAM3,PARAM4
M2    PARAM1, {PARAM2,PARAM3,PARAM4}
這兩個調用完全等價
    

指定參數范圍

%macro   M1   1-4    默認參數2, ,默認參數4
    
這表示 這個宏的參數是 1- 4 個,有點類似c++的默認參數語法: void   m(x1, x2=1,x3=3,x4=4);
其完整含義如下:
第一個參數的必須的
如果沒有第二個參數,就使用默認參數2,
如果沒有第三個參數,就使用默認參數3,因為沒有默認參數3, 就使用空
如果沒有第四個參數,就使用默認參數4
 
注意:支持通配符* 表示任意 比如 0-* 表示隨便幾個參數
    支持貪婪定義,比如 0 - 4+
    

參數的連接 

就是MASN和C中& 和&& 的作用,在單行宏定義中需要使用 符號 %+來連接,多行宏就不需要了,可直接使用
比如
%1abc ,abc%1
但是如果是數字則要這樣
%{1}123
123%1
    

.nolist

作用的在生成list文件的時候不要抱宏擴展出來,你生成list文件是希望將指令對照着2進制代碼去看的,這個時候如果保留宏,而不是將宏給擴展出來的話,可讀性會更好一點。
    
格式
%macro foo 1.nolist 
%macro bar 1-5+.nolist a,b,c,d,e,f,g,h 
    
    

%roate

格式:

%roate 左移個數

說明:

多行宏定義中的參數左移, 負數就是右移
比如
現在的參數是
%1  %2  %3  %4
a     b     c     d
使用
%roate 2 結果如下
%1  %2  %3  %4
c   d     a      b
 
有什么用呢? 

舉例

%macro  multipush 1-*                 
%rep  %0                
                push    %1          
                %rotate 1          
%endrep              
%endmacro 
 
那么我無論 multipush  跟幾個寄存器,他都能正常push
同理
 
%macro  multipop 1-*                
%rep %0          
                %rotate -1               
                pop     %1          
%endrep               
%endmacro 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM