汇编语言 程序设计
第 8章 高级语言汇编技术
◆ 宏汇编
◆ 重复汇编
◆ 条件汇编伪指令
汇编语言 程序设计
8.1 宏汇编
在编写汇编语言程序的过程中,有时某个程序
段要出现许多次,有时只是参数不同,但功能完全
一样,则这样的程序段可以定义成一个指令,并且
称它为宏指令。
8.1.1 宏定义
若想在汇编语言中使用宏指令,就要定义一个
宏。按照是否使用参数,可以将宏指令分为如下两
种格式。
1,不带参数的宏定义
宏指令名 MACRO┇ 宏体
ENDM
汇编语言 程序设计
2.带参数的宏定义:
宏指令名 MACRO 形参 1,形参 2,…
┇ 宏体
ENDM
【例 8.2】将两个存储单元数据交换的程序段定义成一个宏指
令 EXCH_MEM。
EXCH_MEM MACRO MEM_1,MEM_2,REG
MOV REG,MEM_1
XCHG REG,MEM_2
MOV MEM_1,REG
ENDM
MEM_1,MEM_2,REG是形式参数,形参可以是多个,各个形参
之间用逗号相隔。对于带参数的宏定义,宏体中程序段有些部分允
许宏调用时作适当修改。在宏定义中,把允许修改的分用形式参数
(简称形参 )来表示,当宏调用时就用相应的实参数来取代。
汇编语言 程序设计
8.1.2 宏调用和宏展开
1,宏调用
在汇编语言中使用已定义过的宏指令, 称
为宏调用 。 按照宏指令定义的格式, 宏调用也
可分为两种格式 。
(1) 无参数宏调用:宏指令名
(2) 带参数宏调用:宏指令名 实参 1,实参 2,…
汇编语言 程序设计
2,宏展开
当宏汇编程序扫描到宏指令语句 (即宏调
用 )时,宏汇编程序就把宏指令定义中宏体的
程序段代码替代宏指令语句。若是带参数的宏
调用,则同时用相应的实参替代宏体中对应形
参的位置,并对原有宏体代码作修改。
下面是一个源程序的列表文件,它展示了
宏定义、宏调用和宏展开的全部过程。在列表
文件中,左边带, +” 号的指令是宏汇编程序
在宏展开时自动生成的指令。宏定义本身不生
成任何目标代码,宏指令语句本身也不生成目
标代码,它仅表示宏调用出现的位置。
汇编语言 程序设计
EXCH_MEM MACRO MEM_l,MEM_2,REG
MOV REG,MEM_1
XCHG REG,MEM_2
MOV MEM_1,REG
ENDM
DATA SEGMENT
DA_W1 DW 55AAH
DA_W2 DW 6688H
DATA ENDS
CODE SECMENT
ASSUME CS,CODE,DS,DATA,SS,STACK
START,MOV AX,DATA
MOV DS,AX
┇; 宏调用和宏展开
EXCH_MEM DA_W1,DA_W2,AX ; 宏指令语句
+ MOV AX, DA_Wl
+ XCHG AX,DA_W2
+ MOV DA_W1,REG

