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

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

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

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

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

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


一个简单的宏:


; Test34_1.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib ;定义一个 mExit 宏
mExit macro
  PrintLine
  ret
endm .code
sum proc v1, v2, v3
  mov eax, v1
  add eax, v2
  add eax, v3
  ret
sum endp
;
main proc
  invoke sum, , ,
  PrintDec eax ;66
;PrintLine
;ret
  mExit ;mExit 将被替换为上面两行代码
main endp
end main

一个代替求和函数的宏:


; Test34_2.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib mSum macro v1, v2, v3
  mov eax, v1
  add eax, v2
  add eax, v3
endm .code
main proc
  mSum , ,
  PrintDec eax ;66
  PrintLine
  mSum , , , , ;多余的参数会被忽略
  PrintDec eax ;66
  PrintLine
  ret
main endp
end main

宏参数的默认值:


; Test34_3.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib ;参数 v1、v2 通过 REQ 标识说明是必备参数
;参数 v3、v4 给出了默认值
mSum macro v1:req, v2:req, v3:=<>, v4:=<>
  mov eax, v1
  add eax, v2
  add eax, v3
  add eax, v4
endm .code
main proc
  mSum ,
  PrintDec eax ;110
  PrintLine
  ret
main endp
end main

EXITM: 退出宏


; Test34_4.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib mPrint macro
  PrintText '第一行'
  PrintText '第二行'
  exitm
  PrintText '第三行'
endm .code
main proc
  mPrint ;只会输出前两行
  ret
main endp
end main

PURGE: 取消宏


; Test34_5.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib mPrint macro
  PrintText '第一行'
  PrintText '第二行'
  PrintText '第三行'
  PrintLine
endm .code
main proc
  mPrint
  mPrint
  purge mPrint ;可用逗号隔开取消多个宏
  mPrint  ;这个宏不会展开了
  ret
main endp
end main

宏中 local 的使用:


; Test34_6.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib ;从三个数中求最大数的宏
mMax macro v1, v2, v3
  LOCAL L1, L2 ;;如没有这句, 宏在多次展开时会让 L1、L2 重名, 这样宏会把标号名称协调好
  mov eax, v1
  cmp eax, v2
  jge L1
  mov eax, v2
L1: cmp eax, v3
  jge L2
  mov eax, v3
L2:
endm .code
main proc
  mMax , ,
  PrintDec eax ;33
  ret
main endp
end main

灵活的参数, 用到 & 操作符:


; Test34_7.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib ;求最数中的最大值:
mMax macro v1, v2
  LOCAL L1
  mov eax, v1
  cmp eax, v2
  jge L1
  mov eax, v2
L1:
endm ;求最数中的最小值:
mMin macro v1, v2
  LOCAL L1
  mov eax, v1
  cmp eax, v2
  jle L1
  mov eax, v2
L1:
endm ;能把 JGE 或 JLE 做参数:
mCom1 macro XX, v1, v2
  LOCAL L1
  mov eax, v1
  cmp eax, v2
  XX L1
  mov eax, v2
L1:
endm ;能通过参数让 J*E 变为 JGE 或 JLE:
mCom2 macro X, v1, v2
  LOCAL L1
  mov eax, v1
  cmp eax, v2
  J&X&E L1 ;;这里用到特殊操作符 &
  mov eax, v2
L1:
endm .code
main proc
  mMax ,
  PrintDec eax ;22
 
  mMin ,
  PrintDec eax ;11
 
  mCom1 JGE, ,
  PrintDec eax ;22
 
  mCom1 JLE, ,
  PrintDec eax ;11
 
  mCom2 G, ,
  PrintDec eax ;22
 
  mCom2 L, ,
  PrintDec eax ;11
  ret
main endp
end main

特殊操作符: &、<>、%、!


&  ;替换操作符
<> ;字符串传递操作符
% ;表达式操作符, 也用于得到一个变量或常量的值
! ;转义操作符

; Test34_8.asm
.386
.model flat, stdcall include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib ;自定义的宏
mPrint macro Text
  PrintText '* &Text& *'
endm .code
main proc
;该宏会把参数直接替换过去
  mPrint ;* 1234 *
 
;要保证参数的完整应该使用 <>
  mPrint , ;* 12 *
  mPrint <,> ;* 12,34 *
 
;需要计算结果应该使用 %()
  mPrint + ;* 34+12 *
  mPrint %(+) ;* 46 *
 
;用到 &、<、>、%、! 应该使用 ! 转义
  mPrint !% = %(/)!! ;* 10 % 2 = 5! *
  ret
main endp
end main

