NASM手册阅读笔记 - 预处理器之宏定义

简要说明

  所谓预处理器,就是在编译阶段由编译器解释执行的代码,所以代码的结果应该是在编译阶段就能确定,否则就会报错。

  强大的预处理器可以简化和增强汇编代码的能力。

 单行宏

%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 

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值