学 Win32 汇编[34] - 宏汇编(1)
16lz
2021-04-30
学 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的原创作品,如需转载,请注明出处,否则将追究法律责任
更多相关文章
- 学 Win32 汇编[32] - 子程序进阶
- 0428作业-函数
- 使用 IntraWeb (33) - Cookie
- Delphi 正则表达式之TPerlRegEx 类的属性与方法(7): Split 函数
- 异常 - 虚拟机初始化错误 - Error occurred during initializati
- $()的四种类型参数的应用场景实例演示;以及jq转js的方法
- 使用binlog2sql工具来恢复数据库
- 快递100集成多家快递公司同城配送下单API接口代码
- 快递100集成多家快递同城配送公司查询订单API接口案例