学 Win32 汇编[34] - 宏汇编(1)的更多相关文章

  1. ASM-51 宏汇编使用手册

    A51与ASM51基本相同   ASM-51 宏汇编主要用来开发Inter8051系列单片机,它具有宏处理,数据处理,列表处理和条件处理等多种功能.源程序的编写完全采用 Inter标准助记符和行格式. ...

  2. 宏汇编软件MASM51的使用

    单片机开发可以用手工汇编和机器汇编两种方法.采用手工汇编就是先编写出汇编程序,然后对照单片机汇编表手工将汇编程序翻译成机器码,最后将机器码一个一个地送入开发仿真器的RAM中去进行调试. 由于采用手工汇 ...

  3. ARM标准汇编与GNU汇编

    ARM标准汇编与GNU汇编 http://www.cnblogs.com/hnrainll/archive/2011/05/17/2048315.html

  4. 学 Win32 汇编[21] - 传送指令: MOV、LEA、XCHG、XLATB、XLAT、MOVZX、MOVSX

    汇编指令的一般性要求: 1.两个操作数的尺寸必须一致; 2.操作数不能同为内存. MOV(Move): 最常用的数据传送指令 ;该指令不影响 EFlags ;指令格式: (其中的 r.m.i 分别表示 ...

  5. 学 Win32 汇编[33] - 探讨 Win32 汇编的模块化编程

    我觉得所谓的模块化有两种: "假模块化" 和 "真模块化". 所谓 "假模块化" 就是通过 include 指令把 *.inc 或 *.as ...

  6. 学 Win32 汇编[28] - 跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等

    http://www.cnblogs.com/del/archive/2010/04/16/1713886.html 跳转指令分三类:一.无条件跳转: JMP;二.根据 CX.ECX 寄存器的值跳转: ...

  7. 学 Win32 汇编[20]: 洞察标志寄存器

    15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 NT IOPL OF DF IF TF SF ZF AF PF CF 未使用 嵌套标志 I/O权限标志占2位 溢出标志 方向 ...

  8. 学 Win32 汇编[22] - 逻辑运算指令: AND、OR、XOR、NOT、TEST

    AND: 逻辑与 ;该指令会置 CF=OF=; 其结果影响 SF.ZF.PF ;指令格式: AND r/m, r/m/i ; Test22_1.asm - 使用 AND 运算将一个数的第二.四位清零 ...

  9. 从零开始学安全(三十七)●VM汇编环境搭建

    需要下载 vm 虚拟机 破解版连接 链接:https://pan.baidu.com/s/1r9MyPkNBmiYhQ8bdUxPmvQ 提取码:2o98 镜像文件和开发环境 链接:https://p ...

随机推荐

  1. BZOJ.4816.[SDOI2017]数字表格(莫比乌斯反演)

    题目链接 总感觉博客园的\(Markdown\)很..\(gouzhi\),可以看这的. 这个好像简单些啊,只要不犯sb错误 [Update] 真的算反演中比较裸的题了... \(Descriptio ...

  2. 钻牛角尖还是走进死胡同--shell脚本根据名称获得 dubbo 服务的 pid

    到了下午,突然觉得坐立不安,可能是因为中午没有休息好.老大不小了还在做页面整合的事情,这是参加工作时就干的工作了.然后突然想去挑战高级一点的缺陷排查,结果一不小心就钻了一个牛角尖.启动 dubbo 服 ...

  3. Stf-windows版本

    Stf-windows Stf 原项目地址:https://github.com/openstf/stf . 介绍 用于Web端设备远程管理 系统支持 支持Android版本2.3.3 (SDK10) ...

  4. Xtreme8.0 - Kabloom dp

    Xtreme8.0 - Kabloom 题目连接: https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/kablo ...

  5. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort 暴力

    B. Batch Sort 题目连接: http://codeforces.com/contest/724/problem/B Description output standard output Y ...

  6. 什么是NAS

    个人理解: 1.NAS本身不是一种传输协议,只是一个名词而已,就是一个网络储存. 2.NAS系统本身就是一个Linux,也不是什么发行版,就是在Linux下实现了网络储存. 3.NAS系统里面实现了很 ...

  7. POJ 1743 Musical Theme (字符串HASH+二分)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 15900   Accepted: 5494 De ...

  8. 各种版本的ST-LINK仿真器

    1.ST官方正式出版了两种仿真器:ST-LINK.ST-LINK/V2,其他型号(ST-LINK II,ST-LINK III,…)要么是国内公司生产,要么是开发板自带的:2.在ST官网ST-LINK ...

  9. a标签连接空标签的方法

    在写页面时,想把a标签设置成空链接,方便后面数据的连接可以有几种方法. 1. <a herf=""></a> 这种方法会默认打开本页面,重新刷新一次页面. ...

  10. linux 内核升级2 转

    linux内核升级 一.Linux内核概览 Linux是一个一体化内核(monolithic kernel)系统. 设备驱动程序可以完全访问硬件. Linux内的设备驱动程序可以方便地以模块化(mod ...