2009-7-24 80x86汇编语言程序设计第 7章 高级汇编语言技术讲授要点
宏汇编
重复汇编
条件汇编
2009-7-24 80x86汇编语言程序设计
7.1 宏汇编
7.1.1 宏定义、宏调用与宏展开
1,宏定义宏指令名 MACRO [形式参数表 ]
..,; 宏体
ENDM
2,宏调用宏指令名 [实参数表 ]
3,宏展开当源程序被汇编时,MASM用相应的宏体取代每个宏调用,并用实参数按位置替换宏定义中的形式参数 。
2009-7-24 80x86汇编语言程序设计
4,说明
在参数的类型与顺序应与宏定义时的形式参数一致 。
宏展开时,若实参数的个数多于形式参数,则忽略多余的实在参数;若实参数的个数少于形式参数,则多余的形式参数为空 。
宏定义只是告诉 MASM用一个名字来表示一段语句序列,其本身不被汇编 。
宏指令的参数非常灵活,可以出现在指令的操作数或操作码部分,MASM在宏展开时对参数进行文本替换 。
宏定义可以写在程序的任何地方,但习惯上总是把宏定义写在程序的最前面 。
2009-7-24 80x86汇编语言程序设计
【 例 】 参照汇编程序的处理方法,对下面程序中的宏进行展开。
back = 4CH
dosint EQU 21H
dispch MACRO
MOV AH,2
MOV DL,'* '
INT 21H
ENDM
2009-7-24 80x86汇编语言程序设计
code SEGMENT
ASSUME CS,code
main,dispch
dispch
MOV AH,back
INT dosint
code ENDS
END main
2009-7-24 80x86汇编语言程序设计
【 解 】 宏展开后的结果是:
+ MOV AH,2
+ MOV DL,'*'
+ INT 21H
+ MOV AH,2
+ MOV DL,'*'
+ INT 21H
MOV AH,4CH
INT 21H
2009-7-24 80x86汇编语言程序设计
7.1.2 与宏有关的伪指令
1,LOCAL伪指令 — 用来指定宏内局部符号
LOCAL符号名,,..,符号名作用:在宏展开时,MASM将源文件中的所有局部符号统一按出现次序替换为唯一的标识符 (0000 ~FFFF),以避免符号的重复定义 。
2,EXITM 伪指令用来立即终止宏展开,通常与条件汇编结合使用 。 MASM忽略 EXITM
与 ENDM之间的所有语句 。
2009-7-24 80x86汇编语言程序设计
【 例 7.16】 设有如下宏定义:
sum MACRO a,b
LOCAL next
MOV CX,a
LEA BX,b
XOR AX,AX
next:ADD AX,[BX]
ADD BX,2
LOOP next
ENDM
并已知 buf1和 buf2是已定义的两个变量,展开下面的宏调用:
sum 5,buf1
sum 7,buf2
2009-7-24 80x86汇编语言程序设计
【 解 】 宏展开结果是:
+ MOV CX,5
+ LEA BX,buf1
+ XOR AX,AX
+0000:ADD AX,[BX]
+ ADD BX,2
+ LOOP0000
+ MOV CX,7
+ LEA BX,buf2
+ XOR AX,AX
+0001:ADD AX,[BX]
+ ADD BX,2
+ LOOP0001
2009-7-24 80x86汇编语言程序设计
7.1.3 宏操作符
1,< >
在宏调用时,当实参数包含空格或逗号等间隔符时,必须使用 "<" 和
">"作为参数的定界符 。
2,&
在宏定义时,当形式参数作为标识符或字符串的一部分时,必须使用
&作为分隔符 。
3,%
当宏调用时,若在实参数中使用 %,则 MASM将 %后常数表达式的值作为参数,而非表达式本身 。
2009-7-24 80x86汇编语言程序设计
4,!
对于包含在 <和 >之间的文本串,MASM将出现在 !之后的特殊字符
( <,>,%,",'和逗号)作为普通字符处理。若将!作为普通字符,
则使用!!。 !不适用于包含在引号中的字符串。
5,;;
在宏定义中,以 ;;开始的宏注释,在宏展开时被忽略。
2009-7-24 80x86汇编语言程序设计
【 例 】 设有宏定义如下:
data MACRO p,q
v&p DB q
ENDM
以及下面的宏调用:
x = 1
data %x,%x
x = x+1
data %x,%x
其宏展开结果是:
1 v1 DB 1
1 v2 DB 2
2009-7-24 80x86汇编语言程序设计
7.1.3 宏的嵌 套 定义
【 例 】 设某程序中已定义了 3个字型变量 v1,v2,v3,下面是源程序中的一段,试展开最后一行的宏调用 。
mm1 MACRO x
MOV AX,x
MUL AX
ENDM
2009-7-24 80x86汇编语言程序设计
mm2 MACRO a,b,c
mm1 a
MOV BX,AX
mm1 b
ADD AX,BX
MOV c,AX
ENDM
调用:
mm2 v1,v2,v3
2009-7-24 80x86汇编语言程序设计
【 解 】 展开 mm2后得到:
1 mm1 v1
1 MOV BX,AX
1 mm1 v2
1 ADD AX,BX
1 MOV v3,AX
其中还含有宏调用,再把两个 mm1展开后可得到如下结果:
2 MOV AX,v1
2 MUL AX
1 MOV BX,AX
2 MOV AX,v2
2 MUL AX
1 ADD AX,BX
1 MOV v3,AX
2009-7-24 80x86汇编语言程序设计
7.2.4 宏指令与过程的区别
在汇编后产生的目标文件中,过程定义依然存在,而宏定义却不复存在 。
过程调用是在执行时通过 CALL指令完成的,而宏调用是在汇编时进行宏展开,被相应宏体所取代 。
将多次调用的一段代码定义为宏指令,与使用过程相比,其执行速度要快 ( 因为过程需要调用和返回 ),但目标代码长 。
宏指令的参数是在汇编时进行形实替换的,而过程的参数是在执行时通过寄存器或堆栈等方式传递的 。
2009-7-24 80x86汇编语言程序设计
7.2 重复块
7.2.1 REPEAT
1,格式
REPT 数值表达式
..,; 重复体
ENDM
2,功能以数值表达式表示的无符号值作为重复次数,连续汇编重复体中的语句 。
2009-7-24 80x86汇编语言程序设计
【 例 】 前面提到的把 1到 10的整数作为字节型变量的初值可以用下面的方式编写:
x = 1
REPT 10
DB x
x = x+1
ENDM
汇编后产生的结果如下:
1 DB 1
1 DB 2
……
1 DB 9
1 DB 10
2009-7-24 80x86汇编语言程序设计
7.2.2 IRP 伪操作
1,格式
IRP 参数名,<参数值,...,参数值 >
..,; 重复体
ENDM
2,功能为 < >内的每一项重复一次,每次用相应的参数值取代参数名 。
3,实例
2009-7-24 80x86汇编语言程序设计
【 例 7.19】 把除 SP以外的各通用寄存器入栈需要 7条 PUSH
指令,如果用重复汇编可以写成:
IRP regs,<AX,BX,CX,DX,SI,DI,BP>
PUSH regs
ENDM
汇编后展开的结果是:
1 PUSH AX
1 PUSH BX
1 PUSH CX
1 PUSH DX
1 PUSH SI
1 PUSH DI
1 PUSH BP
2009-7-24 80x86汇编语言程序设计
7.2.3 IRPC 伪操作
1,格式
IRPC 参数名,<字符串 > ;包含字符串的 <>可以省略
..,; 重复体
ENDM
2,功能与 IRP不同的是,其重复次数由字符串的长度决定,每次以相应字符取代参数 名 。
2009-7-24 80x86汇编语言程序设计
7.2.4 对重复块的说明
重复块可以用在宏定义体内,也可单独使用 。 重复块没有名字,不能被调用 。
与宏指令不同的是,重复块未将定义与调用分离 。
在汇编时,MASM展开遇到的每个重复块 。 若希望产生可调用的重复块,则可放在宏定义内 。
重复块是在汇编时处理的 。
2009-7-24 80x86汇编语言程序设计
7.3 条件汇编
条件汇编的作用:根据指定条件来确定是否汇编某些代码,以便在不同操作环境下生成不同的目标代码 。 条件汇编类似于高级语言的条件编译 。
条件汇编语句的一般形式如下:
IFxx 表达式
<语句序列 1>
[ ELSE
<语句序列 2> ]
ENDIF
2009-7-24 80x86汇编语言程序设计
较常用的条件汇编语句,IF,IFDEF
使用条件汇编的场合与实例:
在不同 CPU下汇编不同代码。
在程序中插入调试语句。
2009-7-24 80x86汇编语言程序设计本章小结
宏指令只要在程序中定义一次,就可以多次调用 。 在汇编时,
每个宏调用被相应的宏体所取代 。 MASM在宏展开时对参数进行文本替换 。
MASM提供了三种类型的重复块,REPT,IRP和 IRPC。 与宏指令不同的是,重复块未将定义和调用分离 。 若希望产生可调用的重复块,则应将其放在宏定义内 。
使用条件汇编,可以在不同操作环境下生成不同的目标代码 。
然而,太多或太复杂的条件汇编语句,会降低程序的可读性 。
宏汇编
重复汇编
条件汇编
2009-7-24 80x86汇编语言程序设计
7.1 宏汇编
7.1.1 宏定义、宏调用与宏展开
1,宏定义宏指令名 MACRO [形式参数表 ]
..,; 宏体
ENDM
2,宏调用宏指令名 [实参数表 ]
3,宏展开当源程序被汇编时,MASM用相应的宏体取代每个宏调用,并用实参数按位置替换宏定义中的形式参数 。
2009-7-24 80x86汇编语言程序设计
4,说明
在参数的类型与顺序应与宏定义时的形式参数一致 。
宏展开时,若实参数的个数多于形式参数,则忽略多余的实在参数;若实参数的个数少于形式参数,则多余的形式参数为空 。
宏定义只是告诉 MASM用一个名字来表示一段语句序列,其本身不被汇编 。
宏指令的参数非常灵活,可以出现在指令的操作数或操作码部分,MASM在宏展开时对参数进行文本替换 。
宏定义可以写在程序的任何地方,但习惯上总是把宏定义写在程序的最前面 。
2009-7-24 80x86汇编语言程序设计
【 例 】 参照汇编程序的处理方法,对下面程序中的宏进行展开。
back = 4CH
dosint EQU 21H
dispch MACRO
MOV AH,2
MOV DL,'* '
INT 21H
ENDM
2009-7-24 80x86汇编语言程序设计
code SEGMENT
ASSUME CS,code
main,dispch
dispch
MOV AH,back
INT dosint
code ENDS
END main
2009-7-24 80x86汇编语言程序设计
【 解 】 宏展开后的结果是:
+ MOV AH,2
+ MOV DL,'*'
+ INT 21H
+ MOV AH,2
+ MOV DL,'*'
+ INT 21H
MOV AH,4CH
INT 21H
2009-7-24 80x86汇编语言程序设计
7.1.2 与宏有关的伪指令
1,LOCAL伪指令 — 用来指定宏内局部符号
LOCAL符号名,,..,符号名作用:在宏展开时,MASM将源文件中的所有局部符号统一按出现次序替换为唯一的标识符 (0000 ~FFFF),以避免符号的重复定义 。
2,EXITM 伪指令用来立即终止宏展开,通常与条件汇编结合使用 。 MASM忽略 EXITM
与 ENDM之间的所有语句 。
2009-7-24 80x86汇编语言程序设计
【 例 7.16】 设有如下宏定义:
sum MACRO a,b
LOCAL next
MOV CX,a
LEA BX,b
XOR AX,AX
next:ADD AX,[BX]
ADD BX,2
LOOP next
ENDM
并已知 buf1和 buf2是已定义的两个变量,展开下面的宏调用:
sum 5,buf1
sum 7,buf2
2009-7-24 80x86汇编语言程序设计
【 解 】 宏展开结果是:
+ MOV CX,5
+ LEA BX,buf1
+ XOR AX,AX
+0000:ADD AX,[BX]
+ ADD BX,2
+ LOOP0000
+ MOV CX,7
+ LEA BX,buf2
+ XOR AX,AX
+0001:ADD AX,[BX]
+ ADD BX,2
+ LOOP0001
2009-7-24 80x86汇编语言程序设计
7.1.3 宏操作符
1,< >
在宏调用时,当实参数包含空格或逗号等间隔符时,必须使用 "<" 和
">"作为参数的定界符 。
2,&
在宏定义时,当形式参数作为标识符或字符串的一部分时,必须使用
&作为分隔符 。
3,%
当宏调用时,若在实参数中使用 %,则 MASM将 %后常数表达式的值作为参数,而非表达式本身 。
2009-7-24 80x86汇编语言程序设计
4,!
对于包含在 <和 >之间的文本串,MASM将出现在 !之后的特殊字符
( <,>,%,",'和逗号)作为普通字符处理。若将!作为普通字符,
则使用!!。 !不适用于包含在引号中的字符串。
5,;;
在宏定义中,以 ;;开始的宏注释,在宏展开时被忽略。
2009-7-24 80x86汇编语言程序设计
【 例 】 设有宏定义如下:
data MACRO p,q
v&p DB q
ENDM
以及下面的宏调用:
x = 1
data %x,%x
x = x+1
data %x,%x
其宏展开结果是:
1 v1 DB 1
1 v2 DB 2
2009-7-24 80x86汇编语言程序设计
7.1.3 宏的嵌 套 定义
【 例 】 设某程序中已定义了 3个字型变量 v1,v2,v3,下面是源程序中的一段,试展开最后一行的宏调用 。
mm1 MACRO x
MOV AX,x
MUL AX
ENDM
2009-7-24 80x86汇编语言程序设计
mm2 MACRO a,b,c
mm1 a
MOV BX,AX
mm1 b
ADD AX,BX
MOV c,AX
ENDM
调用:
mm2 v1,v2,v3
2009-7-24 80x86汇编语言程序设计
【 解 】 展开 mm2后得到:
1 mm1 v1
1 MOV BX,AX
1 mm1 v2
1 ADD AX,BX
1 MOV v3,AX
其中还含有宏调用,再把两个 mm1展开后可得到如下结果:
2 MOV AX,v1
2 MUL AX
1 MOV BX,AX
2 MOV AX,v2
2 MUL AX
1 ADD AX,BX
1 MOV v3,AX
2009-7-24 80x86汇编语言程序设计
7.2.4 宏指令与过程的区别
在汇编后产生的目标文件中,过程定义依然存在,而宏定义却不复存在 。
过程调用是在执行时通过 CALL指令完成的,而宏调用是在汇编时进行宏展开,被相应宏体所取代 。
将多次调用的一段代码定义为宏指令,与使用过程相比,其执行速度要快 ( 因为过程需要调用和返回 ),但目标代码长 。
宏指令的参数是在汇编时进行形实替换的,而过程的参数是在执行时通过寄存器或堆栈等方式传递的 。
2009-7-24 80x86汇编语言程序设计
7.2 重复块
7.2.1 REPEAT
1,格式
REPT 数值表达式
..,; 重复体
ENDM
2,功能以数值表达式表示的无符号值作为重复次数,连续汇编重复体中的语句 。
2009-7-24 80x86汇编语言程序设计
【 例 】 前面提到的把 1到 10的整数作为字节型变量的初值可以用下面的方式编写:
x = 1
REPT 10
DB x
x = x+1
ENDM
汇编后产生的结果如下:
1 DB 1
1 DB 2
……
1 DB 9
1 DB 10
2009-7-24 80x86汇编语言程序设计
7.2.2 IRP 伪操作
1,格式
IRP 参数名,<参数值,...,参数值 >
..,; 重复体
ENDM
2,功能为 < >内的每一项重复一次,每次用相应的参数值取代参数名 。
3,实例
2009-7-24 80x86汇编语言程序设计
【 例 7.19】 把除 SP以外的各通用寄存器入栈需要 7条 PUSH
指令,如果用重复汇编可以写成:
IRP regs,<AX,BX,CX,DX,SI,DI,BP>
PUSH regs
ENDM
汇编后展开的结果是:
1 PUSH AX
1 PUSH BX
1 PUSH CX
1 PUSH DX
1 PUSH SI
1 PUSH DI
1 PUSH BP
2009-7-24 80x86汇编语言程序设计
7.2.3 IRPC 伪操作
1,格式
IRPC 参数名,<字符串 > ;包含字符串的 <>可以省略
..,; 重复体
ENDM
2,功能与 IRP不同的是,其重复次数由字符串的长度决定,每次以相应字符取代参数 名 。
2009-7-24 80x86汇编语言程序设计
7.2.4 对重复块的说明
重复块可以用在宏定义体内,也可单独使用 。 重复块没有名字,不能被调用 。
与宏指令不同的是,重复块未将定义与调用分离 。
在汇编时,MASM展开遇到的每个重复块 。 若希望产生可调用的重复块,则可放在宏定义内 。
重复块是在汇编时处理的 。
2009-7-24 80x86汇编语言程序设计
7.3 条件汇编
条件汇编的作用:根据指定条件来确定是否汇编某些代码,以便在不同操作环境下生成不同的目标代码 。 条件汇编类似于高级语言的条件编译 。
条件汇编语句的一般形式如下:
IFxx 表达式
<语句序列 1>
[ ELSE
<语句序列 2> ]
ENDIF
2009-7-24 80x86汇编语言程序设计
较常用的条件汇编语句,IF,IFDEF
使用条件汇编的场合与实例:
在不同 CPU下汇编不同代码。
在程序中插入调试语句。
2009-7-24 80x86汇编语言程序设计本章小结
宏指令只要在程序中定义一次,就可以多次调用 。 在汇编时,
每个宏调用被相应的宏体所取代 。 MASM在宏展开时对参数进行文本替换 。
MASM提供了三种类型的重复块,REPT,IRP和 IRPC。 与宏指令不同的是,重复块未将定义和调用分离 。 若希望产生可调用的重复块,则应将其放在宏定义内 。
使用条件汇编,可以在不同操作环境下生成不同的目标代码 。
然而,太多或太复杂的条件汇编语句,会降低程序的可读性 。