内容正文:
第2章 单片机汇编语言程序设计
实训任务2 LED显示电路
2.1 MCS-51系列单片机汇编指令格式
2.2 寻址方式
2.3 MCS-51系列单片机指令系统
2.4 MCS-51系列单片机汇编程序设计
实训任务2 LED显示电路
任务:将0~9这十个数循环送P0口七段LED上显示。
图2-1 实训2电路
LED显示电路控制程序
ORG 0100H
START: SETB P2.0
MOV R0,#00H
MOV DPTR,#TABLE
DISP: MOV A,R0
MOVC A,@A+DPTR
MOV P0,A
ACALL DELAY
INC R0
CJNE R0,#0AH,DISP
AJMP START
DELAY: MOV R1,#0FFH
LOOP0: MOV R2,#0FFH
LOOP1: DJNZ R2,LOOP1
DJNZ R1,LOOP0
RET
TABLE: DB 0C0H,0F9H, 0A4H,0B0H,99H
DB 92H, 82H, 0F8H,80H, 90H
END
2.1 MCS-51系列单片机汇编指令格式
MCS -51系列单片机汇编指令格式如下:
[标号:] 操作码助记符 [目的操作数][,源操作数] [;注释]
例如:MOV A,#22H;A←22H
说明:
1)操作码助记符表明指令的功能,一般用说明其功能的英文单词的缩写形式表示。如MOV――MOVE表示传送。
2)操作数即操作对象,包括数据、数据的地址或指令的地址,用相应的寻址方式指明。操作数之间用逗号隔开。
3)标号是该指令的符号地址。标号后必须用冒号。
4)注释是对该指令的解释说明。注释前面须带分号。
2.2 寻址方式
寻找操作数地址的方式称为寻址方式。
MCS-51指令系统共使用了7种寻址方式,包括立即数寻址、寄存器寻址、直接寻址、寄存器间接寻址、变址寻址、相对寻址和位寻址。
2.2 寻址方式
1、立即数寻址(常数寻址)
操作数是常数,又称为立即数,使用时直接写在指令中,紧跟在操作码的后面,作为指令的一部分,与操作码一起存放在程序存储器中。立即数前面以“#”号作前缀。
例如:
MOV A,#20H
2.2 寻址方式
2、寄存器数寻址(寄存器寻址)
操作数在寄存器中,使用时在指令中直接提供寄存器的名称,这种寻址方式称为寄存器寻址。在MCS-51系统中,这种寻址方式针对的寄存器包括工作寄存器R0~R7、累加器A、通用寄存器B、地址寄存器DPTR等。
例如:
MOV A,R0
2.2 寻址方式
3、直接寻址
直接寻址是指操作数据在存储器单元中,指令中直接给出该存储器单元的地址。在MCS-51单片机中,可直接寻址的是片内RAM低128B空间和特殊功能寄存器。
例如:
MOV A,20H
MOV A,P0
注意:在MCS-51中,用“#”来区别立即数和直接地址,数据前面不加“#”是存储单元地址,加符号“#”是立即数。
2.2 寻址方式
4、寄存器间接寻址
寄存器间接寻址是指数据存放在存储单元中,将存储单元的地址存放在寄存器中,在指令中只提供存放存储单元地址的寄存器。执行指令时,首先根据寄存器的内容,找到所需要的操作数地址,再由该地址找到操作数并完成相应操作。形式为:@寄存器名。
例如:MOV A,@R0
在MCS-51指令系统中,用于寄存器间接寻址的寄存器有R0、R1和DPTR,称为寄存器间接寻址寄存器或数据指针。它能访问的数据是片内数据存储器和片外数据存储器。
若R0中的内容为20H,片内RAM地址为20H的单元中的内容为50H,则执行该指令后,累加器A的内容为50H
2.2 寻址方式
5、变址寻址
变址寻址所访问的存储器为程序存储器,指令中操作数的地址由基址寄存器的内容加上变址寄存器的内容得到。在MCS-51系统中,它是以数据指针寄存器DPTR或程序计数器PC为基址寄存器,累加器A为变址寄存器。 例如:
MOVC A,@A+DPTR
设指令执行前DPTR=2000H,A=05H,程序存储器2005H单元的内容为80H,则指令执行后,A=80H
2.2 寻址方式
6、变址寻址
变址寻址所访问的存储器为程序存储器,指令中操作数的地址由基址寄存器的内容加上变址寄存器的内容得到。在MCS-51系统中,它是以数据指针寄存器DPTR或程序计数器PC为基址寄存器,累加器A为变址寄存器。
例如:MOVC A,@A+DPTR
设指令执行前DPTR=2000H,A=05H,程序存储器2005H单元的内容为80H,则指令执行后,A=80H。
2.2 寻址方式
6、相对寻址
相对寻址是以程序计数器PC的当前值为基础,加上指令给出的相对偏移量rel形成新的PC值(又称目的地址)的寻址方式。该类寻址方式主要用于跳转指令。
例如:SJMP 50H
2.2 寻址方式
7、位寻址
位寻址是指操作数是某一个二进制位的寻址方式。在MCS-51系统中,位处理的操作对象是各种可位寻址位。对于它们的访问是通过提供相应的位地址来处理。
在MCS-51系统中,位地址的表示可以用以下几种方式:
1.直接位地址(00H~0FFH)。例如:20H
2.字节地址带位号。例如:20H.3表示20H单元的3位。
3.特殊功能寄存器名带位号。例如:P0.1表示P0口的1位。
4.位符号地址。例如:TR0是定时/计数器T0的启动位。
2.3 MCS-51系列单片机指令系统
MCS-51单片机指令系统共有33种功能,42种助记符,111条指令。其中有49条单字节指令,45条双字节指令和17条三字节指令;有64条为单机器周期指令,45条为双机器周期指令,只有乘、除法两条指令为四机器周期指令。
2.3.1 指令中用到的标识符
(1)Ri和Rn:表示当前工作寄存器区中的寄存器,i取0或1,表示R0或R1。n取0~7,表示R0~R7。
(2)#data:表示包含在指令中的8位立即数。
(3)#data16:表示包含在指令中的16位立即数。
(4)rel:以补码形式表示的8位偏移量,范围为-128~127,主要用在相对寻址的指令中。
(5)addr16和addr11:分别表示16位直接地址和11位直接地址。
(6)direct:直接地址,包括内部低128B RAM单元地址和全部特殊功能寄存器地址。
(7)bit:表示内部RAM 或特殊功能寄存器中的可直接寻址位。
(8)(X):表示X单元中的内容。
2.3.1 指令中用到的标识符
(9)((X)):表示以X单元的内容为地址的存储器单元内容,即(X)作地址,该地址单元的内容用((X))表示。
(10)/ :表示对指定位操作数取反,但不影响该位的原值。
(11)←:表示操作流程,将箭尾后面的内容送入箭头所指的单元中去。
(12)A : 累加器ACC。
(13)C : 进、借位标志位,或位累加器。
(14)@:间接寄存器或基址寄存器的前缀
(15)$ :当前指令的地址
2.3.2 数据传送类指令
数据传送操作是指把数据从源地址传送到目的地址,源地址内容不变。数据传送指令有29条,是指令系统中数量最多、使用也最频繁的一类指令。可分为五大类:内部传送指令;外部传送指令;交换指令;堆栈操作指令;查表指令。
一、内部传送指令
实现片内数据存储器中数据传送。
指令格式: MOV 目的操作数,源操作数
寻址方式可以采用立即寻址、直接寻址、寄存器寻址、寄存器间接寻址。源操作数可以为A、Rn、@Ri、direct、#data,目的操作数可以为A、Rn、@Ri、direct,组合起来共16条。
一、内部传送指令
(1)以A为目的操作数
MOV A,Rn ;A← Rn
MOV A,direct ;A←(direct)
MOV A,@Ri ;A←(Ri)
MOV A,#data ;A← #data
一、内部传送指令
(2)以Rn为目的操作数
MOV Rn,A ;Rn ← A
MOV Rn,direct ;Rn ←(direct)
MOV Rn,#data ;Rn ← #data
一、内部传送指令
(3)以直接地址direct为目的操作数
MOV direct,A ;(direct) ← A
MOV direct,Rn ;(direct) ←Rn
MOV direct2,direct1;(direct2)←(direct1)
MOV direct,@Ri ;(direct) ←(Ri)
MOV direct,#data ;(direct) ← #data
一、内部传送指令
(4)以间接地址@Ri为目的操作数
MOV @Ri,A ;(Ri) ← A
MOV @Ri,direct ;(Ri) ←(direct)
MOV @Ri,#data ;(Ri) ← #data
(5)以DPTR为目的操作数
MOV DPTR,#data16 ;DPTR ← #data16
一、内部传送指令
注意:
1、在MOV指令中,不允许在一条指令中同时出现工作寄存器,无论它是寄存器寻址(形式为Rn)还是寄存器间接寻址(形式为@Ri)。如不允许有“MOV R2,R1”,“MOV @R1,R7”这样的指令。
2、立即数不能作为目的操作数,如不允许有“MOV #50H,A”这样的指令。
3、区别以下两组指令:
MOV A, @R0 ; 以R0的内容为RAM地址,把该地址单元中的值送到A中去。
MOV A, R0 ; 将R0中的内容送到A去。
MOV A, #20H ; A的内容为立即数20H
MOV A, 20H ; A的内容为20H地址单元中的内容
二、外部传送指令
实现片外数据存储器和累加器A之间的数据传送。
指令格式:MOVX 目的操作数,源操作数
在MCS-51系统中只能通过累加器A与片外数据存储器进行数据传送,访问外数据存储器时,只能通过@Ri和@DPTR以间接寻址方式进行。
二、外部传送指令
1、 DPTR作16位数据指针,寻址整个64KB片外RAM空间
MOVX A,@DPTR ;A←(DPTR)
MOVX @DPTR,A ;(DPTR)←A
2、 Ri作8位数据指针,寻址片外RAM低256B空间
MOVX A,@Ri ;A←(Ri)
MOVX @Ri,A ;(Ri)←A
三、查表指令
实现从程序存储器读取数据到累加器A。
通常用于访问ROM中已做好的表格数据,因此称为查表指令。这类指令只能使用变址寻址方式来访问ROM。共两条指令,一条用DPTR为基址寄存器,一条用PC作基址寄存器。
MOVC A,@A+DPTR ;A ← (A+DPTR)
MOVC A,@A+PC ;A ← (A+PC)
四、数据交换指令
实现片内RAM区的数据双向传送。
数据交换指令要求第一个操作数须为累加器A,共有5条。
XCH A,Rn ;A ↔ Rn
XCH A ,direct ;A ↔ (direct)
XCH A,@Ri ;A ↔ (Ri)
XCHD A,@Ri ;A0~3 ↔ (Ri)0~3
SWAP A ;A0~3 ↔ A4~7
五、堆栈操作指令
在80C51中,堆栈的生长方向是向上的(地址增大)。
入栈操作: PUSH direct;SP←SP+1,(SP)←(direct)
出栈操作:POP direct;(direct)←(SP),SP ← SP-1
2.3.3 算术运算类指令
算术运算指令共24条,可以完成加、减、乘、除及加1和减1等运算。这类指令多数以A为源操作数之一,同时又使A为目的操作数。多数算术运算指令会影响标志位的状态,即CPU执行算术运算指令后,根据数据操作情况自动设置标志位的状态。
一.加法指令
1.不带进位加法指令ADD(影响标志位Cy、AC、OV和P)
ADD A,Rn ;A← A + Rn
ADD A,direct ;A← A +(direct)
ADD A,@Ri ;A← A +(Ri)
ADD A,#data ;A← A + #data
指令的功能是把源操作数与累加器A的内容相加,结果送入目的操作数A中。
一.加法指令
2.带进位加指令ADDC(影响标志位Cy、AC、OV和P)
ADDC A,Rn ;A← A + Rn + C
ADDC A,direct ;A← A +(direct)+ C
ADDC A,@Ri ;A← A +(Ri)+ C
ADDC A,#data ;A← A + #data + C
指令的功能是把源操作数与累加器A的内容相加再与进位标志CY的值相加,结果送入目的操作数A中。
一.加法指令
3.加1指令
INC A ;A← A + 1
INC Rn ;Rn← Rn + 1
INC direct ;(direct)← (direct)+ 1
INC @Ri ;(Ri)←(Ri)+ 1
INC DPTR ;DPTR← DPTR + 1
指令的功能是把源操作数的内容加 1 ,结果再送回原单元。除了INC A要影响P标志位外,对其它标志位都没有影响。
二.减法指令
1.带借位减法指令SUBB
SUBB A,Rn ;A← A - Rn - C
SUBB A,direct ;A← A -(direct)- C
SUBB A,@Ri ;A← A -(Ri)- C
SUBB A,#data ;A← A - #data – C
二.减法指令
2.减1指令DEC
DEC A ;A← A - 1
DEC Rn ;Rn← Rn - 1
DEC direct ;direct← (direct)- 1
DEC @Ri ;(Ri)←(Ri)- 1
三.十进制调整指令
在MCS-51单片机中,十进制调整指令只有一条:
DA A
它只能用在ADD或ADDC指令后面,用来对两个压缩的BCD码数进行二进制相加后的结果进行调整,使得它得到正确的十进制结果。通过该指令可实现两位十进制BCD码数的加法运算。
四.乘法指令MUL
在MCS-51单片机中,乘法指令只有一条:
MUL AB;BA←A×B,Cy←0,当积高字节B=0,OV←0;B≠0,则OV←1
该指令的功能是将存放于累加器A中的无符号被乘数和放于B寄存器中的无符号乘数相乘,积的高字节存于B寄存器中,低字节存于累加器A中。
指令执行后将影响Cy和OV标志,Cy复位,对于OV:当积大于255时(即B中不为0),OV为1;否则,OV为0。
五.除法指令DIV
在MCS-51单片机中,除法指令也只有一条:
DIV AB;A÷B,A←商,B←余数,Cy←0,当除数B=0,OV←1;B≠0,则OV←0
该指令执行时将用存放在累加器A中的无符号被除数与存放在寄存器B中的无符号除数相除,除得的结果,商的整数部分存于累加器A中,余数存于寄存器B中。
指令执行后将影响CY和OV标志,一般情况CY和OV都清0,只有当B寄存器中的除数为0时,结果的A和B的内容不定,CY和OV才被置1。
2.3.4 逻辑运算及移位类指令
逻辑运算指令共有24条。主要用于对8位数进行逻辑“与”、“或”、“异或”、取反、清零以及循环移位。
一.逻辑与指令ANL
ANL A,Rn ; A← A Rn
ANL A,direct ;A← A (direct)
ANL A,@Ri ;A← A (Ri)
ANL A,#data ;A← A data
ANL direct,A ;(direct)← (direct) A
ANL direct,#data ;(direct)← (direct) data
2.3.4 逻辑运算及移位类指令
二.逻辑或指令ORL
ORL A,Rn ; A← A Rn
ORL A,direct ; A← A (direct)
ORL A,@Ri ;A← A (Ri)
ORL A,#data ; A← A data
ORL direct,A ;(direct)← (direct) A
ORL direct,#data ;(direct)← (direct) data
2.3.4 逻辑运算及移位类指令
三.逻辑异或指令XRL
XRL A,Rn ; A← A + Rn
XRL A,direct ; A← A +(direct)
XRL A,@Ri ; A← A +((Ri))
XRL A,#data ;A← A +#data
XRL direct,A ;(direct)← (direct)+ A
XRL direct,#data ;(direct)← (direct)+ data
2.3.4 逻辑运算及移位类指令
在使用中,逻辑与常用于实现对指定位清0,其余位不变;逻辑或常用于实现对指定位置1,其余位不变;逻辑异或常用于实现对指定位取反,其余位不变。
例2-10 写出完成下列功能的指令段。
1.对累加器A中的1、3、5位清0,其余位不变
ANL A,#11010101B
2.对累加器A中的2、4、6位置1,其余位不变
ORL A,#01010100B
3.对累加器A中的高4位取反,其余位不变
XRL A,#11110000B
2.3.4 逻辑运算及移位类指令
四.累加器清零和求反指令
1.清零指令:CLR A;A← 0
2.求反指令:CPL A;A← Ā
五.循环移位指令
1.累加器A的内容循环左移一位:RL A
2.累加器A的内容循环右移一位:RR A
3.累加器A的内容连同进位CY循环左移一位:
RLC A
4.累加器A的内容连同进位CY循环右移一位:
RRC A
2.3.5 控制转移类指令
程序执行是顺序的,改变程序执行的顺序,称作程序转移。控制转移类指令通过改写PC的当前值,从而改变CPU执行程序的顺序,使程序发生跳转。这类指令共有17条,包括无条件转移指令、条件转移指令、子程序调用及返回指令。
2.3.5 控制转移类指令
一.无条件转移指令
无条件转移指令是指当执行该指令后,程序无条件转移到指定处。无条件转移指令包括长转移指令、绝对转移指令、相对转移指令和间接转移指令。
1.长转移指令LJMP
指令格式:LJMP addr16 ;PC ← addr16
2.3.5 控制转移类指令
2.绝对转移指令
指令格式:AJMP addr11 ;PC←PC+2,PC10~0 ← addr11,PC15-11不变
3.相对转移指令
指令格式:SJMP rel ;PC ← PC + 2 + rel
4.间接转移指令
指令格式:JMP @A+DPTR ;PC ← A + DPTR
2.3.5 控制转移类指令
二.条件转移指令
条件转移指令是指当条件满足时,程序转移到指定位置,条件不满足时,程序将继续顺次执行。在MCS-51系统中,条件转移指令有三种:累加器A判零转移指令、比较不等转移指令、减1不为零转移指令。
1.累加器A判零转移指令
判0指令:JZ rel ;若A=0,则PC ← PC + 2 + rel,否则,PC ← PC + 2
判非0指令:JNZ rel ;若A0,则PC ← PC + 2 + rel,否则,PC ← PC + 2
2.3.5 控制转移类指令
2.比较不等转移指令
比较不等转移指令用于对两个数作比较,并根据比较情况进行转移,有四条指令:
CJNE A,#data,rel ;若A≠data,则转移PC ← PC + 3+ rel,否则顺序执行; 若A<data,则Cy=1,否则Cy=0
CJNE Rn,#data,rel ;若Rn≠data,则转移PC ← PC + 3 + rel,否则顺序执行; 若Rn<data,则Cy=1,否则Cy=0
CJNE @Ri,#data,rel ;若(Ri) ≠data,则转移PC ← PC + 3 + rel,否则顺序执行,若(Ri)<data,则Cy=1,否则Cy=0
CJNE A,direct,rel ;若A≠direct,则转移PC ← PC + 3+ rel,否则顺序执行; 若A<direct,则Cy=1,否则Cy=0
该类指令具有比较和判断双重功能。
2.3.5 控制转移类指令
3.减1不为零转移指令
这种指令是先减1后判断,目的操作数内容减1后,若差值不为零,则转移;否则顺序执行。
DJNZ Rn,rel; RnRn-1,若Rn≠0,则PCPC+2+rel, 否则顺序执行
DJNZ direct,rel;(direct)(direct)-1,若(direct)≠0,则PCPC+3+rel,否则顺序执行
在MCS-51系统中,通常用DJNZ指令来构造循环结构,实现重复处理。
2.3.5 控制转移类指令
例2-13 将片内RAM中40H~4FH共16个字节单元清零。
程序如下:
MOV R0,#40H
MOV R7,#10H
CLR A
LOOP:MOV @R0,A
INC R0
DJNZ R7,LOOP
SJMP $
2.3.5 控制转移类指令
三.子程序调用及返回指令
子程序调用和返回指令也使程序发生转移。这类指令有四条。两条子程序调用指令,两条返回指令。
子程序调用过程如图2-7所示:
图2-7 子程序调用示意图
2.3.5 控制转移类指令
1.长调用指令
指令格式:LCALL addr16
;PC←PC+3
;SP←SP+1,(SP)←PC7~0
; SP←SP+1,(SP)←PC15~8
;PC←addr16
由于后面带16位地址,因而可以转移到程序存储器64K范围的任一位置。
2.3.5 控制转移类指令
2.绝对调用指令
指令格式:ACALL addr11
;PC←PC+2
;SP←SP+1,(SP)←PC7~0
;SP←SP+1,(SP)←PC15~8
;PC10~0←addr11,PC15~11不变
该指令执行过程与LCALL指令类似,只是转移范围与PC+ 2在同一个2KB内。
2.3.5 控制转移类指令
3.子程序返回指令
指令格式:
RET ;PC15~8←(SP),SP←SP-1
; PC7~0←(SP),SP←SP-1
执行时将子程序调用指令压入堆栈的地址出栈,第一次出栈的内容送PC的高8位,第二次出栈的内容送PC的低8位。执行完后,程序转移到新的PC位置执行指令。由于子程序调用指令执行时压入的内容是调用指令的下一条指令的地址,因而RET指令执行后,程序将返回到调用指令的下一条指令执行。
该指令通常放在子程序的最后一条指令位置,用于实现返回到主程序。
2.3.5 控制转移类指令
4.中断返回指令
指令格式:
RETI;PC15~8←(SP),SP←SP-1,PC7~0←(SP),SP←SP-1
该指令的执行过程与RET基本相同,只是RETI在执行时,能清除内部相应的中断状态寄存器(以保证正确的中断逻辑)。该指令用于中断服务子程序后面,作为中断服务子程序的最后一条指令,它的功能是返回主程序中断的断点位置,继续执行断点位置后面的指令。
2.3.6 位操作指令
在MCS-51系统中,有17条位处理指令,可以通过位累加器C(即进位标志Cy位)和位地址bit实现位传送、位逻辑运算、位控制转移等操作。
一.位传送指令
位传送指令有两条,用于实现C与一般位之间的相互传送。
MOV C,bit ;C←(bit)
MOV bit,C ;(bit)←C
2.3.6 位操作指令
二.位逻辑操作指令
位逻辑操作指令包括位清0、置1、取反、位逻辑与和位逻辑或,总共10位指令。
1.位清0
CLR C ;C←0
CLR bit ;(bit)←0
2.位置1
SETB C ;C←1
SETB bit ;(bit)←1
2.3.6 位操作指令
3.位取反
CPL C ;C←0
CPL bit ;(bit)←0
4.位逻辑与
ANL C,bit ;C←C∧(bit)
ANL C,/bit ;C←C∧ (bit)
5.位逻辑或
ORL C,bit ;C←C∨(bit)
ORL C,/bit ;C←C∨ (bit)
注意:指令中的/bit并不改变了bit位的原值,只是取得中间值参与运算。
2.3.6 位操作指令
三.位转移指令
1.判C位转移指令
JC rel; 若C=1,则转移,PC←PC+2+rel;否则程序顺序执行
JNC rel; 若C=0,则转移,PC←PC+2+rel;否则程序顺序执行
2.判bit位转移指令
JB bit,rel ; 若bit=1,则转移,PC←PC+3+rel;否则程序顺序执行
JNB bit,rel ; 若bit=0,则转移,PC←PC+3+rel;否则程序顺序执行
JBC bit,rel ; 若bit=1,则转移,PC←PC+3+rel,且bit←0;否则程序顺序执行
利用位转移指令可进行各种测试。
2.3.6 位操作指令
四.空操作指令
NOP ;PC ← PC+1
指令执行时,不作任何操作(即空操作),仅将程序计数器PC的内容加1,使CPU指向下一条指令继续执行程序。它要占用一个机器周期,常用来产生时间延迟,构造延时程序。
2.3.7 常用伪指令
伪指令是放在汇编语言源程序中用于指示汇编程序如何对源程序进行汇编的指令,伪指令只是对汇编过程进行相应的控制和说明,既不控制机器的操作,也不能被汇编成机器代码,故称为伪指令。
2.3.7 常用伪指令
1.起始地址设定伪指令
格式:ORG 地址(十六进制表示)
这条伪指令放于一段源程序或数据的前面,汇编时用于指明程序或数据从程序存储空间什么位置开始存放。ORG伪指令后的地址是程序或数据的起始地址。
例2-16 ORG 1000H
START:MOV A,#00H
·
·
·
指明后面的程序从程序存储器的1000H单元开始存放。
2.3.7 常用伪指令
2.字节数据表定义伪指令
格式:[标号:] DB 字节数据表
将字节数据表中的数据按从左到右的顺序依次存放在指定的存储单元中。一个数据占一个存储单元。在定义时前面可以带标号,定义的标号在程序中是字节数据表起始单元的地址。
例2-17 ORG 3000H
TAB1: DB 12H,34H, '5','A','abc'
图2-8 定义字节数据表时ROM存储器示意图
2.3.7 常用伪指令
3.字数据表定义伪指令
格式:[标号:] DW 字数据表
这条指令与DB相似,但用于定义字数据。所定义的一个字在存储器中占两个字节。汇编时,机器自动按低字节在前,高字节在后,即低字节存放在低地址单元,高字节存放在高地址单元。
例2-18 ORG 3000H
TAB2:DW 1234H,5678H
图2-9 定义字数据表时存储器示意图
2.3.7 常用伪指令
4.赋值伪指令
格式:符号名 EQU 项
该伪指令的功能是将指令中的项的值赋予EQU前面的符号。项可以是常数、地址标号或表达式。以后可以通过使用该符号使用相应的项。
例2-19 TAB1 EQU 1000H
TAB2 EQU 2000H
汇编后TAB1、TAB2分别等于1000H、2000H。程序后面使用1000H、2000H的地方就可以用符号TAB1、TAB2替换。
用EQU伪指令对某标号赋值后,该符号的值在整个程序中不能再改变。
2.3.7 常用伪指令
5.位地址符号定义伪指令
格式:符号名 bit 位地址
该伪指令用于给位地址赋予符号,经赋值后可用该符号代替bit后面的位地址。
例2-20 P10 bit P1.0
定义后,在程序中位地址P1.0就可以通过P10来使用。
2.3.7 常用伪指令
6.结束汇编伪指令
格式:END
该指令放于程序最后位置,用于指明汇编语言源程序的结束位置,当汇编程序汇编到END伪指令时,汇编结束。END后面的指令,汇编程序都不予处理。一个源程序只能有一个END命令,否则就有一部分指令不能被汇编。
2.4 MCS-51系列单片机汇编程序设计
2.4.1 简单程序设计
简单程序即顺序程序,指无分支、无循环结构的程序,其特点是按指令的排列顺序一条条地执行,直到全部指令执行完毕为止。
例2-21 双字节无符号数加法。
设被加数存放在内部RAM的51H、50H单元,加数存放在内部RAM的61H、60H单元,相加的结果存放在内部RAM的51H、50H单元,进位存放在52H单元。
2.4.1 简单程序设计
MOV A,50H ;取被加数低字节
ADD A,60H ;加上加数低字节
MOV 50H,A ;保存低字节相加结果
MOV A,51H ;取被加数高字节
ADDC A,61H ;加上加数高字节(带进位加)
MOV 51H,A ;存高字节相加结果
ADDC A,#00H ;得到进位
MOV 52H,A ;保存进位
2.4.2 分支程序设计
分支程序结构就是根据条件是否满足来改变程序执行的顺序,即程序的流向有两个或两个以上的出口,并根据指定的条件选择程序流向的程序结构。分支结构如图图2-10所示。
图2-10 分支程序结构示意图
2.4.2 分支程序设计
例2-22 在内部RAM40H单元内有一变量X,请根据下式对Y赋值并存于41H单元。
2.4.2 分支程序设计
程序清单:
ORG 0050H
MOV A,40H ;A←X
JZ DONE ;若X=0,则转DONE
JNB ACC.7,NEXT ;若X>0,则转NEXT
MOV A,#0FFH ;若X<0,则A←-1
SJMP DONE
NEXT: MOV A,#01H ;若X>0,则A←1
DONE: MOV 41H,A ;存Y值
SJMP $
RET
2.4.2 分支程序设计
例2-23 下面的程序能根据累加器A的值0、2、4、6转移到相应的TAB0~TA6分支去执行。
MOV DPTR,#TABLE ;表首地址送DPTR
JMP @A+DPTR ;根据A值转移
TABLE: AJMP TAB0 ;当(A)=0时转TAB0执行
AJMP TAB2 ;当(A)=2时转TAB2执行
AJMP TAB4 ;当(A)=4时转TAB4执行
AJMP TAB6 ;当(A)=6时转TAB6执行
2.4.3 循环程序设计
按某种控制规律重复执行的程序称为循环程序。
循环结构的一般处理过程如图2-11所示。
2.4.3 循环程序设计
由循环结构流程图可以看出,循环程序一般包含四部分:
1、循环初始化部分
作循环的准备工作。如:清结果单元、设地址指针、设循环控制变量初值等。
2、循环处理部分
即循环主体,是需要多次重复执行的程序段。
3、循环控制部分
主要完成修改地址指针和循环控制变量,检测循环结束条件。循环次数已知,可用计数器控制循环次数;循环次数未知,按问题条件控制循环是否结束。
4、结果处理部分
对结果分析、处理并保存循环结果。
2.4.3 循环程序设计
例2-24 设计一个50ms延时程序。设单片机时钟晶振频率fosc为12MHz。
若晶振频率为12MHz,则一个机器周期为1μs。执行一条DJNZ指令需要2个机器周期,即 2μs。采用循环计数法实现延时,循环次数可以通过计算获得,并选择先执行后判断的循环结构。程序段如下:
DEL: MOV R7,#200 ;1 μs
DEL1: MOV R6,#123 ;1 μs
NOP ;1 μs
DEL2: DJNZ R6,DEL2 ;2μs,计(2×123)μs
DJNZ R7,DEL1 ;2μs,
RET
共计 [(2×123+2+ 2)×200+1] μs,即50.001ms
2.4.4 查表程序
例2-26 在ROM中定义一个0~9平方表,利用查表指令找出x的平方值。
TA: PUSH DPH
PUSH DPL
MOV A, #x
MOV DPTR, #TAB
MOVC A,@A+DPTR
POP DPL
POP DPH
RET
ORG 2000H
TAB: DB 0,1,4,9,16,25,36,49,64,81
2.4.5 子程序设计
在解决实际问题时,经常会在一个程序中多次使用具有一定功能的同一个程序段,例如延时程序、查表程序、数值转换、数值计算等功能相对独立的程序段。
为了节约内存,我们把这种具有一定功能的独立程序段编成子程序,例如延时子程序。当需要时,可以去调用这些独立的子程序。调用程序称为主程序,被调用的程序称为子程序。
2.4.5 子程序设计
子程序设计的一般步骤:
1)确定子程序名称,即入口标号。
2)确定子程序的输入/输出参数。
3)确定所用的寄存器和存储单元,以便现场保护。断点保护由指令自动完成。
4)确定子程序的算法,编写源程序。
2.4.5 子程序设计
子程序设计时要注意:
1)子程序的第一条语句必须有一个标号,如DELAY,代表该子程序第一个语句的地址,也称为子程序入口地址,供主程序调用;子程序的最后一条语句必须是子程序返回指令RET。
2)现场保护与恢复;堆栈的功能是为了子程序调用和返回而设计的,执行调用指令(LCALL、ACALL)时,CPU自动把断点地址压栈;执行返回指令RET时,自动从堆栈中弹出断点地址。可经常用堆栈暂存中间结果或数据。只是使用时需要注意堆栈先进后出的特点。另外,在子程序调用时,CPU会自动利用堆栈进行保护现场和恢复现场。
3)子程序应具有通用性
�
图2.7 定义字节数据表时ROM存储器示意图
条件成立?
下条指令
程序段A
Y
N
条件成立?
程序段A
Y
N
程序段B
K=0?
K=1?
Y
分支1
分支0
Y
K=2?
Y
分支2
N
N
N
$$