51汇编学习第三章小结
本章重点
MCS-51的寻址方式和寻址空间
MCS-51的指令分类
MCS-51指令系统中各指令的执行过程
MCS-51指领的应用特点
一、MCS-51单片机指令系统概述
1、指令格式
指令操作码用8位二进制数编码,共有255种,指令不同操作码和操作数也不同,有些两者加起来只有一个字节称为单字节指令,有些是操作码和操作数各占一个字节称为双字节指令,有的操作码战一个字节,操作数占两个字节称为3字节指令
A、单字节指令有的没有指定操作数的指令,如INC DPTR,有的有操作数指令,如MOV A,Rn
B、双字节指令在程序存储器中占两个字节单元,操作码字节在前,操作数在后,如ADD A,#08H
C、三字节指令第一个字节为操作码,第二和第三为操作数或者操作数地址如MOV DPTR,#1234
2、指令分类
A、数据传送指令:可用于在单片机CPU内部寄存器、内部RAM、特殊功能寄存器、外部RAM及I/O口、程序存储器之间传送数据
B、算术运算指令:用于两个操作数进行加减乘除等,绝大多数指令要求一个操作数必须存放在累加器A内,而且运算结果仍存回A中
C、逻辑运算和循环移位指令:用于对两个操作希特勒按位进行与、或、异或、取反等操作,大多数也要求把一个操作数和结果放入累加器A中
D、位操作指令:可实现位的传送、修改、运算和位控制转移
E、流程控制类指令:实现无条件转移、条件转移、子程序调用和返回等具体方法就是修改程序计数器PC的值
3、指令系统中使用的符号Rn,A,B……..
51单片机的寻址方式
学习汇编程序设计,要先了解CPU的各种寻址法,才能有效的掌握各个命令的用途,寻址法是命令运算码找操作数的方法。
指令的寻址方式 MOV P1,#0FFH这条指令,第一个词MOV是命令动词,也就是决定做什么事情的,MOV是MOVE少写了一个E,所以就是“传递”,这就是指令,规定做什么事情,数据传递必须要有一个“源”也就是你要送什么数,必须要有一个“目的”,也就是你这个数要送到什么地方去,显然在上面那条指令中,要送的数(源)就是0FFH,而要送达的地方(目的地)就是P1这个寄存器。
寻址方式:指定操作数所在单元的方法。
注意:源操作数、目的操作数都有各自的寻址方式。 掌握指令的7种寻址方式的作用以及不同寻址方式所查询的存储空间及范围,对于常用的指令,能够给出指令的寻址方式。
在我们学习的8051单片机中,有7种寻址方法,下面我们将逐一进行分析。
立即寻址
所要找的操作数是一二进制数或十进制数,出现在指令中,用“#”作前缀
MOV A,#20H
在这种寻址方式中,指令多是双字节的,一般第一个字节是操作码,第二个字节是操作数。该操作数直接参与操作,所以又称立即数,有“#”号表示。立即数就是存放在程序存储器中的常数,换句话说就是操作数(立即数)是包含在指令字节中的。
例如:
MOV A,#3AH
这条指令的指令代码为74H、3AH,是双字节指令,这条指令的功能是把立即数3AH送入累加器A中。
MOV DPTR,#8200H
在前面学单片机的专用寄存器时,我们已学过,DPTR是一个16位的寄存器,它由DPH及DPL两个8位的寄存器组成。这条指令的意思就是把立即数的高8位(即82H)送入DPH寄存器,把立即数的低8位(即00H)送入DPL寄存器。
这里也特别说明一下:在80C51单片机的指令系统中,仅有一条指令的操作数是16位的立即数,其功能是向地址指针DPTR传送16位的地址,即把立即数的高8位送入DPH,低8位送入DPL。
直接寻址
指令中直接给出操作数的地址。
MOV A,30H
MOV 30H,DPH
直接寻址方式是指在指令中操作数直接以单元地址的形式给出,也就是在这种寻址方式中,操作数项给出的是参加运算的操作数的地址,而不是操作数。
例如:MOV A,30H
这条指令中操作数就在30H单元中,也就是30H是操作数的地址,并非操作数。
在80C51单片机中,直接地址只能用来表示特殊功能寄存器、内部数据存储器以及位地址空间,具体的说就是:
1、内部数据存储器RAM低128单元。在指令中是以直接单元地址形式给出。
我们知道低128单元的地址是00H-7FH。在指令中直接以单元地址形式给出这句话的意思就是这0-127共128位的任何一位,例如0位是以00H这个单元地址形式给出、1位就是以01H单元地址给出、127位就是以7FH形式给出。
2、位寻址区。20H-2FH地址单元。
3、特殊功能寄存器。专用寄存器除以单元地址形式给出外,还可以以寄存器符号形式给出。例如下面我们分析的一条指令 MOV IE,#85H 前面的学习我们已知道,中断允许寄存器IE的地址是80H,那么也就是这条指令可以以MOV IE,#85H 的形式表述,也可以MOV 80H,#85H的形式表述。
关于数据存储器RAM的内部情况,请查看我们课程的第十二课。
直接寻址是唯一能访问特殊功能寄存器的寻址方式!
大家来分析下面几条指令:
MOV 65H,A ;将A的内容送入内部RAM的65H单元地址中
MOV A,direct ;将直接地址单元的内容送入A中
MOV direct,direct;将直接地址单元的内容送直接地址单元
MOV IE,#85H ;将立即数85H送入中断允许寄存器IE
前面我们已学过,数据前面加了“#”的,表示后面的数是立即数(如#85H,就表示85H就是一个立即数),
数据前面没有加“#”号的,就表示后面的是一个地址地址(如,MOV 65H,A这条指令的65H就是一个单元地址)。
寄存器寻址
操作数存放在工作寄存器R0 ~ R7中,或寄存器B中。
MOV A,R2
寄存器寻址的寻址范围是:
1、4个工作寄存器组共有32个通用寄存器,但在指令中只能使用当前寄存器组(工作寄存器组的选择在前面专用寄存器的学习中,我们已知道,是由程序状态字PSW中的RS1和RS0来确定的),因此在使用前常需要通过对PSW中的RS1、RS0位的状态设置,来进行对当前工作寄存器组的选择。
2、部份专用寄存器。例如,累加器A、通用寄存器B、地址寄存器DPTR和进位位CY。
寄存器寻址方式是指操作数在寄存器中,因此指定了寄存器名称就能得到操作数。
例如:MOV A,R0
这条指令的意思是把寄存器R0的内容传送到累加器A中,操作数就在R0中。
INC R3
这条指令的意思是把寄存器R3中的内容加1
从前面的学习中我产应可以理解到,其实寄存器寻址方式就是对由PSW程序状态字确定的工作寄存器组的R0-R7进行读/写操作。
寄存器间接寻址
指令中寄存器的内容作为操作数存放的地址,指令中间接寻址寄存器前用
“@”表示前缀。
举“两个抽屉,两把钥匙”的例子。
MOV R0,#30H
MOV A,@R0
MOV A,#20H
MOV R1,#40H
MOV @R1,A
寄存间接寻址方式是指寄存器中存放的是操作数的地址,即操作数是通过寄存器间接得到的,因此称为寄存器间接寻址。
MCS-51单片机规定工作寄存器的R0、R1做为间接寻址寄存器。用于寻址内部或外部数据存储器的256个单元。为什么会是256个单元呢?我们知道,R0或者R1都是一个8位的寄存器,所以它的寻址空间就是2的八次方=256。
例:MOV R0,#30H ;将值30H加载到R0中
MOV A,@R0;把内部RAM地址30H内的值放到累加器A中
MOVX A,@R0 ;把外部RAM地址30H内的值放到累加器A中
大家想想,如果用DPTR做为间址寄存器,那么它的寻址范围是多少呢?DPTR是一个16位的寄存器,所以它的寻址范围就是2的十六次方=65536=64K。因用DPTR做为间址寄存器的寻址空间是64K,所以访问片外数据存储器时,我们通常就用DPTR做为间址寄存器。
例:MOVDPTR,#1234H ;将DPTR值设为1234H(16位)
MOVXA,@DPTR;将外部RAM或I/O地址1234H内的值放到累加器A中
在执行PUSH(压栈)和POP(出栈)指令时,采用堆栈指针SP作寄存器间接寻址。
例:PUSH 30H ;把内部RAM地址30H内的值放到堆栈区中
堆栈区是由SP寄存器指定的,如果执行上面这条命令前,SP为60H,命令执行后会把内部RAM地址30H内的值放到RAM的61H内。
那么做为寄存器间接寻址用的寄存器主要有哪些呢?我们前面提到的有四个,R0、R1、DPTR、SP
寄存器间接寻址范围总结:
1、内部RAM低128单元。对内部RAM低128单元的间接寻址,应使用R0或R1作间址寄存器,其通用形式为@Ri(i=0或1)。
2、外部RAM 64KB。对外部RAM64KB的间接寻址,应使用@DPTR作间址寻址寄存器,其形式为:@DPTR。
例如MOVX A,@DPTR;其功能是把DPTR指定的外部RAM的单元的内容送入累加器A中。
外部RAM的低256单元是一个特殊的寻址区,除可以用DPTR作间址寄存器寻址外,还可以用R0或R1作间址寄存器寻址。
例如MOVX A,@R0;这条指令的意思是,把R0指定的外部RAM单元的内容送入累加器A。
堆栈操作指令(PUSH和POP)也应算作是寄存器间接寻址,即以堆栈指针SP作间址寄存器的间接寻址方式。
寄存器间接寻址方式不可以访问特殊功能寄存器!!
寄存器间接寻址也须以寄存器符号的形式表示,为了区别寄存器寻址我寄存器间接寻址的区别,在寄存器间接寻址方式式中,寄存器的名称前面加前缀标志“@”。
基址寄存器加变址寄存器的变址寻址
操作数地址 = 变地址 + 基地址
基地址寄存器 DPTR 或 PC
变址寄存器 @A
该寻址方式常用于访问程序存储器,查表。
MOV A,@A + DPTR
这种寻址方式以程序计数器PC或DPTR为基址寄存器,累加器A为变址寄存器,变址寻址时,把两者的内容相加,所得到的结果作为操作数的地址。这种方式常用于访问程序存储器ROM中的数据表格,即查表操作。
变址寻址只能读出程序内存入的值,而不能写入,也就是说变址寻址这种方式只能对程序存储器进行寻址,或者说它是专门针对程序存储器的寻址方式。
例:MOVC A,@A+DPTR
这条指令的功能是把DPTR和A的内容相加,再把所得到的程序存储器地址单元的内容送A
假若指令执行前A=54H,DPTR=3F21H,则这条指令变址寻址形成的操作数地址就是54H+3F21H=3F75H。如果3F75H单元中的内容是7FH,则执行这条指令后,累加器A中的内容就是7FH。
变址寻址的指令只有三条,分别如下:
JMP @A+DPTR
MOVC A,@A+DPTR
MOVC A,@A+PC
第一条指令JMP @A+DPTR
这是一条无条件转移指令,这条指令的意思就是DPTR加上累加器A的内容做为一个16位的地址,执行JMP这条指令是,程序就转移到A+DPTR指定的地址去执行。
第二、三条指令MOVC A,@A+DPTR和MOVC A,@A+PC指令
这两条指令的通常用于查表操作,功能完全一样,但使用起来却有一定的差别,现详细说明如下。
我们知道,PC是程序指针,是十六位的。DPTR是一个16位的数据指针寄存器,按理,它们的寻址范围都应是64K。我们在学习特殊功能寄存器时已知道,程序计数器PC是始终跟踪着程序的执行的。也就是说,PC的值是随程序的执行情况自动改变的,我们不可以随便的给PC赋值。而DPTR是一个数据指针,我们就可以给空上数据指针DPTR进行赋值。我们再看指令MOVC A,@A+PC这条指令的意思是将PC的值与累加器A的值相加作为一个地址,而PC是固定的,累加器A是一个8位的寄存器,它的寻址范围是256个地址单元。讲到这里,大家应可明白,MOVC A,@A+PC这条指令的寻址范围其实就是只能在当前指令下256个地址单元。所在,这在我们实际应用中,可能就会有一个问题,如果我们需要查询的数据表在256个地址单元之内,则可以用MOVC A,@A+PC这条指令进行查表操作,如果超过了256个单元,则不能用这条指令进行查表操作。刚才我们已说到,DPTR是一个数据指针,这个数据指针我们可以给它赋值操作的。通过赋值操作。我们可以使MOVC A,@A+DPTR这条指令的寻址范围达到64K。这就是这两条指令在实际应用当中要注意的问题。
变址寻址方式是MCS-51单片机所独有的一种寻址方式。
位寻址
80C51单片机有位处理功能,可以对数据位进行操作,因此就有相应的位寻址方式。所谓位寻址,就是对内部RAM或可位寻址的特殊功能寄存器SFR内的某个位,直接加以置位为1或复位为0。
位寻址的范围,也就是哪些部份可以进行位寻址:
1、我们在学习51单片机的存储器结构时,我们已知道在单片机的内部数据存储器RAM的低128单元中有一个区域叫位寻址区。它的单元地址是20H-2FH。共有16个单元,一个单元是8位,所以位寻址区共有128位。这128位都单独有一个位地址,其位地址的名字就是00H-7FH。
这里就有一个比较麻烦的问题需要大家理解清楚了。我们在前面的学习中00H、01H。。。。7FH等等,所表示的都是一个字节(或者叫单元地址),而在这里,这些数据都变成了位地址。我们在指令中,或者在程序中如何来区分它是一个单元地址还是一个位地址呢?这个问题,也就是我们现在正在研究的位寻址的一个重要问题。其实,区分这些数据是位地址还是单元地址,我们都有相应的指令形式的。这个问题我们在后面的指令系统学习中再加以论述。
2、对专用寄存器位寻址。这里要说明一下,不是所有的专用寄存器都可以位寻址的。具体哪些专用寄存器可以哪些专用寄存器不可以,请大家回头去看看我们前面关于专用寄存器的相关文章。一般来说,地址单元可以被8整除的专用寄存器,通常都可以进行位寻址,当然并不是全部,大家在应用当中应引起注意。
相对寻址
把指令中给定的地址偏移量与本指令所在单元地址(PC内容)相加得到真正有效的操作数所存放的地址。
举“李同学20岁,张同学比李同学大3岁”的例子。
JC 60H ;设(PC) = 2000H,
则当C = 1时,
转移的目的地址 = (PC)+ 2 + 60H
专用寄存器的位寻址表示方法:
下面我们以程序状态字PSW来进行说明
D7
D6
D5
D4
D3
D2
D1
D0
CY
AC
F0
RS1
RS0
OV
P
1、直接使用位地址表示:看上表,PSW的第五位地址是D5,所以可以表示为D5H
MOV C,D5H
2、位名称表示:表示该位的名称,例如PSW的位5是F0,所以可以用F0表示
MOV C,F0
3、单元(字节)地址加位表示:D0H单元位5,表示为DOH.5
MOV C,D0H.5
4、专用寄存器符号加位表示:例如PSW.5
MOV C,PSW.5
这四种方法实现的功能都是相同的,只是表述的方式不同而已。
例题:
1. 说明下列指令中源操作数采用的寻址方式。
MOV R5,R7 答案:寄存器寻址方式
MOV A,55H 直接寻址方式
MOV A,#55H 立即寻址方式
JMP @A+DPTR 变址寻址方式
MOV 30H,C 位寻址方式
MOV A,@R0 间接寻址方式
MOVX A,@R0 间接寻址方式
改错题
请判断下列的MCS-51单片机指令的书写格式是否有错,若有,请说明错误原因。
MOV R0,@R3 答案: 间址寄存器不能使用R2~R7。
MOVC A,@R0+DPTR 变址寻址方式中的间址寄存器不可使用R0,只可使用A。
ADD R0,R1 运算指令中目的操作数必须为累加器A,不可为R0。
MUL AR0 乘法指令中的乘数应在B寄存器中,即乘法指令只可使用AB寄存器组合。
三、数据传送指令
以实现把源操作数复制到目的地址的操作,如果要保留目的地址中操作数(目的操作数),可以使用数据交换指令
1、内部数据传送指令:实现内部寄存器、RAM、特殊功能寄存器之间的数据传送,用MOV
A、以A为目的操作数的8位传送指令
MOVA,#data
MOVA,direct
MOVA,Rn
MOVA,@Ri
B、以direct为目的操作数的8位传送指令
MOVdirect,A
MOVdirect, #data
MOVdirect1 direct2
MOVdirect,Rn
MOVdirect,Ri
C、以Rn为目的操作数的8位传送指令,不能从一个寄存器传到另一个寄存器
MOVRn,A
MOVRn, #data
MOVRn, direct
D、以@Ri的操作数的8位传送指令
MOV@RiA
MOV@Ri,#data
MOV@Ri,direct
E、16位数据传送指令作用把16位立即数装入数据指针DPTR,高8位(指令的第二
个字节)送入DPTR的高8位PDH,低8位送入DPTR的低8位PDL,
MOVDPTR,#data16
2、外部数据传送指令:在CPU与外部数据存储器或外部I/O口之间传送数据,每次传送一个字节,该操作只能使用累加器A来实现,
A、将外部数据送到累加器
MOVXA,@Ri
MOVXA,@DPTR
B、将累加器内容送入外部
MOVX@Ri,A
MOVX@DPTR,A
C、查表指令用于读取程序存储器的内容,或者在程序存储器中存储的固定表格中查找
一项
MOVCA,@A+DPTR
MOVCA,@A+PC
D、堆栈操作指令:当通过子程序调用、返回等指令使程序的执行流程发生改变时,通
常使用堆栈保存返回地址
PUSHdirect
POPdirect
F、数据交换指令用以完成累加器与工作寄存器、内部RAM单元、特殊功能寄存器内容全部或部分互换
字节交换:将累加器A内容与源操作数互换
XCHA,direct
XCHA,Rn
XCHA,@Ri
半字节交换将累加器A的低4位与由Ri内容指定的内部RAM单元的低4位互换,高4位不变
XCHDA,@Ri
练习:假设在内部RAM地址20H处存放着一个BCD数25,编写程序将它转换ASCII码表示,存储在内部RAM地址30H开始的两个单元中
BCD数25H其实表示十进制数25,用ASCII表示时,应转换成字符“2”、“5”的ASCII值32H和35H
MOVR0,#20H;R0内容为25H存放位置
MOVR1#30H;R1内容为转换后ASCII码存放位置
MOV@R1,#30H;ASCII存放外,先初始化为30H
MOVA,@R0;A为25H
XCHDA,@R1;A与30H互换低4位内容,A为20H,30H内容为35H
SWAPA;A高低4位互换,为02H
INCR1;R1为31H
MOV@R1,#30H;初始化为30H
XHCDA,@R1;A与31H互换低4位内容,A为00H,30H内容为32H
问题1、指令的范围,
2、操作数和地址的区分
算术运算类指令分析
算术运算指令共有24条,算术运算主要是执行加、减、乘、除法四则运算。另外MCS-51指令系统中有相当一部分是进行加、减1操作,BCD码的运算和调整,我们都归类为运算指令。虽然MCS-51单片机的算术逻辑单元ALU仅能对8位无符号整数进行运算,但利用进位标志C,则可进行多字节无符号整数的运算。同时利用溢出标志,还可以对带符号数进行补码运算。需要指出的是,除加、减1指令外,这类指令大多数都会对PSW(程序状态字)有影响。这在使用中应特别注意。
[1].加法指令(4条)
这4条指令的作用是把立即数,直接地址、工作寄存器及间接地址内容与累加器A的内容相加,运算结果存在A中。
ADD A,#data;(A)+#data→(A) 累加器A中的内容与立即数#data相加,结果存在A中
ADD A,data;(A)+(data)→(A) 累加器A中的内容与直接地址单元中的内容相加,结果存在A中
ADD A,Rn;(A)+(Rn)→(A) 累加器A中的内容与工作寄存器Rn中的内容相加,结果存在A中
ADD A,@Ri;(A)+((Ri))→(A) 累加器A中的内容与工作寄存器Ri所指向地址单元中的内容相加,结果存在A中
这些指令所用到的源操作数都是累加器ACC,目的操作数则根据自已的需要来选择。
上述这四条指令的用途是:将A中的值与后面的值相加,最终结果存回到累加器A中。
例:MOV A,#30H
ADD A,#10H
则执行完本条指令后,A中的值就是40H
下面的题目请大家自行练习
MOV 34H,#10H
MOV R0,#13H
MOV A,34H
ADD A,R0
MOV R1,#34H
ADD A,@R1
练习题说明:
MOV 34H,#10H
这条指令的目的是将立即数10H送入34H这个存储单元
MOV R0,#13H
这条指令的目的是将立即数13H送入R0这个寄存器
MOV A,34H
这条指令大家要特别注意了,这条指令的源操作数在哪里呢?它的源操作数是在34H这个存储单元里,也就是34H是个存储单元,而不是一个数
这条指令用的是直接寻址,大前看前面的指令,第一条指令将10H这个立即数送入了34H这个存储单元。那么,也就是34H中存储着10H这么一个常数。
执行MOV A,34H单元后,累加器A中的值是多少呢?前面说了34H存储单元中的值是10H,所以这时累加器的值就是10H。
ADD A,R0
这条指令其实就是把前面三条指令的数据求个总和。第二条指令MOV R0,#13H执行完后。R0寄存器里的值是13H。第三条指令MOV A,34H执行完后,累加器的值是10H。
这条指令的意思就是把R0寄存器中的值(13H)与累加器A中的值(10H)相加,其结果是(23H)送入累加器A。
MOV R1,#34H
这条指令是将常数34H送入寄存器R1,执行完这条指令后,R1寄存器中的值是34H
ADD A,@R1
这个时候求和,大家请注意了。这条指令是寄存器间接寻址方式。前面我们已知道,累加器中的值是23H,MOV R1,#34H执行完后,R1寄存器的值是34H。大家注意,在间接寻址方式MOV A,@Ri(Ri为R0或R1,在这条指令中用的是R1)中。R1内的值指的就不是一个常数了,而是一个直接地址。这条指令的意思就是把寄存器R1中存储的34H存储单元的内容(10H)与累加器中的内容(23H)相加,其结果为33H。
根据前面我们用的MedWin仿真软件大家进行模拟仿真,同时打开DATA窗口及寄存器窗口观察程序执行时内部寄存器及数据区的变化情况。软件使用如有不凝问,请到我们论坛提出。我们会尽力为大家解答。
[2].带进位加法指令(4条)
这4条指令除与[1]功能相同外,在进行加法运算时还需考虑进位问题。
ADDC A,data;(A)+(data)+(C)→(A) 累加器A中的内容与直接地址单元的内容连同进位位相加,结果存在A中
ADDC A,#data;(A)+#data +(C)→(A) 累加器A中的内容与立即数连同进位位相加,结果存在A中
ADDC A,Rn;(A)+Rn+(C)→(A) 累加器A中的内容与工作寄存器Rn中的内容、连同进位位相加,结果存在A中
ADDC A,@Ri;(A)+((Ri))+(C)→(A) 累加器A中的内容与工作寄存器Ri指向地址单元中的内容、连同进位位相加,结果存在A中
用途:将A中的值和其后面的值相加,并且加上进位位C中的值。
说明:由于51单片机是一种8位机,所以只能做8位的数学运算,但8位的运算范围只有0-255,这在实际工作中是不够的,因此就要进行扩展,一般是将2个8位的数学运算合起来,成为一个16位的运算,这样,可以表达的数的范围就可以到达0-65535。如何合并呢?其实很简单,让我们看一个十进制数的例子吧:
66+78
这两个数相加,我们根本不在意这个过程,但事实上我们是这样做的:先做6+8(低位),然后再做6+7,这是高位。做了两次加法,只是我们做的时候并没有刻意分成两次加法来做罢了,或者说我们并没有意识到我们做了两次加法。之所以要分成两次来做,是因为这两个数超过了一位数所能表达的范围(0-9)。
在做低位时产生了进位,我们做的时候是在适当的位置点一下,然后在做高位加法时将这一点加进去。那么计算机中做16位加法时同样如此,先做低8位的,如果两数相加后产生了进位,也要“点一下”做个标记,这个标记就职进位位C,在程序状态字PSW中。在进行高位加法是将这个C加进去。
例如:1067H+10A0H,先做67H+A0H=107H,而107H显然超过了0FFH,因此,最终保存在A中的数是7,而1则到了PSW中的CY位了,换言之,CY就相当于100H。然后再做10H+10H+CY,结果是21H,所以最终的结果是2107H。
[3].带借位减法指令(4条)
这组指令包含立即数、直接地址、间接地址及工作寄存器与累加器A连同借位位C内容相减,结果送回累加器A中。
这里我们对借位位C的状态作出说明,在进行减法运算中,CY=1表示有借位,CY=0则无借位。OV=1声明带符号数相减时,从一个正数减去一个负数结果为负数,或者从一个负数中减去一个正数结果为正数的错误情况。在进行减法运算前,如果不知道借位标志位C的状态,则应先对CY进行清零操作。
SUBB A,data;(A)-(data) - (C)→(A) 累加器A中的内容与直接地址单元中的内容、连同借位位相减,结果存在A中
SUBB A,#data;(A)-#data -(C)→(A) 累加器A中的内容与立即数、连同借位位相减,结果存在A中
SUBB A,Rn;(A)-(Rn) -(C)→(A) 累加器A中的内容与工作寄存器中的内容、连同借位位相减,结果存在A中
SUBB A,@Ri;(A)-((Ri)) -(C)→(A) 累加器A中的内容与工作寄存器Ri指向的地址单元中的内容、连同借位位相减,结果存在A中
[4].乘法指令(1条)
这个指令的作用是把累加器A和寄存器B中的8位无符号数相乘,所得到的是16位乘积,这个结果低8位存在累加器A,而高8位存在寄存器B中。如果OV=1,说明乘积大于0FFFFH(65536),否则OV=0,但进位标志位CY总是等于0。
MUL AB;(A)×(B)→(A)和(B) 累加器A中的内容与寄存器B中的内容相乘,结果存在A、B中
例:(A)=4EH,(B)=5DH,执行指令
MUL AB后,乘积是1C56H,所以在B中放的是1CH,而A中放的则是56H。
[5].除法指令(1条)
这个指令的作用是把累加器A的8位无符号整数除以寄存器B中的8位无符号整数,所得到的商存在累加器A,而余数存在寄存器B中。除法运算总是使OV和进位标志位CY等于0。如果OV=1,表明寄存器B中的内容为00H,那么执行结果为不确定值,表示除法有溢出。
DIV AB;(A)÷(B)→(A)和(B) 累加器A中的内容除以寄存器B中的内容,所得到的商存在累加器A,而余数存在寄存器B中。
例如:13/5,其商是2,余数是3。除了以后,商会放在A中,余数放在B中,CU和OV都是0。如果在做除法前B中的值是00H,也就是除数为0,那么OV=1。
[6].加1指令(5条)
这5条指令的的功能均为原寄存器的内容加1,结果送回原寄存器。上述提到,加1指令不会对任何标志有影响,如果原寄存器的内容为FFH,执行加1后,结果就会是00H。这组指令共有直接、寄存器、寄存器减间址等寻址方式:
INC A;(A)+1→(A) 累加器A中的内容加1,结果存在A中
INC data;(data)+1→(data) 直接地址单元中的内容加1,结果送回原地址单元中
INC @Ri;((Ri))+1→((Ri)) 寄存器的内容指向的地址单元中的内容加1,结果送回原地址单元中
INC Rn;(Rn)+1→(Rn)寄存器Rn的内容加1,结果送回原地址单元中
INC DPTR;(DPTR)+1→(DPTR)数据指针的内容加1,结果送回数据指针中
用途很简单,就是将后面目标中的值加1。
例:(A)=12H,(R0)=33H,(21H)=32H,(34H)=22H,DPTR=1234H。执行下面的指令;
INC A ;(A)=13H
INC R0 ;(R0)=34H
INC 21H ;(21H)=33H
INC @R0 ;(34H)=23H
INC DPTR;(DPTR)=1235H
这些指令执行后的结果都附在了指令的后面。
说明:从结果上看,INC A和ADD A,#1差不多,但INC A是单字节,单周期指令,而ADD A,#1则是双字节双周期指令,而且INC A不会影响PSW位,如(A)=0FFH,INC A后(A)=00H,而CY依然保持不变。如果是ADD A,#1,则(A)=00H,而CY一定是1。因此加1指令并不适合做加法运算,事实上它主要是用来做计数、地址增加等用途。另外,加法类指令都是以A为核心的,其中一个数必须放在A中,而运算结果也必须放在A中,而加1类指令的对象则广泛得多,可以是寄存器、内存地址、间址寻址的地址等等。
在INC data这条指令中,如果直接地址是I/O,其功能是先读入I/O锁存器的内容,然后在CPU进行加1操作,再输出到I/O上,这就是“读—修改—写”操作。
[7].减1指令(4条)
这组指令的作用是把所指的寄存器内容减1,结果送回原寄存器,若原寄存器的内容为00H,减1后即为FFH,运算结果不影响任何标志位,这组指令共有直接、寄存器、寄存器间址等寻址方式,当直接地址是I/O口锁存器时,“读—修改—写”操作与加1指令类似。
DEC A;(A)-1→(A)累加器A中的内容减1,结果送回累加器A中
DEC data;(data)-1→(data)直接地址单元中的内容减1,结果送回直接地址单元中
DEC @Ri;((Ri))-1→((Ri))寄存器Ri指向的地址单元中的内容减1,结果送回原地址单元中
DEC Rn;(Rn)-1→(Rn)寄存器Rn中的内容减1,结果送回寄存器Rn中
[8].十进制调整指令(1条)
在进行BCD码运算时,这条指令总是跟在ADD或ADDC指令之后,其功能是将执行加法运算后存于累加器A中的结果进行调整和修正。
DA A
综合练习:
MOV A,#12H
MOV R0,#24H
MOV 21H,#56H
ADD A,#12H
MOV DPTR,#1234H
ADD A,DPH
ADD A,R0
CLR C
SUBB A,DPL
SUBB A,#25H
INC A
SETB C
ADDC A,21H
INC R0
SUBB A,R0
MOV 24H,#16H
CLR C
ADD A,@R0
先写出每步运行结果,然后将以上题目键入,并在软件仿真中运行,观察寄存器及有关单元的内容的变化。
逻辑运算及移位指令分析
逻辑运算和移位指令共有25条,有与、或、异或、求反、左右移位、清0等逻辑操作,有直接、寄存器和寄存器间址等寻址方式。这类指令一般不影响程序状态字(PSW)标志。
[1].循环移位指令(4条)
这4条指令的作用是将累加器中的内容循环左或右移一位,后两条指令是连同进位位CY一起移位。
RL A;累加器A中的内容左移一位
RR A;累加器A中的内容右移一位
RLC A ;累加器A中的内容连同进位位CY左移一位
RRC A ;累加器A中的内容连同进位位CY右移一位
[2].累加器半字节交换指令(1条)
这条指令是将累加器中的内容高低半字节互换,这在上一节中内容已有介绍。
SWAP A; 累加器中的内容高低半字节互换
[3].求反指令(1条)
这条指令将累加器中的内容按位取反。
CPL A; 累加器中的内容按位取反
[4].清零指令(1条)
这条指令将累加器中的内容清0。
CLR A; 0→(A),累加器中的内容清0
[5].逻辑与操作指令(6条)
这组指令的作用是将两个单元中的内容执行逻辑与操作。如果直接地址是I/O地址,则为“读—修改—写”操作。
ANL A,data;累加器A中的内容和直接地址单元中的内容执行与逻辑操作。结果存在寄存器A中。
ANL data,#data;直接地址单元中的内容和立即数执行与逻辑操作。结果存在直接地址单元中。
ANL A,#data;累加器A的内容和立即数执行与逻辑操作。结果存在累加器A中。
ANL A,Rn;累加器A的内容和寄存器Rn中的内容执行与逻辑操作。结果存在累加器A中。
ANL data,A;直接地址单元中的内容和累加器A的内容执行与逻辑操作。结果存在直接地址单元中。
ANL A,@Ri;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行与逻辑操作。结果存在累加器A中。
[6].逻辑或操作指令(6条)
这组指令的作用是将两个单元中的内容执行逻辑或操作。如果直接地址是I/O地址,则为“读—修改—写”操作。
ORL A,data;累加器A中的内容和直接地址单元中的内容执行逻辑或操作。结果存在寄存器A中。
ORL data,#data;直接地址单元中的内容和立即数执行逻辑或操作。结果存在直接地址单元中。
ORL A,#data;累加器A的内容和立即数执行逻辑或操作。结果存在累加器A中。
ORL A,Rn;累加器A的内容和寄存器Rn中的内容执行逻辑或操作。结果存在累加器A中。
ORL data,A;直接地址单元中的内容和累加器A的内容执行逻辑或操作。结果存在直接地址单元中。
ORL A,@Ri;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行逻辑或操作。结果存在累加器A中。
[7].逻辑异或操作指令(6条)
这组指令的作用是将两个单元中的内容执行逻辑异或操作。如果直接地址是I/O地址,则为“读—修改—写”操作。
XRL A,data;累加器A中的内容和直接地址单元中的内容执行逻辑异或操作。结果存在寄存器A中。
XRL data,#data;直接地址单元中的内容和立即数执行逻辑异或操作。结果存在直接地址单元中。
XRL A,#data;累加器A的内容和立即数执行逻辑异或操作。结果存在累加器A中。
XRL A,Rn;累加器A的内容和寄存器Rn中的内容执行逻辑异或操作。结果存在累加器A中。
XRL data,A;直接地址单元中的内容和累加器A的内容执行逻辑异或操作。结果存在直接地址单元中。
XRL A,@Ri;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行逻辑异或操作。结果存在累加器A中
控制转移类指令分析
控制转移指令用于控制程序的流向,所控制的范围即为程序存储器区间,MCS-51系列单片机的控制转移指令相对丰富,有可对64kB程序空间地址单元进行访问的长调用、长转移指令,也有可对2kB字节进行访问的绝对调用和绝对转移指令,还有在一页范围内短相对转移及其它无条件转移指令,这些指令的执行一般都不会对标志位有影响。
[1].无条件转移指令(4条)
这组指令执行完后,程序就会无条件转移到指令所指向的地址上去。长转移指令访问的程序存储器空间为16地址64kB,绝对转移指令访问的程序存储器空间为11位地址2kB空间。
LJMP addr16;addr16→(PC),给程序计数器赋予新值(16位地址)
AJMP addr11;(PC)+2→(PC),addr11→(PC10-0)程序计数器赋予新值(11位地址),(PC15-11)不改变
SJMP rel;(PC)+ 2 + rel→(PC)当前程序计数器先加上2再加上偏移量给程序计数器赋予新值
JMP @A+DPTR;(A)+ (DPTR)→(PC),累加器所指向地址单元的值加上数据指针的值给程序计数器赋予新值
这几条指令,如果要他细分析的话,区别较大,但初学者时,可以不理会那么多,统统理解成LJMP标号,也就是跳转到一个标号处,但事实上,JMP标号,在前面的例程中我们已接触过,并且也知道如何来使用了,AJMP和SJMP也是一样,那么这几条指令它们的区别何在呢?在于跳转的范围不一样。好比跳远,LJMP一下就能跳64K那么远(当然近了就更没关系了)。而AJMP最多只能跳2K距离,而SJMP则最多只能跳256这么远,原则上,所有用AJMP或SJMP的地方都可以用LJMP来替代。因此在初学者时,需要跳转时可以全用LJMP。
但是在查表时要注意会出错,因为他们的机器周期不一样,取得的数也不一样。
[2].条件转移指令(8条)
条件转移指令是指在满足一定条件时进行相对转移
JZ rel; A=0,(PC)+ 2 + rel→(PC),累加器中的内容为0,则转移到偏移量所指向的地址,否则程序往下执行
JNZ rel; A≠0,(PC)+ 2 + rel→(PC),累加器中的内容不为0,则转移到偏移量