zoukankan      html  css  js  c++  java
  • 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 
  • 相关阅读:
    汇编结合vc6的使用
    QT textbroswer textedite Qlist的常用的操作函数
    QT Qdialog的对话框模式以及其关闭
    QT生成的exe在其他电脑打开
    c++实现服务器和多个客户端的实时群聊通信
    c++ 实时通信系统(基础知识TCP/IP篇)
    c++的并发操作(多线程)
    六种Socket I/O模型幽默讲解
    c++字符串的输入
    字符串 与其他数据类型的转换,以及字符创的常用操作
  • 原文地址:https://www.cnblogs.com/alwaysking/p/12287116.html
Copyright © 2011-2022 走看看