汇编语言——宏

上传人:陈** 文档编号:250602943 上传时间:2024-11-03 格式:PPT 页数:44 大小:599.50KB
返回 下载 相关 举报
汇编语言——宏_第1页
第1页 / 共44页
汇编语言——宏_第2页
第2页 / 共44页
汇编语言——宏_第3页
第3页 / 共44页
点击查看更多>>
资源描述
7.3 宏,程序中使用宏分为定义和调用两个部分。宏定义用来说明哪些指令或伪指令是将在程序中重复出现的程序段;宏调用是用来告诉汇编程序,在翻译前先把宏定义中的程序段复制一遍。可见,宏定义和宏调用都是告诉汇编程序如何处理,属于伪操作。,7.3.1 宏定义,【格式】宏名 MACRO,宏体,ENDM,【说明】,(1)“宏名”是一个标识符,一个程序中可以定义多个宏,对每一个宏必须以不同的标识符命名,且宏名不能与变量、标号、段名等标识符同名。,(2)汇编语言规定,宏定义的起始标记MACRO前面必须写宏的名字,而结束标记ENDM的前面却不允许写任何内容,写在起止标记之间的部分称为宏体,宏体部分通常是一段程序中需要重复使用的指令序列。,(3)宏定义仅仅用来告诉汇编程序,将来宏调用时复制的对象是什么,宏定义中的程序段并不是程序的一部分,也就是说,如果程序中定义了一个宏而没有调用它,汇编程序将忽略宏定义。,(4)宏定义可以写在程序的任何地方,但习惯上总是把宏定义写在程序的最前面。,宏定义与编辑器中的文字块的定义有相似之处,也有一些差别。两者都需要以特定的方式说明开始和结束的位置。文字块是文件的一部分,而宏体中的程序段必须经过宏调用才能复制到源程序中正确的位置,没有被调用的宏体在汇编程序翻译时会被忽略。,7.3.2 宏调用,定义后的宏名又称为宏指令。经宏定义后,就可以在源程序中调用宏了。宏调用的方式是在源程序中需要复制宏体的地方写宏的名字。宏名单独占一行,当源程序被汇编时,汇编程序将对宏调用进行宏体复制,并取代宏名,这种复制操作称为宏展开。为了与源程序的其它部分相区别,后面的叙述中,对由宏调用而展开后得到的指令,都在前面标以加号“”以示区别。,【例7.10】参照汇编程序的处理方法,对下面程序中的宏进行展开。,back =4CH,dosint EQU 21H,dispch MACRO,MOV AH,2,MOV DL,*,INT 21H,ENDM,code SEGMENT,ASSUME CS:code,main:dispch,dispch,MOVAH,back,INTdosint,code ENDS,ENDmain,【解】宏展开后的结果是:,MOVAH,2,MOVDL,*,INT21H,MOVAH,2,MOVDL,*,INT21H,MOVAH,4CH,INT21H,由于宏展开是汇编程序翻译的一个步骤,宏展后的结果并不是源程序,所以展开后不再写出完整的程序格式,只列出有效指令部分。,可以看到,汇编程序对宏调用与已定义的常量及符号的引用的处理是很类似的,定义部分在汇编处理结束后就已完成它的作用。汇编程序翻译后得到的机器代码中没有宏、常量等的定义,只是调用或引用部分被代换成宏体或定义的内容。宏与常量定义及符号定义的差别在于,常量及符号定义都必须在一行写完,对常量和符号的引用只能代换指令中的操作数,或者操作数的一部分,宏调用则可以代换一段程序。不仅如此,宏还允许代换的内容有个别地方不同,这是通过带参数的宏实现的。,7.3.3 带参数的宏,如果宏只能对完全相同的程序段进行复制,那就没有多大的应用价值了,宏的好处主要体现在每次调用而展开的宏体可以不同。这需要在宏定义时以形式参数指明宏体中的哪些部分可以被不同的实际参数代替,每次调用时在宏名字的后面附带实际参数。完整的宏定义格式是:,宏名 MACRO 形式参数表,宏体,ENDM,形式参数可以出现在宏体中的任何位置,可以在操作数中,可以在指令助记符的位置,甚至还可以是其中的一部分。下面的几个例子用来说明参数的各种不同用法。,【例7.11】普通用法,形式参数出现在操作数的位置。,dch MACRO x,MOV AH,2,MOV DL,x,INT 21H,ENDM,源程序中调用宏dch时,应该在宏名字的后面跟一个实际参数,从例7.11的宏体可以看出,这个实际参数应该是用于屏幕显示的一个ASCII字符。因而,源程序中用下面的写法连续两次调用上述宏,就可以实现回车换行操作。宏展开时,对每一次宏调用,将分别以相应的实际参数代换宏体中的形式参数。,dch 13,dch 10,【例7.12】形式参数可以出现在助记符的位置。,cc MACRO cmd,lab,CMP AX,BX,cmd lab,ENDM,上述宏在调用时可以用不同的实际参数代换形式参数cmd,使得宏体中的第2行是不同的指令。比如下面是几个调用的例子,请读者自己写出宏展开的结果。,cc JG,n1,cc JBE,n2,cc JNZ,n3,【例7.13】宏的形式参数可以作为一个标识符的一部分。这时,必须用符号“&”把形式参数与标识符的其余部分分开。例7.12中的宏定义还可以写成下面的形式:,cc1 MACRO cmd,lab,CMP AX,BX,J&cmd lab,ENDM,宏体中第2行的J&cmd就是在一个标识符中(例7.13中表现为指令助记符)含有形式参数,符号“&”用于把形参cmd从标识符中分离出来。如果没有分隔符号“&”,汇编程序将把Jcmd作为一个整体处理,而不知道其中的cmd是形参。,对例7.12后面的3个调用,调用例7.13中的宏可以达到同样的效果,相应写法是:,cc1 G,n1,cc1 BE,n2,cc1 NZ,n3,【例7.14】形式参数还可以出现在变量定义伪操作的初值表中,甚至是以字符串形式出现的初值。,msg MACRO num,pname,var&num DB HELLO,&pname,ENDM,汇编语言规定,字符串中的形参必须用分隔符“&”从其它部分分离出来。对于下面两个宏调用,,msg 1,John,msg 2,Henrry,宏展开的结果是:,var1 DB HELLO,John,var2 DB HELLO,Henrry,*7.3.4 宏操作中形参与实参的对应关系,由于宏是伪操作,形参与实参的对应方法是由汇编程序决定的,与高级语言中形参与实参的对应方式有很大的不同。汇编语言规定:,(1)形参表中的多个参数项之间必须用逗号分隔,但实参表的各个参数项可以用逗号也可以用空格分隔。,(2)如果形参的数目与实参的数目相等,则按照形参表与实参表中各参数项的次序一一对应。,(3)如果形参数目少于实参数目,多余的实参被忽略,汇编程序不做任何提示。,(4)如果形参数目多于实参数目,不足的实参作空串处理,汇编程序也不做提示。,(5)如果实参中包含逗号、空格等分隔符作有效符号,必须用尖括号“”括起来,避免混淆。,【例7.15】设有宏定义如下:,data MACRO p,q,v&p DB q,ENDM,以及下面的宏调用:,x =1,data%x,%x,x =x+1,data%x,%x,其宏展开结果是:,v1 DB 1,v2 DB 2,符号“”的作用体现在宏展开中是用常量标识符x的值(第1次宏调用时是1,第2次宏调用时是2),而不是符号x本身,去替换宏展开时的形参。,需要注意的是,宏操作与源程序的其它部分一样,都要经过汇编程序的处理。汇编程序在处理带有宏调用的程序时,是先进行宏展开,再进行语法检查及翻译。宏体在定义时,由于可以带有一些形式参数,在没有进行代换之前很可能是不符合语法规则的,但宏调用并展开后是否符合语法规则,需要由汇编程序来判定。如果展开后的指令或伪指令有错,汇编程序只能指出宏调用有错,并指出宏调用所在行的号码,却无法指出究竟是展开后的哪一行不符合语法。,因此,对这一类错误提示,程序员只能自己按规则进行宏展开,并判断展开后的结果是如何出的错。对于MASM汇编程序比较熟悉的人,还可以借助于MASM处理源程序时产生的一个.LST文件(只要在MASM提问“Source listingNUL.LST”时输入一个合适的文件名即可产生清单文件),判断程序中的错误,以及查看宏展开的结果。,另外,宏调用的优先级高于其它伪指令和指令,所以如果用伪指令或指令助记符等内部保留字作为宏的名字,则汇编程序会把这样的标识符当作宏进行处理,而使得源程序中无法使用其原有的功能。汇编语言中还提供了一个PURGE伪指令,用于在源程序适当的位置取消某个宏。比如:,add MACRO x,y,ENDM,ADD AX,BX,PURGE add,ADD AX,BX,这样的源程序中,前一个ADD被当作宏调用处理(汇编语言是不分大小写的),进行宏展开;后一个ADD由于已用PURGE伪指令取消了作为宏的add宏调用,使得该标识符恢复原功能,因此是ADD指令。,7.3.5 宏体中的标号,宏体中出现标号分为两种情况:一是在带有跳转功能的指令中,标号作为跳转的目的地,也就是对标号的引用;另一种是宏体中某条指令的前面出现标号,即标号定义。如果宏体中引用标号,由于汇编语言允许从程序的不同地方用跳转指令跳转到同一位置,所以即使源程序中对这样的宏多次调用,展开后的结果并不违反语法规则。但是需要注意,如果标号的引用出现在条件跳转指令中,由于条件跳转的距离是有限制的,所以源程序中在不同位置调用这样的宏,那些离标号定义处较近的可以不超过范围因而没有语法错误,但那些离标号定义处远的就不保证了。,【格式】LOCAL 标号1,标号2,【功能】用于告诉汇编程序,在宏展开时,对宏体中出现的“标号1”、“标号2”等标号定义,代换为特殊的各不相同的标号。汇编程序在遇到用LOCAL说明的标号时,会代以?0000、?0001、?0002、等特殊的标识符,以保证宏体中的标号定义在每次宏展开时各不相同,避免重复定义的情况。,【例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,【解】宏展开结果是:,MOV CX,5,LEA BX,buf1,XOR AX,AX,?0000:ADD AX,BX,ADD BX,2,LOOP?0000,MOV CX,7,LEA BX,buf2,XOR AX,AX,?0001:ADD AX,BX,ADD BX,2,LOOP?0001,可以看到,两次调用宏sum,展开后的结果中标号分别是?0000和?0001,是不同的。如果宏定义中没有LOCAL伪操作,展开结果中将在两个地方定义标号next,是重复定义。,汇编语言还规定,LOCAL伪操作必须出现在宏体的第1行上,在“宏名 MACRO”与LOCAL伪操作之间不允许有任何内容,包括空行、注释。,*7.3.6 宏的嵌套,类似于在子程序中可以调用另一个子程序,在一个宏体中也允许再调用另一个已定义的宏。对这种宏中套宏的宏调用,汇编程序将逐次展开,直到展开后的结果不再含有宏调用为止。,【例7.17】设某程序中已定义了3个字型变量v1、v2、v3,下面是源程序中的一段,试展开最后一行的宏调用。,mm1 MACRO x,MOV AX,x,MUL AX,ENDM,mm2 MACRO a,b,c,mm1 a,MOV BX,AX,mm1 b,ADD AX,BX,MOV c,AX,ENDM,mm2 v1,v2,v3,【解】展开mm2后得到:,mm1 v1,MOV BX,AX,mm1 v2,ADD AX,BX,MOV v3,AX,其中还含有宏调用,再把两个mm1展开后可得到如下结果:,MOV AX,v1,MUL AX,MOV BX,AX,MOV AX,v2,MUL AX,ADD AX,BX,MOV v3,AX,7.3.7 宏与子程序的比较,(1)处理的时间不同。宏调用是在源程序被汇编时由汇编程序处理的;而子程序调用是在程序执行期间由CPU直接执行的。,(2)处理的方式不同。宏必须先定义后调用,宏调用是用宏体替换宏调用伪指令,实参代替形参,源程序被翻译成目标代码后宏定义随之消失;而子程序的调用没有这样的替换操作,是以CALL指令将控制权由调用者转给子程序,(3)目标代码的长度不同。由于每一次宏调用都要进行宏展开,把宏体中的
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > PPT模板库


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!