学 Win32 汇编[34] - 宏汇编(1)


从接触 C 语言时, 我就不大喜欢宏; 但为了看懂别人的代码也不得不去了解.

宏可定义在源程序的任意位置, 但一般放在 .data 前面.
有些简单的宏可以用 equ、textequ 或 = 来代替, 但宏有更复杂的功能.

"宏" 的本质是 "替换", 但又像极了 "子过程";
所以即有宏过程(macro procedure)、也有宏函数(macro function).
它既以有参数(可以是: 常数、变量、寄存器、指令、表达式), 有时也需要像子过程一样声明.
宏可以指定哪些参数是必须的, 还可以给参数默认值.

宏可以包含数据(.data)和代码(.code)、还可以嵌套.
宏中的注释使用 ;; 如果只用 ; 将会被一起替换到代码中.

宏的功能很强大, 现在常用的 PrintDec、PrintHex、PrintString、PrintText 等等都是宏.
再强大它也只是 "文本替换".

"宏" 和 "子程序" 相比:
1、宏展开后顺序执行, 不像调用子程序跳来跳去, 这样程序会更 "快";
2、宏展开后会让代码量增大, 导致程序变 "大".

一个简单的宏:
; Test34_1.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib;定义一个 mExit 宏mExit macro    PrintLine    retendm.codesum proc v1, v2, v3    mov eax, v1    add eax, v2    add eax, v3    retsum endp;main proc    invoke sum, 11, 22, 33    PrintDec eax ;66    ;PrintLine    ;ret    mExit ;mExit 将被替换为上面两行代码main endpend main

一个代替求和函数的宏:
; Test34_2.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.libmSum macro v1, v2, v3    mov eax, v1    add eax, v2    add eax, v3endm.codemain proc    mSum 11, 22, 33    PrintDec eax ;66    PrintLine    mSum 11, 22, 33, 44, 55 ;多余的参数会被忽略    PrintDec eax ;66    PrintLine    retmain endpend main

宏参数的默认值:
; Test34_3.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib;参数 v1、v2 通过 REQ 标识说明是必备参数;参数 v3、v4 给出了默认值mSum macro v1:req, v2:req, v3:=<33>, v4:=<44>    mov eax, v1    add eax, v2    add eax, v3    add eax, v4endm.codemain proc    mSum 11, 22    PrintDec eax ;110    PrintLine    retmain endpend main

EXITM: 退出宏
; Test34_4.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.libmPrint macro    PrintText '第一行'    PrintText '第二行'    exitm    PrintText '第三行'endm.codemain proc    mPrint ;只会输出前两行    retmain endpend main

PURGE: 取消宏
; Test34_5.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.libmPrint macro    PrintText '第一行'    PrintText '第二行'    PrintText '第三行'    PrintLineendm.codemain proc    mPrint    mPrint    purge mPrint ;可用逗号隔开取消多个宏    mPrint       ;这个宏不会展开了    retmain endpend main

宏中 local 的使用:
; Test34_6.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib;从三个数中求最大数的宏mMax macro v1, v2, v3    LOCAL L1, L2 ;;如没有这句, 宏在多次展开时会让 L1、L2 重名, 这样宏会把标号名称协调好    mov eax, v1    cmp eax, v2    jge L1    mov eax, v2L1: cmp eax, v3    jge L2    mov eax, v3L2:endm.codemain proc    mMax 11, 22, 33    PrintDec eax  ;33    retmain endpend main

灵活的参数, 用到 & 操作符:
; Test34_7.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib;求最数中的最大值:mMax macro v1, v2    LOCAL L1    mov eax, v1    cmp eax, v2    jge L1    mov eax, v2L1:endm;求最数中的最小值:mMin macro v1, v2    LOCAL L1    mov eax, v1    cmp eax, v2    jle L1    mov eax, v2L1:endm;能把 JGE 或 JLE 做参数:mCom1 macro XX, v1, v2    LOCAL L1    mov eax, v1    cmp eax, v2    XX L1    mov eax, v2L1:endm;能通过参数让 J*E 变为 JGE 或 JLE:mCom2 macro X, v1, v2    LOCAL L1    mov eax, v1    cmp eax, v2    J&X&E L1    ;;这里用到特殊操作符 &    mov eax, v2L1:endm.codemain proc    mMax 11, 22    PrintDec eax ;22        mMin 11, 22    PrintDec eax ;11        mCom1 JGE, 11, 22    PrintDec eax ;22        mCom1 JLE, 11, 22    PrintDec eax ;11        mCom2 G, 11, 22    PrintDec eax ;22        mCom2 L, 11, 22    PrintDec eax ;11    retmain endpend main

特殊操作符: &、<>、%、!
&  ;替换操作符<> ;字符串传递操作符%  ;表达式操作符, 也用于得到一个变量或常量的值!  ;转义操作符; Test34_8.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib;自定义的宏mPrint macro Text    PrintText '* &Text& *'endm.codemain proc    ;该宏会把参数直接替换过去    mPrint 1234    ;* 1234 *        ;要保证参数的完整应该使用 <>    mPrint 12,34   ;* 12 *    mPrint <12,34> ;* 12,34 *        ;需要计算结果应该使用 %()    mPrint 34+12   ;* 34+12 *    mPrint %(34+12)   ;* 46 *        ;用到 &、<、>、%、! 应该使用 ! 转义    mPrint 10 !% 2 = %(10/2)!! ;* 10 % 2 = 5! *    retmain endpend main

posted on 2010-04-29 21:34 万一 阅读(4384) 评论(5) 编辑 收藏©著作权归作者所有:来自51CTO博客作者JLee79的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 学 Win32 汇编[32] - 子程序进阶
  2. 0428作业-函数
  3. 使用 IntraWeb (33) - Cookie
  4. Delphi 正则表达式之TPerlRegEx 类的属性与方法(7): Split 函数
  5. 异常 - 虚拟机初始化错误 - Error occurred during initializati
  6. $()的四种类型参数的应用场景实例演示;以及jq转js的方法
  7. 使用binlog2sql工具来恢复数据库
  8. 快递100集成多家快递公司同城配送下单API接口代码
  9. 快递100集成多家快递同城配送公司查询订单API接口案例

随机推荐

  1. Android suspend/resume flow (上篇: Use
  2. Android(安卓)View Animation Example
  3. 【Android】android按钮的四种点击事件
  4. 编译Android donut
  5. Android(安卓)的布局优化
  6. 详解Android系统中的root权限获得原理
  7. android:windowSoftInputMode用法
  8. scrollview中使用recyclerview莫名自动上
  9. Android学习笔记之mainfest文件中android
  10. 在Ubuntu上下载、编译和安装Android最新