在AT89S51指令系統(tǒng)中,有單字節(jié)的加、減、乘、除法指令,算術(shù)運算功能比較強(qiáng)。算術(shù)運算指令都是針對8位二進(jìn)制無符號數(shù)的,如要進(jìn)行帶符號或多字節(jié)二進(jìn)制數(shù)運算,需編寫具體的運算程序,通過執(zhí)行程序?qū)崿F(xiàn)。
算術(shù)運算的結(jié)果將使PSW中的進(jìn)位(Cy)、輔助進(jìn)位(Ac)、溢出(OV)3種標(biāo)志位置1或清0,但是增1和減1指令不影響這些標(biāo)志。
1.加法指令
共有4條加法運算指令:
這4條8位二進(jìn)制數(shù)加法指令的一個加數(shù)總是來自累加器A,而另一個加數(shù)可由寄存器尋址、直接尋址、寄存器間接尋址和立即數(shù)尋址等不同的尋址方式得到。其相加的結(jié)果總是放在累加器A中。
使用加法指令時,要注意累加器A中的運算結(jié)果對各個標(biāo)志位的影響:
(1)如果位7有進(jìn)位,則進(jìn)位標(biāo)志Cy置l,否則Cy清0。
(2)如果位3有進(jìn)位,輔助進(jìn)位標(biāo)志Ac置1,否則Ac(Ac為PSW寄存器中的一位)清O。
(3)如果位6有進(jìn)位而位7沒有進(jìn)位,或者位7有進(jìn)位而位6沒有進(jìn)位,則溢出標(biāo)志位OV置l,否則OV清0。
溢出標(biāo)志位OV的狀態(tài),只有進(jìn)行帶符號數(shù)加法運算時才有意義。當(dāng)兩個帶符號數(shù)相加時,OV=1,表示加法運算超出了累加器A所能表示的帶符號數(shù)的有效范圍(-128~+127),即產(chǎn)生了溢出,表示運算結(jié)果是錯誤的,否則運算是正確的,即無溢出產(chǎn)生。
【例3-1】 (A)=53H,(RO)=FCH,執(zhí)行指令
運算式為
結(jié)果為(A)=4FH,Cy=l,Ac=0,OV=O,P=1(A中l(wèi)的位數(shù)為奇數(shù))。
注意:在上面的運算中,由于位6和位7同時有進(jìn)位,所以標(biāo)志位OV=O。
【例3-2】 (A)=85H,(RO)=20H,(20H)=AFH,執(zhí)行指令
運算式為
結(jié)果為(A)=34H,Cy=l,Ac=l,OV=1,P=1。
注意:由于位7有進(jìn)位,而位6無進(jìn)位,所以標(biāo)志位OV=1。
2.帶進(jìn)位加法指令
帶進(jìn)位加法運算的特點是進(jìn)位標(biāo)志位Cy參加運算,因此帶進(jìn)位的加法運算是三個數(shù)相加。帶進(jìn)位的加法指令共4條:
這組帶進(jìn)位加法指令的功能是,指令中不同尋址方式所指定的加數(shù)、進(jìn)位標(biāo)志與累加器A內(nèi)容相加,結(jié)果存在累加器A中。
如果位7有進(jìn)位,則進(jìn)位標(biāo)志Cy置1,否則Cy清0;如果位3有進(jìn)位輸出,則輔助進(jìn)位標(biāo)志Ac置l,否則Ac清0;如果位6有進(jìn)位而位7沒有進(jìn)位,或者位7有進(jìn)位而位6沒有進(jìn)位,則溢出標(biāo)志OV置1,否則標(biāo)志OV清O。
【例3-3】 (A)=85H,(20H)=FFH,Cy=l,執(zhí)行指令
運算式為
結(jié)果為(A)=85H,Cy=l,Ac=l,OV=0,P=l(A中1的位數(shù)為奇數(shù))。
3.增1指令
共有5條增1指令:
這組增1指令的功能是把指令中所指出的變量增1,且不影響程序狀態(tài)字PSW中的任何標(biāo)志。若變量原來為FFH,加1后將溢出為OOH(僅指前4條指令),標(biāo)志也不會受到影響。第5條指令“INC DPTR”,是16位數(shù)增1指令。指令首先對低8位指針DPL的內(nèi)容執(zhí)行加1操j作,當(dāng)產(chǎn)生溢出時,就對DPH的內(nèi)容進(jìn)行加1操作,并不影響標(biāo)志Cy的狀態(tài)。
4.十進(jìn)制調(diào)整指令
十進(jìn)制調(diào)整指令用于對BCD碼十進(jìn)制數(shù)加法運算結(jié)果的內(nèi)容進(jìn)行修正,指令格式為:
這條指令的功能是對壓縮的BCD碼(一個字節(jié)存放2位BCD碼)的加法結(jié)果進(jìn)行十進(jìn)制調(diào)整。兩個BCD碼按二進(jìn)制相加之后,必須經(jīng)本指令的調(diào)整才能得到正確的壓縮BCD碼的和數(shù)。
(1)十進(jìn)制調(diào)整問題
對于十進(jìn)制數(shù)(BCD碼)的加法運算,只能借助于二進(jìn)制加法指令。然而,二進(jìn)制數(shù)的加法運算原則上并不能適用于十進(jìn)制數(shù)的加法運算,有時會產(chǎn)生錯誤結(jié)果。
例如:
上述的BCD碼運算中:
(a)運算結(jié)果正確。
(b)運算結(jié)果不正確,因為十進(jìn)制數(shù)的BCD碼中沒有1111這個編碼。
(c)運算結(jié)果也不正確,正確結(jié)果應(yīng)為17,而運算結(jié)果卻是11。
這種情況表明,二進(jìn)制數(shù)加法指令不能完全適用于BCD碼十進(jìn)制數(shù)的加法運算,因此要對結(jié)果進(jìn)行有條件的修正,這就是所謂的十進(jìn)制調(diào)整問題。
(2)出錯原因和調(diào)整方法
出錯的原因在于BCD碼是4位二進(jìn)制編碼,共有16個編碼,但BCD碼只用了其中的10個,剩下6個沒用到。這6個沒用到的編碼(1010,1011,1100,1101,1110,1111)為無效編碼。
在BCD碼的加法運算中,凡結(jié)果進(jìn)入或者跳過無效編碼區(qū)時,其結(jié)果就是錯誤的。因此1泣BCD碼加法運算出錯的情況有以下兩種:
?、傧嗉咏Y(jié)果大于9,說明已經(jīng)進(jìn)入無效編碼區(qū)。
?、谙嗉咏Y(jié)果有進(jìn)位,說明已經(jīng)跳過無效編碼區(qū)。
無論哪一種出錯情況,都是因為6個無效編碼造成的。因此,只要出現(xiàn)上述兩種情況之一,就必須進(jìn)行調(diào)整。調(diào)整的方法是把運算結(jié)果加6調(diào)整,即所謂的十進(jìn)制調(diào)整修正。
十進(jìn)制調(diào)整的修正方法如下:
?、倮奂悠鞯?位大于9或輔助進(jìn)位位Ac=l,則進(jìn)行低4位加6修正。
②累加器高4位大于9或進(jìn)位位Cy=l,則進(jìn)行高4位加6修正。
③累加器高4位為9,低4位大于9,則高4位和低4位分別加6修正。
上述十進(jìn)制調(diào)整修正,是通過執(zhí)行指令“DA A”自動實現(xiàn)的。
【例3-4】 (A)=56H,(R5)=67H,把它們看作兩個壓縮的BCD數(shù),進(jìn)行BCD數(shù)加法。
執(zhí)行指令:
由于高4位和低4位分別大于9,所以“DA A”指令要分別加6,來對結(jié)果進(jìn)行修正。
結(jié)果為(A)=23H,Cy=l。
由上可見,56+67=123,結(jié)果是正確的。
5.帶借位的減法指令
共有4條指令:
這組帶借位減法指令是從累加器A中的內(nèi)容減去指定的變量和進(jìn)位標(biāo)志Cy的值,結(jié)果存放在累加器A中。
如果位7需借位則Cy置l,否則Cy清0;如果位3需借位則Ac置1,否則Ac清0;如果位6需借位而位7不需要借位,或者位7需借位而位6不需借位,則溢出標(biāo)志位OV置1,否則OV清0。
源操作數(shù)允許有寄存器尋址、直接尋址、寄存器間接尋址和立即數(shù)尋址方式。
【例3-5】 (A)=C9H,(R2)=54H,Cy=l,執(zhí)行指令
運算式為
結(jié)果為(A)=74H,Cy=0,Ac=0,OV=1(位6向位7借位)。
6.減1指令
共有4條指令:
這組指令的功能是指定的變量減1。若原來為OOH,減1后下溢為FFH,不影響標(biāo)志位(P標(biāo)志除外)。
【例3-6】 (A)=OFH,(R7)=19H,(30H)=OOH,(Rl)=40H,(40H)=OFFH,執(zhí)行指令
結(jié)果為(A)=OEH,(R7)=18H,(30H)=OFFH,(40H)=OFEH,P=l,不影響其他標(biāo)志。
7.乘法指令
這條指令的功能是把累加器A和寄存器B中的無符號8位整數(shù)相乘,其16位積的低位字節(jié)在累加器A中,高位字節(jié)在B中。如果積大于255,則溢出標(biāo)志位OV置1,否則OV清0。進(jìn)位標(biāo)志位Cy總是清0。
8.除法指令
該指令的功能是用累加器A中8位無符號整數(shù)(被除數(shù))除以B中8位無符號整數(shù)(除數(shù)),所得的商(為整數(shù))存放在累加器A中,余數(shù)存放在寄存器B中,且Cy和溢出標(biāo)志位OV清0。如果B的內(nèi)容為0(即除數(shù)為0),則存放結(jié)果的A、B中的內(nèi)容不定,并溢出標(biāo)志位OV置l。
【例3-7】 (A)=FBH,(B)=12H,執(zhí)行指令
結(jié)果為(A)=ODH,(B)=11H,Cy=0,OV=O。