这有什么意义呢?ACC本来中值是100,B值原本是20,是的,在这种情况下,确实没有意义,但在实际工作中,在PUSH B其他指令往往需要执行,这些指令会在A中执行值,B因此,如果我们想在程序结束时删除A和B这些指令在恢复原值时很有意义。
另一个问题是,如果我不需要堆栈,比如PUSH ACC指令处用MOV 60H,A,在PUSH B处用指令MOV 61H,B,然后用MOV A,60H,MOV B,61H来替代两条POP指令不一样吗?是的,结果是一样的,但过程是不同的,PUSH和POP指令是单字节,单周期指令, MOV指令是双字节,双周期指令。更重要的是,堆栈的作用不止于此,所以一般的计算机都有堆栈。当我们编写子程序并需要保存数据时,我们通常不使用以下方法,而是使用堆栈方法。
例:写下下列程序的操作结果
MOV 30H,#12
MOV 31H,#23
PUSH 30H
PUSH 31H
POP 30H
POP 31H
结果是30H中值为23,而31H中间值变为12。两者之间的数据交换。从这个例子可以看出,在使用堆栈时,进出堆栈的书写顺序必须相反,以确保数据被送回原位,否则就会出错。
算术操作指令
1.没有进位的加法指令
ADD A,#DATA ;例:ADD A,#10H
ADD A,direct ;例:ADD A,10H
ADD A,Rn ;例:ADD A,R7
ADD A,@Ri ;例:ADD A,@R0
用途:将A中的值与后面的值相加,最终结果是否回到A中。
例:
MOV A,#30H
ADD A,#10H
执行本条指令后,A中的值为40H。
2.带入位的加法指令
ADDC A,Rn
ADDC A,direct
ADDC A,@Ri
ADDC A,#data
用途:将A中的值与后面的值相加,并加入进位C中的值。
说明:由于51单片机是一种8位机,只能做8位数学操作,但8位数学操作的范围只有0-255,这在实际工作中是不够的。因此,有必要扩展它。一般来说,它将两个8位数学操作结合起来,成为一个16位数学操作。这样,可达的数字范围可以达到0-65535。如何合并?其实很简单。让我们看看一个 10进制数例:
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.带借位的减法指令
SUBB A,Rn
SUBB A,direct
SUBB A,@Ri
SUBB A,#data
设(每个H,(R2)=55H,CY=1,执行指令SUBB A,R2之后,A中的值为73H。
说明:没有没有借位的减法指令。如果需要做没有借位的减法指令(第一次相减),只需要CY清零即可。
4.乘法指令
MUL AB
该指令的功能是将A和B两个8位无符号数相乘,两位数相乘结果一般较大,最终结果以1个16位数表示,其中高8位在B中,低8位在A中。乘积大于FFFFFH(65535)时,0V置1(溢出),否则OV为0,而CY总是0。
例:(A)=4EH,(B)=5DH,执行指令
MUL AB后,乘积是1C56H,所以在B中放1CH,A中放56H。
5.除法指令
DIV AB
该指令的功能是将A中的8位无符号除以B中的8位无符号(A/B)。小数通常出现在除法中,但小数在计算机中不能直接表达。它使用的是我们小学生在小数时没有接触到商业和余数的概念,如13 /5,商为2,余数为3。除此之外,商放在A中,余数放在B中。CY和OV都是0。如果在做除法前B中的值是00H,也就是说,除数为0,0V=1。
6.加1指令
INC A
INC Rn
INC direct
INC @Ri
INC DPTR
用途很简单,就是将后面目标中的值加1。例:(A)=12H,(R0)=33H,(21H)=32H,(34H)=22H,DPTR=1234H。执行以下指令:
INC A (A)=13H
INC R2 (R0)=34H
INC 21H (21H)=33H
INC @R0 (34H)=23H
INC DPTR 9; ( DPTR)=1235H
结果如上所示。
说明:从结果上看INC A和ADD A,#1差不多,但是INC A单字节,单周期指令,ADD #1是双字节、双周期指令和INC A不会影响PSW位,如(A)=0FFH,INC A后(A)=00H,而CY保持不变。如果是ADD A ,#1,则(A)=00H,而CY一定是1。所以加1指令不适合加法,其实主要用于计数、地址增加等。此外,以A为核心的加法指令之一必须放在A中,计算结果也必须放在A中,而加法指令的对象要广泛得多,可以是寄存器、内存地址、地址等。
7.减1指令
DEC A
DEC RN
DEC direct
DEC @Ri
类似于加1指令,就不多说了。
逻辑操作指令:
1.累加器A的逻辑操作:
CLR A ;将A中的值清0、单周期单字节指令和MOV A,#00H效果相同。
CPL A ;按位取反A中的值
RL A ;左移A中的值逻辑
RLC A ;逻辑左移A中的值加上进位位
RR A ;逻辑右移A中的值
RRC A ;将A中的值加上进位位进行逻辑右移
SWAP A ;交换A中的高低值。
例:(A)=73H,则执行CPL A,这样进行:
73H二进制为0110011,
逐位取反即为 10001100,也就是8CH。
RL A是将(A)第7位送到第0位,第0位送到1位,依次类推。
例:A中的值为68H,执行RL A。68H按上图移动,将二进制变成01101000。01101000化为11010000,即D0H。
RLC A,是将(A)中值带上进位(C)进行移位。
例:A中的值为68H,C如果中值为1,则执行RLC A
1 01101000后,结果是0 11010001,即C进位值变为0,(A)则变成了D1H。
RR A和RRC A我就不多说了。请参考以上两个例子自己练习。
SWAP A,交换A中的高低值。
例:(A)=39H,则执行SWAP A之后,A中的值就是93H。前后交换怎么会这样?因为这是16进制数,每16进位数代表4个二进位。如果是这样的话,请注意:(A)=39,后面没H,执行SWAP A之后,不是(A)=93。将其转化为二进制:39转化为二进制为10111,即001,0111高4位为0001,低4位为0111,交换后为0111001,即711H,即113。
2.逻辑和指令
ANL A,Rn ;A与Rn中值按位和,结果送到A中
ANL A,direct ;A与direct中值按位和,结果送到A中
ANL A,@Ri ;A与地址寻址单元@Ri中值按位和,结果送到A中
ANL A,#data ;A与立即数data按位和,结果送到A中
ANL direct,A ;direct中值与A值按位,结果送入direct中
ANL direct,#data ;direct中值和立即数data按位与,结果送入direct中。
这些指令的关键是知道什么是逻辑和逻辑。这里的逻辑是指按位和
例:71H和56H相和将两数写成二进制形式:
(71H) 01110001
(56H) 00100110
结果 00100000 即20H,从上面的公式可以看出,只要两个参与计算的值中有一个是0,结果就是0,两个是1,结果就是1。