MOV AH,4CH
INT 21H
CODE ENDS
END START
汇编语言 程序设计
8.1.3 宏调用中的参数使用
为了宏定义和引用的某些特殊需要, 有时实参
是由字符, 空格等特殊符号组成的, 因此汇编程
序支持几个具有特定含义的运算符 。
1,连接运算符 &
在宏定义中, 如果形式参数与其它字符连接在
一起, 或形式参数出现在字符串之中, 那么, 就
必须使用连接运算符 (&)。 在宏指令定义的具体使
用时, 连接操作符 &可以在形参的前面, 也可在形
参的后面 。 在宏指令展开时, 对应形参的实参就
与它前面或后面的符号连接在一起构成一个新的
符号 。
汇编语言 程序设计
【 例 8.3】 宏指令 SHIFT_N功能是:对某一个寄存器进行
由 COUNT确定的移位次数, 由 DIRECT确定逻辑或算术左/右
移位, 移位的方向可通过 &将 S和 DIRECT对应的实参连接起来 。
SHIFT_N MARCO REG,DIRECT,COUNT
MOV CL,COUNT
S&DIRECT REG,CL
ENDM
如 SHIFT_N BX,HR,3的宏指令的展开为:
+ MOV CL,3
+ SHR BX,CL
这样就实现了使 BX逻辑右移 3位 。 形参 DIRECT被实参 HR
代替, 通过连接符 &将 S和 HR连接成 SHR。 同理 SHIFT_N AX,
HL,5可实现 AX逻辑左移 5位 。
汇编语言 程序设计
2,文本操作符 < >
文本操作符是一对尖括号 <>,用它括起来的内容将作为一个字符串来进行形式参数的整体替换 。 在宏引用时, 如果实参内包
含逗号, 空格等间隔符, 则必须使用该操作符, 以保证实参的完整性 。 如果实参是某个具有特殊含义的字符, 为了使它只表示该
字符本身, 也需要用该运算符括起来 。
NUMBER MACRO THEDATA
DB THEDATA
ENDM
假设在程序中调用此宏指令:
DATA SEGMENT
NUMBER <1,3,5>
DATA ENDS
则宏展开为:
DATA SEGMENT
+ DB 1,3,5
DATA ENDS
如果不加 < >,则在宏展开为:
+ DB 1 ; 而 3,5按规则被忽略
汇编语言 程序设计
3,表达式操作符 %
进行宏调用时, 如要在实参中使用, %,, 则在宏指令调用
时宏汇编程序将获取, %, 后常数表达式的值作为参数, 而非表
达式本身, 如:
NUMBER MACRO X,Y,Z,
DB X,Y,Z
ENDM
若宏调用为:
I EQU 10
J EQU 50
NUMBER 16,% I+J,% J-I
则相应的宏展开为:
+ DB 16,60,40
汇编语言 程序设计
4,字符操作符 !
字符操作符 !的使用表明,, !” 后的字符不是特殊字符, 而
是普通字符 。 这样对于包含在, <”,, >”,, !,,, %” 之
间的文本串, 汇编程序将能以普通字符处理 。 如将, !” 作为普
通字符, 则使用 !! 。
例如宏指令定义:
DEFIN_ST MACRO STRING
DB ‘ &String&S’
ENDM
则宏调用:
DEFIN_ST <Please Input a Integer( !>0), $>
其宏展开为:
+ DB ‘ Please Input a Integer( >0), $’
汇编语言 程序设计
8.1.4 宏嵌套
宏指令定义中还含有宏定义或者是宏指令的定义中含有宏调用,这两种情况都称为宏嵌套 。
1,宏定义中嵌套宏定义
ABCD_1 MACRO

ABCD_2 MACRO

ENDM

ENDM
【 例 8.4】 宏指令定义中嵌套宏定义实例
INIT_1 MACRO X,Y,Z
SHIFT_&Y MACRO
MOV CL,X
S&Z Y,CL
ENDM
ENDM
如采用下面的宏调用:
INIT_1 2,BX,AR ; 即将 BX算术右移 2位的宏指令
则相应的宏展开为:
+ SHIFT_BX MACRO
+ MOV CL,2
+ SAR BX,CL
+ ENDM
汇编语言 程序设计
2,在宏定义中嵌套宏调用
在宏定义中嵌套宏调用的基本形式为:这种嵌套形式比
较简单, 只需在宏定义中 (像在程序中一样 )写出宏指令即可 。
但必须先定义, 后调用 。
ABCD_l MACRO ; 定义一个宏

ENDM
ABCD_2 MACRO
ABCD_l ; 在宏定义中调用宏

