宏指令及补充教案.docx
《宏指令及补充教案.docx》由会员分享,可在线阅读,更多相关《宏指令及补充教案.docx(11页珍藏版)》请在冰豆网上搜索。
宏指令及补充教案
一条件汇编
⒈一般格式
Ifx[CONT]
:
:
若干语句(称为条件块)
[ELSE]
:
:
若干语句(称为条件块)
ENDIF
说明:
IBMPC宏汇编程序提供了十种条件汇编伪操作指令:
IF、IF1、IF2、IFE、IFDEF、IFNDEF、IFB、IFNB、IFIDN、IFDIF。
⒉条件汇编的作用
条件汇编伪操作允许用户在编制汇编语言程序时规定某种条件,汇编程序在汇编过程中测试条件是否成立,当条件成立时,则将某段汇编语言源程序汇编为目标程序,否则,不进行汇编。
注意:
条件汇编允许嵌套使用。
⒊详细介绍
①IFCONT
当条件表达式CONT值不是零时,条件为真。
②IFECONT
当条件表达式CONT值为零时,条件为真。
③IF1
如果是第一遍扫描,条件为真。
IBMPC的宏汇编程序是一种两遍的扫描程序,它两次从头至尾地读汇编源程序,第一遍用来确定每个程序行的相对偏移量,产生自定义符号表,检查语句格式和语法等。
第二遍扫描产生目标程序和列表文件。
④IF2
如果是第二遍扫描,条件为真。
⑤IFDEFCONT
此操作中的条件CONT是一个符号,如果这个符号已经定义,或者已用EXTRN伪指令说明过它是外部标号,则条件为真。
⑥IFNDEFCONT
该伪操作中的条件CONT是一个符号,如果此符号未定义或未经EXTRN伪指令说明,则条件为真。
⑦IFB
如果尖括号中为(不写任何字符),则条件为真。
⑧IFNB
如果尖括号中不为空,则条件为真。
⑨IFIDN,
CHR1和CHR2为字符串,如果两个字符串相同,则条件为真。
两个字符串必须分别用尖括号括起来。
⑩IFDIF,
CHR1和CHR2为字符串,如果两个字符串不相同,则条件为真。
两个字符串必须用尖括号括起来。
⒋条件汇编举例
ARG1EQU35H
ARG2=NOTARG1
IF(ARG1ORARG2)EQ0FFFFH
MOVAX,ARG1
MOVBX,ARG2
ADDAX,BX
IF(ARG1ANDARG2)EQ0FFFFH
SUBAX,CX
IFEARG1
ADDAX,DX
ENDIF
MOV[SI],AX
ENDIF
MOV[DI],AX
ENDIF
二宏伪操作
⒈宏定义和宏结束伪操作命令
①宏定义的一般格式
MNAMEMACRO[DUMPAR1][,DUMPAR2]……
:
:
宏体
:
ENDM
说明:
MNAME是宏名字,用户自定义的符号,也就是我们所定义的宏指令。
MACRO是宏定义伪操作命令,ENDM是宏结束伪操作命令。
MACRO与ENDM之间是一系列汇编语言语句,称为宏体。
方括号的DUMPAR1,DUMPAR2,…是形式参数,也称哑参数,可选项,不需要时可以省略。
形式参数在宏扩展时被实在参数代替。
②宏调用与宏扩展
在汇编语言程序中,操作码段写上宏名字,即使用宏指令,称为宏调用。
宏调用的格式:
MNAME[RPAR1][,RPAR2]……
其中MNAME是已经定义的宏名字(宏指令),使用时写在语句中的操作码段;RPAR1,RPAR2……是实在参数,它在宏调用中的意义与出现的次序必须与宏定义中形式参数的意义与出现次序相同,在宏扩展时,用实在参数顺序替代它所对应的形式参数。
汇编程序对汇编语言源程序进行汇编时,每当在操作码段遇到宏名字时,就用其相应的宏体代替它,即将它所代表的宏体写入程序中,这个过程叫做宏扩展。
例:
定义数据块传送的宏指令
BLMOVMACROSRC,DST,CNT
LEASI,SRC
LEADI,DST
MOVCX,CNT
CLD
REPMOVSB
ENDM
宏调用:
MAIN1:
…
BLMOVADR1,ADR2,CNT1
…
BLMOVADR2,ADR3,20
…
⒉参数的使用
①用参数代表自定义符号和数值
在上例中的SRC,DST代表要传送数据的源地址,目的地址,在第一个宏调用中,ADR1、ADR2分别代表了他们,在第二个宏调用中ADR2,ADR3代表了它们,形式参数CNT在第一个宏调用中CNT1代表了它,CNT1可能是内存单元地址,该单元中的内容为一个计数值,也可能是用等价伪指令定义的数值;在第二个宏调用中数值20代替了它。
②用参数代表指令
例:
定义将某存储区清零的宏指令
CLEARMACRODIR,DST,CNT
DIR
LEADI,DST
MOVCX,CNT
XORAL,AL
REPSTOSB
ENDM
宏调用:
MAIN2:
CLEARCLD,ADR1,80
③用参数代替寄存器名字
例:
定义将任一个寄存器循环左移或右移n位的宏指令
RLSMACRODIR,REG,CNT
MOVCL,CNT
RO&DIRREG,CL
ENDM
宏调用:
MAIN3:
…
RLSR,AX,5
…
RLSL,CH,2
…
④用参数代表任何一字符串或子字符串
例:
定义两个多精度数据求和的宏指令
MADD1MACROLABEL,SRC,DST,LEN,SUN
LEASI,SRC
LEADI,DST
MOVCX,LEN
LEABX,SUN
CLC
LABEL:
MOVAL,[SI]
ADCAL,[DI]
MOV[BX],AL
INCSI
INCDI
INCBX
LOOPLABEL
ENDM
宏调用:
MAIN4:
MADD1LOOP1,ADR3,ADR1,8,ADR2
…
MADD1LOOP2,ADR1,ADR2,6,ADR3
…
⒊宏中的标号处理
我们知道,编写汇编语言程序的一个规则是标号必须是惟一的,即同一个标号不允许在一个程序中的标号域出现两次以上,否则为重复定义,汇编程序在汇编程序时就会打印出错信息。
如果在宏定义中有标号,那么,在多次宏调用后,在多次宏调用后,在标号域中必然会多次重复出现同一个标号,这是汇编程序所不允许的。
解决这个问题的方法有两种:
①把标号定义为参数形式
②在宏定义中声明标号为局部标号
格式:
LOCALLAB1[,LAB2]…
功能:
LOCAL的作用就是要告诉汇编程序宏体中的这些标号是局部的。
例:
定义求三个寄存器中的最小数的宏指令
FMINMACROREG1,REG2,REG3
LOCALNEXT1,NEXT2
CMPREG1,REG2
JNANEXT1
MOVREG1,REG2
NEXT1:
CMPREG1,REG3
JNANEXT2
MOVREG1,REG3
NEXT2:
NOP
ENDM
宏调用:
MAIN5:
MOVAL,[SI]
MOVBL,[SI+1]
MOVCL,[SI+2]
FMINAL,BL,CL
MOVMIN,AL
⒊宏嵌套
宏嵌套有两种形式:
宏定义中嵌套宏定义和宏定义中嵌套宏调用,两种宏嵌套的深度不限。
⒋宏与子程序的区别
宏与子程序都是用来处理在编程序过程中多次使用的功能程序的方法,这是二者的共同点,二者的区别见下表:
宏与子程序的区别
宏
子程序
处理者
宏汇编程序
中央处理机
处理时间
在汇编过程中
程序执行时
处理方法
用宏体替换宏指令
用CALL指令调用
占用内存
占用内存空间多
占用内存空间少
运行速度
运行速度较高
运行速度较低
灵活性
十分灵活
不够灵活
⒌特殊宏操作命令
①退出宏操作命令EXITM
格式:
EXITM
说明:
EXITM用于宏定义和重复块伪操作中。
在宏定义和重复块伪操作中含有条件汇编伪操作,对条件进行测试,如果想在条件成立时则不进行扩展或重复剩余部分而结束宏定义或重复伪操作,用EXITM退出。
②特殊宏操作符号&(连接)
格式:
STR1&STR2
说明:
&的功能将字符串STR1和字符串STR2连接在一起。
③特殊宏操作符号%
格式:
%EXP
说明:
EXP为数值、数值符号或算术表达式。
%的功能是允许用数值调用宏定义。
例:
MESSIMACRON
ORDER=0
REPTN
ORDER=ORDER+1
MARK%ORDER
ENDM
MARKMACROY
MESS&YDB‘ROOMNO.&Y’,0
ENDM
三简化段定义的格式
对于大多数小型MASM程序,采用简化段定义伪指令,整个源程序格式表达如下:
.modelsmall;定义程序的存储模式(一般采用small)
.stack;定义堆栈段
.data;定义数据段
…;数据定义
.code;定义代码段
.startup;程序起始点,并建立DS,SS内容(注1)
…;程序代码
.exit0;程序结束点,返回DOS(注2)
…;子程序代码
end;汇编结束(注3)
⒈存储模式伪指令
见书94页
⒉简化段定义伪指令
.stack[大小]
堆栈段伪指令.stack创建一个堆栈段,段名是:
stack。
它的参数指定堆栈段所占存储区的字节数,默认是1KB
.DATA
.DATA?
数据段伪指令.DATA创建一个数据段,段名是:
_DATA。
它用于定义具有初值的变量,当然也允许定义无初值的变量。
无初值变量可以安排在另一个段中,它用.DATA?
伪指令创建,它建立的数据段名是:
_BSS。
使用.DATA?
伪指令可以减小形成的EXE文件,并与其他语言保持最大的兼容性。
另外,.CONST伪指令用于建立只读的常量数据段(段名:
CONST),.FARDATA和.FARDATA?
伪指令分别用于建立有初值和无初值的远调用数据段。
.CODE[段名]
.CODE伪指令创建一个代码段,它的参数指定该代码段的段名。
如果没有给出段名,则采用默认段名。
在TINY,SMALL,COMPACT和FLAT模式下,默认的代码段名是:
_TEXT;MEDIUM,LARGE和HUGE模式下,默认的代码段名是:
模块名_TEXT。
另外,使用简化段定义,各段名称和其他用户所需的信息可以使用MASM预定义的符号,这些符号主要有:
@CODE——表示.CODE伪指令定义的段名
@DATA——表示由.DATA,.DATA?
等定义的数据段的段名
另外,还有@CURSEG当前段名,@CODESIZE代码段规模和@DATASIZE数据段规模等。
一个源程序中可以出现多个简化段定义伪指令,例如多处写有.DATA。
但实际上,汇编程序MASM将它们组织一起连续存放在定义的缓冲区。
⒊程序开始伪指令
.STARTUP
.STARTUP伪指令按照给定的CPU类型,根据.MODEL语句选择的存储模式、操作系统和堆栈类型,产生程序开始执行的代码;同时还指定了程序开始执行的起始点。
在DOS下,.STARTUP语句还将初始化DS值,调整SS和SP值。
例如,在SMALL存储模式下,对应8086CPU,.STARTUP语句将被汇编成如下启动代码:
MOVDX,DGROUP;DGROUP表示数据段组的段地址
MOVDS,DX;设置DS
MOVBX,SS
SUBBX,DX
SHLBX,1
SHLBX,1
SHLBX,1
SHLBX,1
CLI;关中断
MOVSS,DX;调整SS=DS,这是small模式的规定
ADDSP,BX;移动了SS段地址,所以SP也需要相应调整
STI;开中断
显然,如果不使用.STARTUP语句,可以用下面2条指令代替(没有调整堆栈SS:
SP)
START:
MOVAX,@DATA;@DATA表示数据段的段地址
MOVDS,AX;设置DS
⒋程序终止伪指令
.EXIT[返回数码]
.EXIT语句产生终止程序执行返回操作系统的指令代码。
它的可选参数是一个返回的数码,通常用0表示没有错误,例如.EXIT0对应的代码是:
MOVAX,4C00H
INT21H
⒌汇编结束伪指令
END[标号]
END伪指令指示汇编程序MASM到此结束汇编过程。
源程序的最后必须有一条END语句,可选的标号用于指定程序开始执行点,例如START,连接程序据此设置CS:
IP值。
简化段定义格式引入了存储模式,极大地方便了编写源程序。
在小型程序中,通常采用SMALL模式;为了得到更短小的程序,可以创建COM程序。
利用MASM6.X的简化段定义格式,可以非常容易地创建一个COM程序。
此时,要采用TINY模式;源程序只设置代码段,不能设置数据、堆栈等其他段;程序必须从偏移地址100H处开始执行;数据安排在代码段中,但不能与可执行代码相冲突,通常在程序最后。
例:
COM程序实现按任意键后响铃
.MODELTINY;采用微型模式
.CODE;只有一个段,没有数据段和堆栈段
.STARTUP;等效于ORG100H,汇编程序自动产生
MOVDX,OFFSETSTRING;现实信息
MOVAH,9
INT21H
MOVAH,01H;等待按键
INT21H
MOVAH,02H;响铃
MOVDL,07H
INT21H
.EXIT0
STRINGDB‘Pressanykeytocontinue!
$’;数据安排在不与代码冲突的地方
END