(1)不带进位的加法指令。
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=9AH,R0=30H,(30H)=70H,执行指令ADD A,@R0,操作如下:
1 0 0 1 1 0 1 0
+ 0 1 1 1 0 0 0 0
1 0 0 0 0 1 0 1 0
结果为:A=0AH,C=1,AC=0,OV=0,P=0。
MCS-51单片机的运算是针对无符号数的运算。利用补码MCS-51单片机也可以进行有符号数的运算,利用PSW的OV位判断运算结果的正确性。用D6c和D7c分别代表运算过程中D6位、D7位发生的进位或借位,则OV为D6c与D7c相异或的结果。
OV=D6c?D7c
例如,设A=61H,R0=39H,执行ADD A,R0,操作如下:
0 1 1 0 0 0 0 1
+ 0 0 1 1 1 0 0 1
1 0 0 1 1 0 1 0
结果为:A=9AH,C=0,AC=0,OV=1,P=0。
从以上两例可看出,进位与溢出并无必然联系。进位不一定溢出,溢出也不一定进位。
在第二例中,若将A中的数与R0中的数据视作有符号数,则两数均为正数据,但相加结果却为负数,显然数据范围已溢出(大于127),OV=1则是本次运算溢出的标志。
(2)带进位的加法指令。
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
C来自PSW状态寄存器中的进位位CY。指令功能是把源地址所指示的操作数与累加器A和进位位CY相加,运算结果存放在A中,这些指令主要用于多字节加法运算中。
例如,设A=20H,R0=24H,C=1,执行指令ADDC A,R0后,A=45H。
(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指令的功能是把源操作数所规定的单元中的内容加1。前4条是8位数加1指令,最后一条是16位数加1指令。只有第一条指令对PSW的P位产生影响,其余指令不会对PSW的任何标志位产生影响(为什么?请读者自己思考)。
例如,(30H)=22H,A=FFH,DPTR=2000H。
执行以下程序后操作结果为:(30H)=23H,A=00H,DPTR=2001H。
INC A
INC 30H
INC DPTR
(4)十进制调整指令。
DA A ;把A中的二进制数调整为BCD码
MCS-51的ADD、ADDC是二进制的加法指令,能进行二进制和十六进制的加法运算。若要进行十进制数(BCD码)加法,只能借助于二进制的加法指令,因为MCS-51没有提供专门的BCD码加法运算指令,先用ADD、ADDC加法指令对BCD数实行加法运算,并在其后紧跟一条十进制调整指令就能完成两个BCD数相加。
例如,A=65BCD,B=78BCD,C=0,执行指令ADD A,B和DA A后,A=43 BCD,C=1。
说明:(1)DA指令只对加法进行正确的BCD码调整,且必须跟在ADD或
ADDC指令之后。
(2)以上两条指令完成了65BCD+78BCD=143 BCD的运算,百位上的“1”
存于C中。
(3)在执行DA A指令时,若两个BCD数相加的结果中,低4位大于9
或有半进位,则在低4位加06H修正;若高4位大于9或有进位,则
在高4位加06H进行修正。
上例中:
0 1 1 0 0 1 0 1 ←65BCD
+ 0 1 1 1 1 0 0 0 ←78BCD
1 1 0 1 1 1 0 1 ←个位、十位均出现非法BCD码
+ 0 1 1 0 0 1 1 0 ←执行DA A指令
0 0 1 0 0 0 0 1 1 ←得结果143 BCD
之所以有非法BCD码出现,是因为计算机只懂二进制(十六进制本质上仍是二进制),而BCD码本质上是十进制。当按十进制加法运算“逢十进一”时,计算机却不知道这是十进制,仍按二进制加法相加,故出现了大于9的非法BCD码,而没产生进位。需要产生进位而不产生进位,于是加6产生进位,至于为什么加6而不是别的数,请读者思考。
【例3-6】设A=34,B=53,求A+B=?
解:34的BCD码为0011 0100B,53的BCD码为0101 0011B。运算过程如下:
0 0 1 1 0 1 0 0
+ 0 1 0 1 0 0 1 1
1 0 0 0 0 1 1 1
结果为87,显然运算结果仍然为BCD码,并且运算过程没有产生进位,这一结果是正确的,不必修正。
若假设A=37,B=46,则这两个BCD码的运算过程为:
0 0 1 1 0 1 1 1
+ 0 1 0 0 0 1 1 0
0 1 1 1 1 1 0 1
结果为7DH,运算结果的低位大于9,已不是BCD码。这种情况下就需要进行修正,以得到正确的BCD码。
在单片机中,BCD码进行加法运算时,中间结果的修正是由ALU硬件中的十进制修正电路自动进行的,使用时只要在加法指令后紧跟一条“DA A”指令即可修正。但需注意的是:在MCS-51单片机中,“DA A”指令不能直接用在减法指令后面,即不能直接用来对BCD码的减法运算进行修正。
【例3-7】 设有两个4位BCD码,分别存放在内部数据存储器的50H、51H单元和60H、61H单元中,试编写求这两数之和的程序,结果存放到40H、41H单元中。
解:求两个BCD码之和的程序如下。
MOV A,50H ;A←(50H)
ADD A,60H ;低两位相加,A←(A)+(60H)
DA A ;进行BCD码修正
MOV 40H,A ;将修正后的低两位结果送40H
MOV A,51H ;A←(51H)
ADDC A,61H ;高两位带上低位的进位位相加,A←(A)+(61H)+CY
DA A ;进行BCD码修正
MOV 41H,A ;将修正后的高两位结果送41H
(1)带借位的减法指令。
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
减法指令的功能是把累加器A中的操作数减去源地址所指操作数和指令前的CY值,并将差值存放在累加器A中。减法只有带借位的减法指令,没有不带借位的减法指令,若在减法指令前加一条CLR C指令,即将CY先清零,则可间接实现不带借位的减法功能。其对标志位的影响规则与加法类似。
例如,设A=39H,R0=20H,(20H)=32H,C=1,执行指令SUBB A,@R0后,A=06H,C=0。
(2)减1指令。
DEC A ;A←A-1
DEC Rn ;IU←Rn-1
DEC Direct ;direct←(direct)-1
DEC @Ri ;(Ri) ←((Ri))-1
减1指令的功能是把源操作数所规定的RAM单元中的内容减1,与加1指令相比,除不含有对16位数的减1操作外,其余性质相同。
例如,R0=30H,(30H)=22H,执行DEC@R0后,(30H)=21H。
MUL AB ;BA←A×B
乘法指令的功能是把累加器A和通用寄存器B中两个8位无符号数相乘,指令执行后,16位乘积的高8位存于B中,低8位存于A中。本指令对PSW中的CY、OV和P这3个标志位产生影响。如乘积大于FFH,即B中内容不为0时,则OV=1,否则为0;进位标志位总被清零;P位仍由A中“1”的个数的奇偶性确定。
例如,A=25H,B=30H,执行MUL AB后,A=0F0H,B=06H。标志位C=0,OV=1,P=0。
DIV AB ;A÷B→商在A中,余数在B中
除法指令的功能是用累加器A的一个8位无符号数除以B中的8位无符号数,即A为被除数,B为除数。指令执行后,A中存放商,B中存入余数。将进位标志位CY和OV清零;P位由A中“1”的个数的奇偶性确定。若B=00H,则指令执行后OV=l,A与B不变。
例如,A=30H,B=07H,执行DIV AB后,A=06H,B=06H。标志位C=0,OV=0,P=0。
【例3-8】设A=56H,B=78H,执行如下指令。
MUL AB
结果为:A=50H,B=28H,OV=1。
【例3-9】设A=0ABH,B=12H,执行以下指令。
DIV AB
结果为:A=09H,B=09H,OV=0。
算术操作类指令见表3-4。本类指令除MUL、DIV和INC DPTR外,其余各条的执行时间都只有一个机器周期。除包含立即寻址和直接寻址的指令外,其余指令都是单字节指令。
表3-4 算术运算类指令一览表
助 记 符 |
功能说明 |
字 节 数 |
振荡器周期 |
ADD A,Rn |
寄存器内容加到累加器 |
1 |
12 |
ADD A,direct |
直接寻址字节内容加到累加器 |
2 |
12 |
ADD A,@Ri |
间接寻址RAM内容加到累加器 |
1 |
12 |
ADD A,#data |
立即数加到累加器 |
2 |
12 |
ADDC A,Rn |
寄存器加到累加器(带进位) |
1 |
12 |
ADDC A,direct |
直接寻址字节加到累加器(带进位) |
2 |
12 |
ADDC A,@Ri |
间接寻址RAM加到累加器(带进位) |
1 |
12 |
ADDC A,#data |
立即数加到累加器(带进位) |
2 |
12 |
SUBB A,Rn |
累加器内容减去寄存器内容(带借位) |
1 |
12 |
SUBB A,direct |
累加器内容减去直接寻址字节(带借位) |
2 |
12 |
SUBB A,@Ri |
累加器内容减去间接寻址RAM(带借位) |
1 |
12 |
SUBB A,#data |
累加器减去立即数(带借位) |
2 |
12 |
DA A |
累加器十进制调整 |
1 |
12 |
INC A |
累加器加1 |
1 |
12 |
1NC Rn |
寄存器加1 |
1 |
12 |
INC direct |
直接寻址字节加1 |
2 |
12 |
INC@Ri |
间接寻址RAM加1 |
1 |
12 |
INC DPTR |
数据指针寄存器加1 |
1 |
24 |
DEC A |
累加器减l |
1 |
12 |
DEC Rn |
寄存器减l |
1 |
12 |
DEC direct |
直接寻址字节减1 |
2 |
12 |
DEC@Ri |
间接寻址RAM减1 |
1 |
12 |
MUL AB |
累加器A和寄存器B相乘 |
1 |
48 |
DIV AB |
累加器A除以寄存器B |
1 |
48 |