3.3 伪操作指令
伪操作指令是一类特殊指令,它不是真正的单片机系统指令,没有机器码与伪指令对应。它存在于源程序中,但目标程序中并没有这些伪指令的代码,伪指令也因此而得名。伪指令是为了方便程序设计人员编程而设计的,在源程序中的作用是为完成汇编程序而做的各种准备工作,告诉汇编器如何完成汇编过程和一些规定的操作,控制汇编器的输入输出和数据定位等。它仅在汇编过程中起作用,一旦汇编结束,伪指令的使命也即随之完成。
伪指令语句主要由3部分组成,其一般格式为:
符号名 伪指令助记符 操作数
其中,符号名通常是代表专用寄存器名、通用寄存器变量、常数名、标志位或控制位名、复位矢量或中断矢量的一个字符串,其在书写时需要顶格,其后每部分之间用一个或一个以上的空格隔开,另外还需注意的是,一条语句只能占用一行,而不能分行。
在汇编程序MPASM中,有下列4类伪指令:
(1)数据伪指令:主要用于程序寄存器的定位和定义数据的名称等。
(2)列表伪指令:用于控制列表文件的指定标题、换页等。
(3)控制伪指令:即条件汇编,用于控制汇编的路径。
(4)宏汇编指令:用于控制宏定义体中的运行和数据定位。
下面将对这几类伪指令分别予以介绍。
1.数据伪指令
(1)DATA定义程序存储器的值
格式:〔<标号>〕DATA<操作数>,[<操作数>…] 例: DATA 3, 4+AB
(2)DEFINE定义字符串变量
格式:#DEFINE.<变量名>[<字符串>]
说明:用于定义文本替换的标号,用一定的变量名字替换源代码中的字符串,以使程序更加简洁,并且易于修改。
例:#DEFINE COUNT 07H;将程序中所有出现的用于定义循环次数的 07H都用COUNT代替。
(3)UNDEFINE取消己定义的字符串变量
格式:#UNDEFINE<变量名>
说明:用于取消以前定义过的文本替换标号。
(4)SET对标号赋值
格式:<标号>SET<表达式>
说明:用SET可对标号任意重新赋值,这与后面的CONSTANT伪指令不同。
例:WIDTH SET9 HEIGHT SET 12H WIDTH SET HEIGHT+8
(5)EQU对寄存器f和标号赋值
格式:<标号>EQU<表达式>
说明:为标号或寄存器赋值,标号一旦由EQU赋值,该值就不能再重新定义。
例:COUNT EQU 21H
(6)RES保留某段程序存储区
格式:RES<单元个数>
说明:保留10个空白字节。
例:RES 10
(7)INCLUDE包含其他外部源文件
格式:INCLUDE“文件名” INCLUDE<文件名>
说明:用于把指定文件读入源程序中作为源程序代码的一部分,直到检测到文件结束符时为止,再恢复到原源程序中的代码处。此伪指令可允许嵌套使用,最多可嵌套6层。文件名必须用双引号或尖括号给出。
例:INCLUDE“c∶\PIC\sysdefs.inc” INCLUDE<math.h>
(8)RADIX进制定义指令
格式:RADIX<进制表达式>
说明:用于设置常数数制的基数,有效的为十六进制、十进制、八进制,默认为十六进制。
例:RADIX DEC;十进制 RADIX HEX;十六进制 RADIX OCT;八进制
(9)CONSTANT定义符号常数
格式:CONSTANT<标号>[=<表达式>,<标号>[=<表达式>]…]
说明:用于对表达式中的常量符号进行定义,常量符号一旦被定义,在程序中就将被重新设置。这与伪指令VARIABLE不同,后者的值能在程序中修改。
例:VARIABLE MINVOLTAGE=12 CONSTANT MAXVOLTAGE=24 … VARIABLE MINVOLTAGE=5 CONSTANT DIFFVOLTAGE=MAXVOLTAGE—MINVOLTAGE
2.列表伪指令
(1)LIST列表选择指令
格式:LIST<选择项>,…,<选择项>
说明:用来设置各种汇编参数以控制汇编过程或对列表文件进行格式化。需注意的是,此伪指令的所有参数只能在一行内完成,参数的数值都用十进制数设置。
LIST列表选择伪指令可以选用的部分参数如表3-2所示。
表3-2 LIST选项表
例:LISTF=1NHX8M,R=DEC,P=16F877
(2)PAGE分页命令
格式:PAGE
说明:在列表文件中产生分页效果,即下面的文件输出将从新页面开始。
(3)TITLE程序标头命令
格式:TITLE‘程序标头’
说明:用于指定在列表文件中作为每一页开头第一行的程序标题,标头最长不超过60个字符。
例:TITLE‘This is for PIC16F877 demo’
3.控制伪指令
(1)ORG存放单元起始地址
格式:<标号>ORG<地址表达式>
说明:ORG用于指定该伪指令后面的源程序存放的起始地址,也就是汇编后的目标机器码存放的首地址。若ORG后面不带地址参数,则默认为零。若ORG带标号,则地址参数也赋值给该标号。在一个源程序中,可以根据需要多次使用ORG伪指令来定位。
例:ORG 00H GOTO MAIN … ORG 01H DISPLAY MOVLW 05H
(2)END结束伪指令
格式:END
说明:指令末的伪指令END是通知汇编程序MPASM结束对源程序(.ASM)的汇编,即使后面还有语句,也不再予以汇编。在一个源程序中必须有END伪指令,而且只能有一个END,放在整个程序的最后。
(3)IF条件汇编命令
格式:IF<条件表达式> <源程序行> <ELSE> <源程序行> ENDIF
说明:如果条件表达式为真,则汇编器将编译IF和ELSE之间的语句,反之编译ELSE和ENDIF之间的语句。ELSE可以默认。
例: IF COUNT=20 MOVLW 6 WOVWF DISP ELSE MOVLW 7 MOVWF DISP ENDIF
(4)WHILE条件循环命令
格式:WHILE<条件表达式> … ENDW
说明:当条件表达式满足条件时,即对WHILE与ENDW之间的源程序进行汇编,反之跳过。该循环最多允许有100行语句,最大循环次数为256次。
例:VARIABLE i WHILE i<count MOVLW i i=i+1 ENDW
4.MACRO宏定义
格式:<标号>MACRO[<参数1>,…,<参数N>] (宏体) ENDM
说明:宏指令可以对一个指令序列进行定义,定义后的宏指令可以在源程序中调用。通过宏调用,可以把被定义后的宏指令序列源程序代码插入到主程序中,另外,宏定义还可以嵌套使用。从表面上看,宏与程序类似,但宏定义只能使程序看起来更简洁一些,从而避免一些程序段在源程序中,此时它本身并不节省内存空间。当汇编器编译后,主程序每使用一次宏,程序存储器就要开销相应大小的空间,而子程序则不需要,这也是宏与子程序的最大区别。宏的使用分为宏定义和宏调用两个部分,举例如下:
例:① 宏定义: DISP MACRO X, Y, Z MOVLW 10H MOVWF X Y BSF FLAG:7 GOTO Y Z ENDM ② 宏调用: DISP DATE,LOOP,(CALL DISPLAY)
说明:DATA,LOOP,(CALL DISPLAY)分别相当于宏定义中的参数X,Y,Z。
③ 汇编后的源代码: MOVLW 10H MOVWF DATE LOOP BSF FLAG.7 GOTO LOOP CALL DISPLAY