第二十四課:算術(shù)運(yùn)算類指令分析
算術(shù)運(yùn)算指令共有24條,算術(shù)運(yùn)算主要是執(zhí)行加、減、乘、除法四則運(yùn)算。另外MCS-51指令系統(tǒng)中有相當(dāng)一部分是進(jìn)行加、減1操作,BCD碼的運(yùn)算和調(diào)整,我們都?xì)w類為運(yùn)算指令。雖然MCS-51單片機(jī)的算術(shù)邏輯單元ALU僅能對(duì)8位無(wú)符號(hào)整數(shù)進(jìn)行運(yùn)算,但利用進(jìn)位標(biāo)志C,則可進(jìn)行多字節(jié)無(wú)符號(hào)整數(shù)的運(yùn)算。同時(shí)利用溢出標(biāo)志,還可以對(duì)帶符號(hào)數(shù)進(jìn)行補(bǔ)碼運(yùn)算。需要指出的是,除加、減1指令外,這類指令大多數(shù)都會(huì)對(duì)PSW(程序狀態(tài)字)有影響。這在使用中應(yīng)特別注意。
[1]. 加法指令(4條)
這4條指令的作用是把立即數(shù),直接地址、工作寄存器及間接地址內(nèi)容與累加器A的內(nèi)容相加,運(yùn)算結(jié)果存在A中。
ADD A,#data ;(A)+#data→(A) 累加器A中的內(nèi)容與立即數(shù)#data相加,結(jié)果存在A中
ADD A,data ;(A)+(data)→(A) 累加器A中的內(nèi)容與直接地址單元中的內(nèi)容相加,結(jié)果存在A中
ADD A,Rn ;(A)+(Rn)→(A) 累加器A中的內(nèi)容與工作寄存器Rn中的內(nèi)容相加,結(jié)果存在A中
ADD A,@Ri ;(A)+((Ri))→(A) 累加器A中的內(nèi)容與工作寄存器Ri所指向地址單元中的內(nèi)容相加,結(jié)果存在A中
這些指令所用到的源操作數(shù)都是累加器ACC,目的操作數(shù)則根據(jù)自已的需要來(lái)選擇。
上述這四條指令的用途是:將A中的值與后面的值相加,最終結(jié)果存回到累加器A中。
例:MOV A,#30H
ADD A,#10H
則執(zhí)行完本條指令后,A中的值就是40H
下面的題目請(qǐng)大家自行練習(xí)
MOV 34H,#10H
MOV R0,#13H
MOV A,34H
ADD A,R0
MOV R1,#34H
ADD A,@R1
練習(xí)題說(shuō)明:
MOV 34H,#10H
這條指令的目的是將立即數(shù)10H送入34H這個(gè)存儲(chǔ)單元
MOV R0,#13H
這條指令的目的是將立即數(shù)13H送入R0這個(gè)寄存器
MOV A,34H
這條指令大家要特別注意了,這條指令的源操作數(shù)在哪里呢?它的源操作數(shù)是在34H這個(gè)存儲(chǔ)單元里,也就是34H是個(gè)存儲(chǔ)單元,而不是一個(gè)數(shù)
這條指令用的是直接尋址,大前看前面的指令,第一條指令將10H這個(gè)立即數(shù)送入了34H這個(gè)存儲(chǔ)單元。那么,也就是34H中存儲(chǔ)著10H這么一個(gè)常數(shù)。
執(zhí)行MOV A,34H單元后,累加器A中的值是多少呢?前面說(shuō)了34H存儲(chǔ)單元中的值是10H,所以這時(shí)累加器的值就是10H。
ADD A,R0
這條指令其實(shí)就是把前面三條指令的數(shù)據(jù)求個(gè)總和。第二條指令MOV R0,#13H執(zhí)行完后。R0寄存器里的值是13H。第三條指令MOV A,34H執(zhí)行完后,累加器的值是10H。
這條指令的意思就是把R0寄存器中的值(13H)與累加器A中的值(10H)相加,其結(jié)果是(23H)送入累加器A。
MOV R1,#34H
這條指令是將常數(shù)34H送入寄存器R1,執(zhí)行完這條指令后,R1寄存器中的值是34H
ADD A,@R1
這個(gè)時(shí)候求和,大家請(qǐng)注意了。這條指令是寄存器間接尋址方式。前面我們已知道,累加器中的值是23H,MOV R1,#34H執(zhí)行完后,R1寄存器的值是34H。大家注意,在間接尋址方式MOV A,@Ri(Ri為R0或R1,在這條指令中用的是R1)中。R1內(nèi)的值指的就不是一個(gè)常數(shù)了,而是一個(gè)直接地址。這條指令的意思就是把寄存器R1中存儲(chǔ)的34H存儲(chǔ)單元的內(nèi)容(10H)與累加器中的內(nèi)容(23H)相加,其結(jié)果為33H。
根據(jù)前面我們用的MedWin仿真軟件大家進(jìn)行模擬仿真,同時(shí)打開DATA窗口及寄存器窗口觀察程序執(zhí)行時(shí)內(nèi)部寄存器及數(shù)據(jù)區(qū)的變化情況。軟件使用如有不凝問(wèn),請(qǐng)到我們論壇提出。我們會(huì)盡力為大家解答。
[2]. 帶進(jìn)位加法指令(4條)
這4條指令除與[1]功能相同外,在進(jìn)行加法運(yùn)算時(shí)還需考慮進(jìn)位問(wèn)題。
ADDC A,data ;(A)+(data)+(C)→(A) 累加器A中的內(nèi)容與直接地址單元的內(nèi)容連同進(jìn)位位相加,結(jié)果存在A中
ADDC A,#data ;(A)+#data +(C)→(A) 累加器A中的內(nèi)容與立即數(shù)連同進(jìn)位位相加,結(jié)果存在A中
ADDC A,Rn ;(A)+Rn+(C)→(A) 累加器A中的內(nèi)容與工作寄存器Rn中的內(nèi)容、連同進(jìn)位位相加,結(jié)果存在A中
ADDC A,@Ri ;(A)+((Ri))+(C)→(A) 累加器A中的內(nèi)容與工作寄存器Ri指向地址單元中的內(nèi)容、連同進(jìn)位位相加,結(jié)果存在A中
用途:將A中的值和其后面的值相加,并且加上進(jìn)位位C中的值。
說(shuō)明:由于51單片機(jī)是一種8位機(jī),所以只能做8位的數(shù)學(xué)運(yùn)算,但8位的運(yùn)算范圍只有0-255,這在實(shí)際工作中是不夠的,因此就要進(jìn)行擴(kuò)展,一般是將2個(gè)8位的數(shù)學(xué)運(yùn)算合起來(lái),成為一個(gè)16位的運(yùn)算,這樣,可以表達(dá)的數(shù)的范圍就可以到達(dá)0-65535。如何合并呢?其實(shí)很簡(jiǎn)單,讓我們看一個(gè)十進(jìn)制數(shù)的例子吧:
66+78
這兩個(gè)數(shù)相加,我們根本不在意這個(gè)過(guò)程,但事實(shí)上我們是這樣做的:先做6+8(低位),然后再做6+7,這是高位。做了兩次加法,只是我們做的時(shí)候并沒(méi)有刻意分成兩次加法來(lái)做罷了,或者說(shuō)我們并沒(méi)有意識(shí)到我們做了兩次加法。之所以要分成兩次來(lái)做,是因?yàn)檫@兩個(gè)數(shù)超過(guò)了一位數(shù)所能表達(dá)的范圍(0-9)。
在做低位時(shí)產(chǎn)生了進(jìn)位,我們做的時(shí)候是在適當(dāng)?shù)奈恢命c(diǎn)一下,然后在做高位加法時(shí)將這一點(diǎn)加進(jìn)去。那么計(jì)算機(jī)中做16位加法時(shí)同樣如此,先做低8位的,如果兩數(shù)相加后產(chǎn)生了進(jìn)位,也要“點(diǎn)一下”做個(gè)標(biāo)記,這個(gè)標(biāo)記就職進(jìn)位位C,在程序狀態(tài)字PSW中。在進(jìn)行高位加法是將這個(gè)C加進(jìn)去。
例如:1067H+10A0H,先做67H+A0H=107H,而107H顯然超過(guò)了0FFH,因此,最終保存在A中的數(shù)是7,而1則到了PSW中的CY位了,換言之,CY就相當(dāng)于100H。然后再做10H+10H+CY,結(jié)果是21H,所以最終的結(jié)果是2107H。
[3]. 帶借位減法指令(4條)
這組指令包含立即數(shù)、直接地址、間接地址及工作寄存器與累加器A連同借位位C內(nèi)容相減,結(jié)果送回累加器A中。
這里我們對(duì)借位位C的狀態(tài)作出說(shuō)明,在進(jìn)行減法運(yùn)算中,CY=1表示有借位,CY=0則無(wú)借位。OV=1聲明帶符號(hào)數(shù)相減時(shí),從一個(gè)正數(shù)減去一個(gè)負(fù)數(shù)結(jié)果為負(fù)數(shù),或者從一個(gè)負(fù)數(shù)中減去一個(gè)正數(shù)結(jié)果為正數(shù)的錯(cuò)誤情況。在進(jìn)行減法運(yùn)算前,如果不知道借位標(biāo)志位C的狀態(tài),則應(yīng)先對(duì)CY進(jìn)行清零操作。
SUBB A,data ;(A)-(data) - (C)→(A) 累加器A中的內(nèi)容與直接地址單元中的內(nèi)容、連同借位位相減,結(jié)果存在A中
SUBB A,#data ;(A)-#data -(C)→(A) 累加器A中的內(nèi)容與立即數(shù)、連同借位位相減,結(jié)果存在A中
SUBB A,Rn ;(A)-(Rn) -(C)→(A) 累加器A中的內(nèi)容與工作寄存器中的內(nèi)容、連同借位位相減,結(jié)果存在A中
SUBB A,@Ri ;(A)-((Ri)) -(C)→(A) 累加器A中的內(nèi)容與工作寄存器Ri指向的地址單元中的內(nèi)容、連同借位位相減,結(jié)果存在A中
[4]. 乘法指令(1條)
這個(gè)指令的作用是把累加器A和寄存器B中的8位無(wú)符號(hào)數(shù)相乘,所得到的是16位乘積,這個(gè)結(jié)果低8位存在累加器A,而高8位存在寄存器B中。如果OV=1,說(shuō)明乘積大于0FFFFH(65536),否則OV=0,但進(jìn)位標(biāo)志位CY總是等于0。
MUL AB ;(A)×(B)→(A)和(B) 累加器A中的內(nèi)容與寄存器B中的內(nèi)容相乘,結(jié)果存在A、B中
例:(A)=4EH,(B)=5DH,執(zhí)行指令
MUL AB后,乘積是1C56H,所以在B中放的是1CH,而A中放的則是56H。
[5]. 除法指令(1條)
這個(gè)指令的作用是把累加器A的8位無(wú)符號(hào)整數(shù)除以寄存器B中的8位無(wú)符號(hào)整數(shù),所得到的商存在累加器A,而余數(shù)存在寄存器B中。除法運(yùn)算總是使OV和進(jìn)位標(biāo)志位CY等于0。如果OV=1,表明寄存器B中的內(nèi)容為00H,那么執(zhí)行結(jié)果為不確定值,表示除法有溢出。
DIV AB ;(A)÷(B)→(A)和(B) 累加器A中的內(nèi)容除以寄存器B中的內(nèi)容,所得到的商存在累加器A,而余數(shù)存在寄存器B中。
例如:13/5,其商是2,余數(shù)是3。除了以后,商會(huì)放在A中,余數(shù)放在B中,CU和OV都是0。如果在做除法前B中的值是00H,也就是除數(shù)為0,那么OV=1。
[6]. 加1指令(5條)
這5條指令的的功能均為原寄存器的內(nèi)容加1,結(jié)果送回原寄存器。上述提到,加1指令不會(huì)對(duì)任何標(biāo)志有影響,如果原寄存器的內(nèi)容為FFH,執(zhí)行加1后,結(jié)果就會(huì)是00H。這組指令共有直接、寄存器、寄存器減間址等尋址方式:
INC A ;(A)+1→(A) 累加器A中的內(nèi)容加1,結(jié)果存在A中
INC data ;(data)+1→(data) 直接地址單元中的內(nèi)容加1,結(jié)果送回原地址單元中
INC @Ri ;((Ri))+1→((Ri)) 寄存器的內(nèi)容指向的地址單元中的內(nèi)容加1,結(jié)果送回原地址單元中
INC Rn ;(Rn)+1→(Rn)寄存器Rn的內(nèi)容加1,結(jié)果送回原地址單元中
INC DPTR ;(DPTR)+1→(DPTR)數(shù)據(jù)指針的內(nèi)容加1,結(jié)果送回?cái)?shù)據(jù)指針中
用途很簡(jiǎn)單,就是將后面目標(biāo)中的值加1。
例:(A)=12H,(R0)=33H,(21H)=32H,(34H)=22H,DPTR=1234H。執(zhí)行下面的指令;
INC A ;(A)=13H
INC R0 ;(R0)=34H
INC 21H ;(21H)=33H
INC @R0 ;(34H)=23H
INC DPTR;(DPTR)=1235H
這些指令執(zhí)行后的結(jié)果都附在了指令的后面。
說(shuō)明:從結(jié)果上看,INC A和ADD A,#1差不多,但I(xiàn)NC A是單字節(jié),單周期指令,而ADD A,#1則是雙字節(jié)雙周期指令,而且INC A不會(huì)影響PSW位,如(A)=0FFH,INC A后(A)=00H,而CY依然保持不變。如果是ADD A,#1,則(A)=00H,而CY一定是1。因此加1指令并不適合做加法運(yùn)算,事實(shí)上它主要是用來(lái)做計(jì)數(shù)、地址增加等用途。另外,加法類指令都是以A為核心的,其中一個(gè)數(shù)必須放在A中,而運(yùn)算結(jié)果也必須放在A中,而加1類指令的對(duì)象則廣泛得多,可以是寄存器、內(nèi)存地址、間址尋址的地址等等。
在INC data這條指令中,如果直接地址是I/O,其功能是先讀入I/O鎖存器的內(nèi)容,然后在CPU進(jìn)行加1操作,再輸出到I/O上,這就是“讀—修改—寫”操作。
[7]. 減1指令(4條)
這組指令的作用是把所指的寄存器內(nèi)容減1,結(jié)果送回原寄存器,若原寄存器的內(nèi)容為00H,減1后即為FFH,運(yùn)算結(jié)果不影響任何標(biāo)志位,這組指令共有直接、寄存器、寄存器間址等尋址方式,當(dāng)直接地址是I/O口鎖存器時(shí),“讀—修改—寫”操作與加1指令類似。
DEC A ;(A)-1→(A)累加器A中的內(nèi)容減1,結(jié)果送回累加器A中
DEC data ;(data)-1→(data)直接地址單元中的內(nèi)容減1,結(jié)果送回直接地址單元中
DEC @Ri ;((Ri))-1→((Ri))寄存器Ri指向的地址單元中的內(nèi)容減1,結(jié)果送回原地址單元中
DEC Rn ;(Rn)-1→(Rn)寄存器Rn中的內(nèi)容減1,結(jié)果送回寄存器Rn中
[8]. 十進(jìn)制調(diào)整指令(1條)
在進(jìn)行BCD碼運(yùn)算時(shí),這條指令總是跟在ADD或ADDC指令之后,其功能是將執(zhí)行加法運(yùn)算后存于累加器A中的結(jié)果進(jìn)行調(diào)整和修正。
DA A
綜合練習(xí):
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
先寫出每步運(yùn)行結(jié)果,然后將以上題目鍵入,并在軟件仿真中運(yùn)行,觀察寄存器及有關(guān)單元的內(nèi)容的變化?唇Y(jié)果是否與預(yù)想的結(jié)果相同?
關(guān)于軟件仿真的具體使用方法,我們會(huì)專門安排一節(jié)課給大家學(xué)習(xí)。敬請(qǐng)期待!