ENDM
汇编语言 程序设计
8.1.5 宏汇编中的伪指令
1,MACRO和 ENDM
在前面的宏指令的定义中已经介绍过, 这是宏操作时必不可少的指令, 而且成对出现 。
2,PURGE
PURGE的功能是取消多个宏定义, 即一个宏指令定义可以用伪指令 PURGE来取消, 然后就再重新定义 。
格式,PURGE 宏指令名 1, 宏指令名 2……
取消宏定义的含义是使该宏定义成为空, 程序中如果出现一个已被取消宏定义的宏调 用, 则汇编程序将
不会指示出错, 但它将忽略该宏调用, 当然也不会予以展开 。
3,LOCAL
某些宏定义中存在变量或标号, 这些宏定义在同一程序中被多次调用且展开后, 就会出现变量或标号重复
定义的错误 。 LOCAL伪指令的使用可以避免此类错误 。在宏展开时, 让宏汇编程序自动为其后的形参顺序生成
特殊符号 (范围为0000—FFFFH),并用这些特殊符号来取代宏体中的形参, 避免了符号重复定义的错误 。
格式,LOCAL 形参 1,形参 2
汇编语言 程序设计
8.1.6 宏库
有些宏指令在应用过程中效果较好, 因此在以后的汇编
语言编程时就不必每次在源程序中重复编制一个宏指令定义,
这样也可减少重复编写时的错误, 可以把几个宏定义组成一
个宏库, 以文件形式供其它源程序调用 。
在源程序中, 通过书写宏名来引用宏, 而子程序是通过
CALL指令来调用 。
汇编程序对宏通过宏扩展来加入其定义体, 宏引用多少
次, 就相应扩展多少次, 所以, 引用宏不会缩短目标程序;
而子程序代码在目标程序中只出现一次, 调用子程序是执行
同一程序段, 因此, 目标程序也得到相应的简化 。
宏引用时, 参数是通过, 实参, 替换, 形参, 的方式来实现
传递的, 参数形式灵活多样, 而子程序调用时, 参数是通过
寄存器, 堆栈或约定存储单元进行传递的 。
宏引用语句扩展后, 目标程序中就不再有宏引用语句,
运行时, 不会有额外的时间开销, 而子程序的调用在目标程
序中仍存在, 子程序的调用和返回均需要时间 。
8.1.7 宏与子程序的区别
返回
汇编语言 程序设计
8.2 重复汇编
8.2.1 使用 REPT伪指令的重复汇编结构
指令格式:
REPT 表达式
┇ 重复语句序列
ENDM
指令以 REPT开始, ENDM结束 。 其中, 表达式是 REPT与 ENDM中
间的语句序列需要重复的次数, 可以是具体数值, 表达式中不能
包含有任何外部的或没有定义的项, 否则产生错误 。
例 REPT重复汇编结构举例Y=20
REPT 5Y= Y+10
DB YENDM
经汇编后结果如下:DB 30
DB 40DB 50
DB 60DB 70
汇编语言 程序设计
8.2.2 使用 IRP伪指令的重复汇编结构
指令格式:
IRP 形参,<实参 1,实参 2,…… >
┇ 重复语句序列
ENDM
每次重复汇编语句序列时,就用一个实参替代形参。第一次
用第一个实参替代形参,第二次用第二个实参替代形参,直到所
有实参用完为止。重复汇编次数由尖括号括起来的实参个数所决
定。注意实参必须用尖括号括起来,各个实参之间用逗号分开,
如果实参为空,汇编程序则约定跳过 IRP与 ENDM之间的语句,IRP
伪指令的形参只能有一个。
【例 8.8】 IRP重复汇编结构举例
IRP REG,<AX,BX,CX,DX>
PUSH REG
ENDM
经汇编展开后为:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
汇编语言 程序设计
8.2.3 使用 IRPC伪指令的重复汇编结构
指令格式,
IRPC 形参, <字符串 >
┇ 重复语句序列
ENDM
每当汇编重复语句序列时, 汇编程序将依次用字符串中的
一个字符替代形参, 直到字符串中的字符替代完毕 。 重复次数
由字符串中字符个数来确定 。 IIRPC伪指令的形参也只能有一
个 。
【 例 8.9】 IRPC重复汇编结构举例
IRPC S,ABCD
PUSH S&X
ENDM
汇编后展开成:
PUSH AX
PUSH BX
PUSH CX
PUSH DX 返回
汇编语言 程序设计
8.3 条件汇编伪指令
PC机有 10种条件汇编伪指令,它们是 IF,IFl,IF2、
IFE,IFDEF,IFNDET,IFB,IFNB,IFIDN,IFNIDN。
一般格式是:
IF XX 表达式
┇ 语句序列 1
ELSE
┇ 语句序列 2
ENDIF
IF与 ENDIF必须有,且成对出现,ELSE是可选的,其
中 IF XX是上述 l0种条件汇编伪指令之一,XX为指定的条
件,如果指定的条件成立,宏汇编程序将汇编语句序列 1,
否则汇编语句序列 2。
如果没有 ELSE,则指定条件成立就汇编,否则就要
跳过 IF与 ENDIF之间的语句序列,IF XX指定的条件参见
书中表格。
汇编语言 程序设计
【 例 8.10】 条件汇编举例
使用宏指令 BRANCH产生一条转向 Y的转移指令 。 当它相对于 Y的距离小于 128字节时产生 JMP SHORT Y; 否则产生 JMP
NEAR PTR Y(Y必须位于该转移指令之后, 即低地址区 )。
BRANCH宏指令定义:
BRANCH MACRO Y
IF ($-Y) LT 128
JMP SHORT Y
ELSE
JMP NEAR PTR Y
ENDIF
ENDM
现采用宏调用 BRANCH Z
则对应宏展开:
设 Z与 BRANCH指令间的距离小于 128时产生:
+ JMP SHORT Z
否则产生
+ JMP NEAR PTR Z 返回