什么是單片機(jī)尋址方式與指令系統(tǒng)
通過前面的學(xué)習(xí),我們已經(jīng)了解了單片機(jī)內(nèi)部的結(jié)構(gòu),并且也已經(jīng)知道,要控制單片機(jī),讓它為我們干學(xué),要用指令,我們已學(xué)了幾條指令,但很零散,從現(xiàn)在開始,我們將要系統(tǒng)地學(xué)習(xí)8051單片機(jī)的指令部份。
一、概述
1、指令的格式
指令的一個(gè)重要組成部分是操作數(shù),由它指定參與運(yùn)算的數(shù)據(jù)或數(shù)據(jù)所在的存儲(chǔ)器單元或寄存器或I/O接口的地址。指令中所規(guī)定的尋找操作數(shù)的方式就是尋址方式。每一種計(jì)算都具有多種尋址方式,尋址方式越多,計(jì)算機(jī)的功能就越強(qiáng),靈活性就越大。尋址方式的多少及尋址功能是反映指令系統(tǒng)優(yōu)劣的主要因素之一。要掌握指令系統(tǒng)也可從尋址方式入手。
MCS-51指令系統(tǒng)的尋址方式有7種:立即尋址(#data)、寄存器尋址(Rn)、間接尋址(@Ri、@DPTR)直接尋址direct、變址尋址(A+)、相對(duì)尋址(rel)和特定寄存器尋址(A)。有些書把A當(dāng)寄存器尋址,把位尋址單獨(dú)作一種尋址方式,不管怎么分類其目的是為了便于記憶、掌握111條指令。
1.立即尋址(#data)
操作數(shù)包含在指令字節(jié)中,操作數(shù)直接出現(xiàn)在指令中,并存放在程序存儲(chǔ)器中,這種方式稱為立即尋址。
立即尋址指令的操作數(shù)是一個(gè)8位或16位的二進(jìn)制常數(shù),它前面以“#”號(hào)標(biāo)識(shí),例如:ADD A,#56H,即#56H與累加器A(設(shè)為31H)內(nèi)容相加,結(jié)果(87H)存于累加器A中。這條指令的機(jī)器碼為2456H.
2.寄存器尋址(Rn)
由指令指出某一個(gè)寄存器中的內(nèi)容作為操作數(shù),這種尋址方式稱為寄存器尋址。在這種尋址方式中,指令的操作碼中包含了參加操作的工作寄存器R0~R7的代碼(指令操作碼字節(jié)的低3位指明所尋址的工作寄存器)。例如:ADD A,Rn中的Rn,當(dāng)n為0、1、2時(shí),機(jī)器碼分別為28、29、2A.
3.間接尋址(@Ri/@DPTR)
由指令指出某一個(gè)寄存器內(nèi)容作為操作數(shù)的地址。這種尋址方式稱為寄存器間接尋址。訪問外部RAM時(shí),可使用R0,R1或DPTR作為地址指針,寄存器間接尋址用符號(hào)“@”表示。
例如:MOV A,@RO(機(jī)器碼E7)是指:若RO內(nèi)容為66(內(nèi)部RAM地址單元66H),而66H單元中內(nèi)容是27H,則指令的功能是將27H這個(gè)數(shù)送到累加器A.
4.直接尋址(direct)
在指令中直接給出操作數(shù)所在存儲(chǔ)單元的地址(一個(gè)8位二進(jìn)制數(shù)),稱為直接尋址。直接地址用direct表示,
直接尋址方式中操作數(shù)存儲(chǔ)的空間有三種:
(1).內(nèi)部數(shù)據(jù)存儲(chǔ)器的128個(gè)字節(jié)單元(00H~7FH)
(2).位地址空間(有些書把這種尋址方式單獨(dú)作一種尋址方式)
(3).特殊功能寄存器, 特殊功能寄存器只能用直接尋址方式進(jìn)行訪問。
5.基址加變址尋址(@A+PC/@A+DPTR)
以16位寄存器(DPTR或PC)作為基址寄存器,加上地址偏移量(累加器A中的8位無符號(hào)數(shù))形成操作數(shù)的地址。
變址尋址方式有兩類:
(1).以程序計(jì)數(shù)器的值為基址例如指令:
MOVC A,@A+PC; ;(A)←((A)+(PC))
指令的功能是先使PC指向本指令下一條指令地址(本指令以完成),然后PC地址與累加器內(nèi)容相加,形成變址尋址的單元地址內(nèi)容送A。
(2).以數(shù)據(jù)指針DPTR為基址,以數(shù)據(jù)指針內(nèi)容和累加器內(nèi)容相加形成地址,例如:
MOV DPTR #4200H ;給DPTR賦值
MOV A,#10H ;給A賦值
MOVC A ,@A+DPTR ;變址尋址方式(A)←((A)+(DPTR))
三條指令的執(zhí)行結(jié)果是將4210H單元內(nèi)容送A中。
6.相對(duì)尋址(rel)
以程序計(jì)數(shù)器PC的當(dāng)前值為基址,加上相對(duì)尋址指令的字節(jié)長度,再加上指令中給定的偏移量rel的值(rel是一個(gè)8位帶符號(hào)數(shù),用二進(jìn)制補(bǔ)碼表示),形成相對(duì)尋址的地址。
例如指令:
JNZ rel (或rel = 23H,機(jī)器碼為7023)
當(dāng)A≠0時(shí),程序跳到這條指令后面,相差23個(gè)字節(jié)運(yùn)行下一條指令。
7.特定寄存器尋址
累加器A和數(shù)據(jù)針DPTR這兩個(gè)使用最頻繁的寄存器又稱為特殊寄存器。對(duì)特定寄存器的操作指令,指令不再需要指出其地址字節(jié),指令碼本身隱含了操作對(duì)象A或DPTR。
例如:
INC A (指令碼04) ;累加器加1
MOV A,#12H (指令碼7412) ;數(shù)12送累加器
INC DPTR (指令碼A3) ;數(shù)據(jù)指針內(nèi)容加1
綜上所述,尋址方式與存儲(chǔ)器結(jié)構(gòu)有密切關(guān)系。一種尋址方式只適合于對(duì)一部分存儲(chǔ)器進(jìn)行操作,在使用時(shí)要加以注意。
我們已知,要讓計(jì)算機(jī)做事,就得給計(jì)算機(jī)以指令,并且我們已知,計(jì)算機(jī)很“笨”,只能懂得數(shù)字,如前面我們寫進(jìn)機(jī)器的75H,90H,00H等等,所以指令的第一種格式就是機(jī)器碼格式,也說是數(shù)字的形式。但這種形式實(shí)在是為難我們?nèi)肆耍y記了,于是有另一種格式,助記符格式,如MOV P1,#0FFH,這樣就好記了。 這兩種格式之間的關(guān)系呢,我們不難理解,本質(zhì)上它們完全等價(jià),只是形式不一樣而已。
2、匯編
我們寫指令使用匯編格式,而計(jì)算機(jī)和單片機(jī)只懂機(jī)器碼格式,所以要將我們寫的匯編格式的指令轉(zhuǎn)換為機(jī)器碼格式,這種轉(zhuǎn)換有兩種辦法:手工匯編和機(jī)器匯編。手工匯編實(shí)際上就是查表,因?yàn)檫@兩種格式純粹是格式不一樣,所以是一一對(duì)應(yīng)的,查一張表格就行了。不過手工查表總是嫌麻煩,所以就有了計(jì)算機(jī)軟件,用計(jì)算機(jī)軟件來替代手工查表,這就是機(jī)器匯編。
二、單片機(jī)的尋址
讓我們先來復(fù)習(xí)一下我們學(xué)過的一些指令:MOV P1,#0FFH,MOV R7,#0FFH這些指令都是將一些數(shù)據(jù)送到對(duì)應(yīng)的位置中去,為什么要送數(shù)據(jù)呢?第一個(gè)因?yàn)樗腿氲臄?shù)能讓燈全滅掉,第二個(gè)是為了要實(shí)現(xiàn)延時(shí),從這里我們能看出來,在用單片機(jī)的編程語言編程時(shí),經(jīng)常要用到數(shù)據(jù)的傳遞,事實(shí)上數(shù)據(jù)傳遞是單片機(jī)編程時(shí)的一項(xiàng)重要工作,一共有28條指令(單片機(jī)共111條指令)。下面我們就從數(shù)據(jù)傳遞類指令開始吧。
分析一下MOV P1,#0FFH這條指令,我們不難得出結(jié)論,第一個(gè)詞MOV是命令動(dòng)詞,也就是決定做什么事情的,MOV是MOVE少寫了一個(gè)E,所以就是“傳遞”,這就是指令,規(guī)定做什么事情,后面還有一些參數(shù),分析一下,數(shù)據(jù)傳遞必須要有一個(gè)“源”也就是你要送什么數(shù),必須要有一個(gè)“目的”,也就是你這個(gè)數(shù)要送到什么地方去,顯然在上面那條單片機(jī)指令中,要送的數(shù)(源)就是0FFH,而要送達(dá)的地方(目的地)就是P1這個(gè)寄存器。在數(shù)據(jù)傳遞類指令中,均將目的地寫在指令的后面,而將源寫在最后。
這條指令中,送給P1是這個(gè)數(shù)本身,換言之,做完這條指令后,我們能明確地知道,P1中的值是0FFH,但是并不是任何時(shí)候都能直接給出數(shù)本身的。例如,在我們前面給出的單片機(jī)延時(shí)程序例是這樣寫的:
MAIN: SETB P1.0 ?。唬ǎ保?/P>
LCALL DELAY ;(2)
CLR P1.0 ;(3)
LCALL DELAY ??;(4)
AJMP MAIN ;(5)
;以下子程序
DELAY: MOV R7,#250 ??;(6)
D1: MOV R6,#250 ;(7)
D2: DJNZ R6,D2 ??;(8)
DJNZ R7,D1 ?。唬ǎ梗?/P>
RET ??;(10)
END ??;(11)
表1
-----------------------------------------------------
MAIN: SETB P1.0 ;(1)
MOV 30H,#255
LCALL DELAY ;
CLR P1.0 ;(3)
MOV 30H,#200
LCALL DELAY ?。唬ǎ矗?/P>
AJMP MAIN ??;(5)
;以下子程序
DELAY: MOV R7,30H ??;(6)
D1: MOV R6,#250 ??;(7)
D2: DJNZ R6,D2 ??;(8)
DJNZ R7,D1 ??;(9)
RET ;(10)
END ?。唬ǎ保保?
表2
這樣一來,我每次調(diào)用延時(shí)程序延時(shí)的時(shí)間都是相同的(大致都是0.13S),如果我提出這樣的要求:燈亮后延時(shí)時(shí)間為0.13S燈滅,燈滅后延時(shí)0.1秒燈亮,如此循環(huán),這樣的程序還能滿足要求嗎?不能,怎么辦?我們能把延時(shí)程序改成這樣(見表2):調(diào)用則見表2中的主程,也就是先把一個(gè)數(shù)送入30H,在子程序中R7中的值并不固定,而是根據(jù)30H單元中傳過來的數(shù)確定。這樣就能滿足要求。
從這里我們能得出結(jié)論,在數(shù)據(jù)傳遞中要找到被傳遞的數(shù),很多時(shí)候,這個(gè)數(shù)并不能直接給出,需要變化,這就引出了一個(gè)概念:如何尋找操作數(shù),我們把尋找操作數(shù)所在單元的地址稱之為尋址。在這里我們直接使用數(shù)所在單元的地址找到了操作數(shù),所以稱這種辦法為直接尋址。除了這種辦法之外,還有一種,如果我們把數(shù)放在工作寄存器中,從工作寄存器中尋找數(shù)據(jù),則稱之為寄存器尋址。例:MOV A,R0就是將R0工作寄存器中的數(shù)據(jù)送到累加器A中去。提一個(gè)問題:我們知道,工作寄存器就是內(nèi)存單元的一部份,如果我們選擇工作寄存器組0,則R0就是RAM的00H單元,那么這樣一來,MOV A,00H,和MOV A,R0不就沒什么區(qū)別了嗎?為什么要加以區(qū)別呢?的確,這兩條指令執(zhí)行的結(jié)果是完全相同的,都是將00H單元中的內(nèi)容送到A中去,但是執(zhí)行的過程不一樣,執(zhí)行第一條指令需要2個(gè)周期,而第二條則只需要1個(gè)周期,第一條指令變成最終的目標(biāo)碼要兩個(gè)字節(jié)(E5H 00H),而第二條則只要一個(gè)字節(jié)(E8h)就能了。
這么斤斤計(jì)較!不就差了一個(gè)周期嗎,如果是12M的晶體震蕩器的話,也就1個(gè)微秒時(shí)間了,一個(gè)字節(jié)又能有多少?
不對(duì),如果這條指令只執(zhí)行一次,也許無所謂,但一條指令如果執(zhí)行上1000次,就是1毫秒,如果要執(zhí)行1000000萬次,就是1S的誤差,這就很可觀了,單片機(jī)做的是實(shí)時(shí)控制的事,所以必須如此“斤斤計(jì)較”。字節(jié)數(shù)同樣如此。
再來提一個(gè)問題,現(xiàn)在我們已知,尋找操作數(shù)能通過直接給的方式(立即尋址)和直接給出數(shù)所在單元地址的方式(直接尋址),這就夠了嗎?
看這個(gè)問題,要求從30H單元開始,取20個(gè)數(shù),分別送入A累加器。
就我們目前掌握的辦法而言,要從30H單元取數(shù),就用MOV A,30H,那么下一個(gè)數(shù)呢?是31H單元的,怎么取呢?還是只能用MOV A,31H,那么20個(gè)數(shù),不是得20條指令才能寫完嗎?這里只有20個(gè)數(shù),如果要送200個(gè)或2000個(gè)數(shù),那豈不要寫上200條或2000條命令?這未免太笨了吧。為什么會(huì)出現(xiàn)這樣的狀況?是因?yàn)槲覀冎粫?huì)把地址寫在指令中,所以就沒辦法了,如果我們不是把地址直接寫在指令中,而是把地址放在另外一個(gè)寄存器單元中,根據(jù)這個(gè)寄存器單元中的數(shù)值決定該到哪個(gè)單元中取數(shù)據(jù),比如,當(dāng)前這個(gè)寄存器中的值是30H,那么就到30H單元中去取,如果是31H就到31H單元中去取,就能解決這個(gè)問題了。怎么個(gè)解決法呢?既然是看的寄存器中的值,那么我們就能通過一定的辦法讓這里面的值發(fā)生變化,比如取完一個(gè)數(shù)后,將這個(gè)寄存器單元中的值加1,還是執(zhí)行同一條指令,可是取數(shù)的對(duì)象卻不一樣了,不是嗎。通過例程來說明吧。
MOV R7,#20
MOV R0,#30H
LOOP:MOV A,@R0
INC R0
DJNZ R7,LOOP
這個(gè)例程中大部份指令我們是能看懂的,第一句,是將立即數(shù)20送到R7中,執(zhí)行完后R7中的值應(yīng)當(dāng)是20。第二句是將立即數(shù)30H送入R0工作寄存器中,所以執(zhí)行完后,R0單元中的值是30H,第三句,這是看一下R0單元中是什么值,把這個(gè)值作為地址,取這個(gè)地址單元的內(nèi)容送入A中,此時(shí),執(zhí)行這條指令的結(jié)果就相當(dāng)于MOV A,30H。第四句,沒學(xué)過,就是把R0中的值加1,因此執(zhí)行完后,R0中的值就是31H,第五句,學(xué)過,將R7中的值減1,看是否等于0,不等于0,則轉(zhuǎn)到標(biāo)號(hào)LOOP處繼續(xù)執(zhí)行,因此,執(zhí)行完這句后,將轉(zhuǎn)去執(zhí)行MOV A,@R0這句話,此時(shí)相當(dāng)于執(zhí)行了MOV A,31H(因?yàn)榇藭r(shí)的R0中的值已是31H了),如此,直到R7中的值逐次相減等于0,也就是循環(huán)20次為止,就實(shí)現(xiàn)了我們的要求:從30H單元開始將20個(gè)數(shù)據(jù)送入A中。
這也是一種尋找數(shù)據(jù)的辦法,由于數(shù)據(jù)是間接地被找到的,所以就稱之為間址尋址。注意,在間址尋址中,只能用R0或R1存放等尋找的數(shù)據(jù)。
指令系統(tǒng)
數(shù)據(jù)傳送指令
數(shù)據(jù)傳送指令包括數(shù)據(jù)的傳送、交換、堆棧數(shù)據(jù)的壓入與彈出,是最基本、使用率最高的一類指令。助記符有MOV、MOVX、MOVC、XCH、XCHD、SWAP、PUSH、POP共八種。
1.MOV類指令及功能(16條)
這類指令的功能是從源操作數(shù)到目的操作數(shù)的數(shù)據(jù)傳送。
MOV A, Rn ;Rn→A,寄存器Rn的內(nèi)容送到累加器A
MOV A, direct ;(direct)→A,直接地址中的內(nèi)容送A
MOV A, @Ri ;(Ri)→A,Ri間址的內(nèi)容送A
MOV A, #data ;data→A,立即數(shù)送A
MOV Rn,, A ;A→Rn,累加器A中的內(nèi)容送寄存器Rn
MOV Rn, direct ;(direct)→Rn;直接地址中的內(nèi)容送Rn
MOV Rn, #data ;data→Rn;立即數(shù)送Rn
MOV direct, A ;A→(direct),A中的內(nèi)容送入直接地址中
MOV direct, Rn ;Rn→(direct),寄存器內(nèi)容送入直接地址中
MOV direct, direct ;(direct) →(direct),源操作數(shù)直接地址的內(nèi)容送入
;目的操作數(shù)的直接地址中
MOV direct, @Ri ;(Ri)→(direct),Ri間址內(nèi)容送入直接地址中
MOV direct, #data ;data→(direct),立即數(shù)送入直接地址中
MOV @Ri, A ;A→(Ri),A中內(nèi)容送到Ri間址單元中
MOV @Ri, direct ;(direct)→(Ri),直接地址中內(nèi)容送入Ri間址單元中
MOV @Ri, #data ;data→(Ri),立即數(shù)送入Ri間址單元中
MOV DPTR, #data16 ;data16→DPTR,16位常數(shù)送入數(shù)據(jù)指針DPTR中,高8
;位送入DPH,低8位送入DPH,低8位送入DPL中
從上述指令可以看出目的操作數(shù)有A累加器、Rn寄存器、直接地址direct及間接地址@Ri,源操作數(shù)除此之外還多一種立即數(shù)data。
例1 R0中有常數(shù)30H,而30H地址中有常數(shù)50H
執(zhí)行MOV A, R0后,A=30H,R0不變。
執(zhí)行MOV A, @R0后A=50H,而不是30H,這條指令的功能是把R0中內(nèi)容為地址的單元的書送入A,R0中是30H也就是把30H地址中內(nèi)容50H送入A。
例2 若(40H)=20H,(50H)=30H
執(zhí)行MOV 40H, 50H; (50H) →(40H)
結(jié)果:(40H)=30H,50H地址中內(nèi)容仍為30H。
例3 若A=40H,R0=30H,
執(zhí)行MOV @R0, A ;A→(R0)
結(jié)果:(30H)=40H,A與R0皆不變,即A=40H,R0=30H。
該指令功能是把A中內(nèi)容送入R0間址單元即R0中內(nèi)容為地址的單元。
例4 執(zhí)行MOV DPTR, #2040H ;2040H→DPTR
結(jié)果:DPH=20H, DPL=40H
DPTR是片外RAM地址指針,只有這一條指令是傳送16位數(shù)據(jù)。
2.MOVC類指令及功能(2條)
MOVC A, @A+PC ;PC+1→PC, (A+PC) →A
MOVC A, @A+DPTR ;(A+DPTR) →A
功能:該類屬于查表指令,利用這兩條指令很方便地查找放在程序存儲(chǔ)器中數(shù)據(jù)表格的內(nèi)容。
例1 程序
1000H MOV A, #10H ;10H→A
1002H MOVC A, @A+PC ;PC+1→PC,PC=1003H,(A+PC)=(10H+1003H)→A
...
1010H 02H
1011H 04H
1012H 06H
1013H 08H
程序執(zhí)行結(jié)果:A=08H
用MOVC A, @A+PC指令需注意兩點(diǎn):
1)指令中的PC是執(zhí)行完本條指令后的PC值,即PC等于本條指令地址加1。
2)A是修正值,它等于查表指令和欲查數(shù)據(jù)相間隔字節(jié)數(shù)。A的范圍是0~255,一次該指令只能查找本指令后的256B范圍內(nèi)的表格,故稱為近程查表。
例2 程序
1000H MOV A, #01H ;01H→A
1002H MOV DPTR, #6000H ;6000H→DPTR
1005H MOVC A,@A+DPTR ;(A+DPTR)=(01H+6000H)=(6001H) →A
...
6001H 0AH
6002H 0BH
6003H 0CH
6004H 0DH
程序執(zhí)行結(jié)果:A=0AH,查到了地址為6001H單元中的數(shù)據(jù)。
用MOVC A, @A+DPTR指令查表特點(diǎn):A, DPTR都可以改變,因此可在64KB范圍內(nèi)查表,故稱為遠(yuǎn)程查表。這條指令更方便。
3.MOVX類指令(4條)
MOVX A, @DPTR ;(DPTR) →A,DPTR間址單元內(nèi)容送A
MOVX @DPTR, A ;A→(DPTR), A 中內(nèi)容送入DPTR間址單元
MOVX A, @Ri ;(Ri) →A,Ri間址單元內(nèi)容送A
MOVX @Ri, A ;A→(Ri), A中內(nèi)容送Ri間址單元
MOVX類指令功能:這四條指令專門用來與外部數(shù)據(jù)存儲(chǔ)區(qū)傳送數(shù)據(jù)。CPU與外部RAM傳送數(shù)據(jù)時(shí)只能用間接尋址方式。
例1 把外部數(shù)據(jù)存儲(chǔ)單元2000H中的數(shù)據(jù)送到4000H單元中,設(shè)2000H中有數(shù)據(jù)30H。
程序 各條指令執(zhí)行結(jié)果
MOV DPTR, #2000H ;2000H DPTR, DPTR=2000H
MOVX A, @DPTR ;(DPTR) A即(2000) A,A=30H
MOV DPTR, #4000H ;4000H→DPTR, DPTR=4000H
MOVX @DPTR, A ;A→(DPTR)即A→(4000H), (4000H)=30H
例2 把內(nèi)部RAM50H單元數(shù)據(jù)送到片外20H單元,設(shè)50H中單元存有數(shù)據(jù)10H。
程序 各條指令執(zhí)行結(jié)果
MOV A,50H ;(50H) 各條指令執(zhí)行結(jié)果A, A=10H
MOV R0,#20H ;20H→R0, R0=20H
MOVX @R0, A ;A→(R0)即A→(20H)則20H=10H
注意:與外部RAM傳送數(shù)據(jù)時(shí),地址小于256B用Ri間址,大于256B時(shí)用DPTR間址。
4.交換指令
XCH A, Rn ;Rn A, Rn與A內(nèi)容交換
XCH A,direct ;(direct) A, 直接地址內(nèi)容與A內(nèi)容交換
XCH A, @Ri ;(Ri) A,Ri間址內(nèi)容與A內(nèi)容交換
XCHD A, @Ri ;(Ri.3~Ri.0) A.3~A.0, Ri間址內(nèi)容低4
位與A中低4 位內(nèi)容交換
SWAP A ;A.3~A.0 A.7~A.4, A中高4位與低4位
交換
例 若R0=30H, A=F0H, (30H)=46H
執(zhí)行 XCH A, R0 ;結(jié)果:A=30H,R0=F0H, R0與A 內(nèi)容交換
執(zhí)行 XCH A, @R0 ;結(jié)果:A=46H, (30H)=F0H, R0中不變,
;實(shí)際上是(R0) A即(30H) A
若執(zhí)行 XCHD A, @R0 ;結(jié)果:A=F6H,(30)H=40H
;A與(30H)中低4位交換,高4位不變
執(zhí)行 SWAP A ;結(jié)果:A=0FH, 高低4位互換
5.堆棧操作指令(2條)
PUSH、POP屬堆棧操作指令,其功能是把直接地址中的內(nèi)容壓入堆棧保存,或從堆棧中取出(彈出)數(shù)據(jù)到直接地址中。
PUSH direct ;SP+1→SP, (direct) →(SP)
;直接地址內(nèi)容壓入堆棧頂
POP direct ;(SP)→(direct), SP-1→SP
;堆棧棧頂內(nèi)容彈出到直接地址
注意:堆棧是用戶自己設(shè)定的內(nèi)部RAM中的一塊專用存儲(chǔ)區(qū),使用堆棧時(shí)一定先設(shè)堆棧指針。堆棧遵循后進(jìn)先出的原則安排數(shù)據(jù)。壓入數(shù)據(jù)時(shí)SP先加1,再壓入;彈出時(shí),先彈出數(shù)據(jù),SP再減1。
例 設(shè)堆棧指針為30H,為保護(hù)現(xiàn)場(chǎng)把A和B中的內(nèi)容壓入堆棧保護(hù),然后根據(jù)需要再把兩者彈出。設(shè)A中為30H,B中為01H。
程序 執(zhí)行結(jié)果
MOV SP, #30H ;30H→SP, SP=30H設(shè)堆棧指針為30H
PUSH ACC ;SP+1→SP=31H, A→(SP)即A→(31H),(31H)=30H
PUSH B ;SP+1→SP=32H, B→(SP)即B→(32H),(32H)=01H
POP B ;SP→B即(32H)→B, B=01H, SP-1→SP=31H
POP ACC ;SP→A即(31H)→A, A=30H, SP-1→SP=30H
從此例可以看出壓入、彈出過程SP的變化規(guī)律
算術(shù)運(yùn)算指令
算術(shù)運(yùn)算指令的主要功能是實(shí)現(xiàn)算術(shù)加、減、乘、除等運(yùn)算。
1.ADD類指令是不帶進(jìn)位的加法運(yùn)算指令(4條)。
ADD A,Rn ;A+Rn→A, A與Rn寄存器內(nèi)容相加,結(jié)果送到A中
ADD A,direct ;(direct)+A→A, A與直接地址內(nèi)容相加,和送A
ADD A, @Ri ;(Ri)+A→A, A與Ri間址內(nèi)容相加,和送A
ADD A, #data ;data+A→A, A與立即數(shù)相加,和送A
注意:ADD類指令相加結(jié)果均在A中,相加后源操作數(shù)不變。若A中最高位有進(jìn)位,Cy置1;若半加位有進(jìn)位,AC置1。A的結(jié)果還影響奇偶標(biāo)志位P。
例 A=30H, R0=10H
執(zhí)行 ADD A,R0 結(jié)果:A=40H, R0=10H,標(biāo)志位 P=1, Cy=0, OV=0, AC=0
2.ADDC類指令(帶進(jìn)位加法4條)
ADDC A, Rn ;A+Rn+Cy→A, A與R n內(nèi)容、進(jìn)位狀態(tài)相加,和送
到A中
ADDC A, direct ;(direct)+Cy+A→A, A與直接地址中內(nèi)容、進(jìn)位狀態(tài)
相加,和送A
ADDC A, @Ri ;(Ri)+Cy+A→A, A與Ri間址單元中內(nèi)容、進(jìn)位狀態(tài)
相加,和送A
ADDC A, #data ;data+Cy+A→A, A與 立即數(shù)、進(jìn)位狀態(tài)相加,和送A
與ADD類指令的區(qū)別是,ADDC指令相加時(shí)連同進(jìn)位標(biāo)志Cy內(nèi)容一起相加,主要用于多字節(jié)加法中的高位字節(jié)的相加,而最低位字節(jié)相加用ADD指令。進(jìn)位位Cy加到字節(jié)的最低位。
例 編寫計(jì)算1234H+0FE7H的程序,將結(jié)果存入內(nèi)部RAM的41H和40H單元,40H存低8位,41H存高8位。
程序
MOV A, #34H ;被加數(shù)低8位數(shù)34H送A
ADD A, #0E7H ;加數(shù)低8位數(shù)E7H與之相加,A=1BH,Cy=1
MOV 40H, A ;A→40H即34H+E7H結(jié)果存入40H中(40H=1BH)
MOV A, #12H ;被加數(shù)高8位數(shù)12H送A
ADDC A, #0FH ;加數(shù)高8位0FH和Cy與A相加,A=22H
MOV 41H, A ;高8位與進(jìn)位位之和存入41H中(41H)=22H
;總和為221BH,總結(jié)果在41H,40H單元中
3.SUBB類指令(4條)
SUBB類指令是帶借位減法指令,其功能是將A中被減數(shù)減去源操作數(shù)指出的內(nèi)容,再減去借位標(biāo)志Cy(原進(jìn)位標(biāo)志)狀態(tài),差值在A中。
SUBB A, Rn ;A-Rn-Cy→A ,A減寄存器Rn內(nèi)容及進(jìn)位標(biāo)志
SUBB A, direct ;A-(direct)-Cy→A,A減直接地址內(nèi)容和進(jìn)位標(biāo)志
SUBB A, Ri ;A-(Ri)-Cy→A, A減Ri間址單元內(nèi)容和進(jìn)位位標(biāo)志
SUBB A, #data ;A-data-Cy→A, A減立即數(shù)和進(jìn)位標(biāo)志
說明:
1) 多字節(jié)減法時(shí),低位相減有借位則把Cy置1,否則Cy為0。
2) MCS-51系列指令中沒有不帶借位的減法指令,所以在單字節(jié)或低位字節(jié)減法時(shí)用SUBB類指令前要先將Cy清0。
3)減去一個(gè)數(shù)實(shí)際上是加上這個(gè)數(shù)的相反數(shù)(負(fù)數(shù)),減法運(yùn)算常常用補(bǔ)碼相加方式。
4.MUL(乘)和DIV(除)指令
乘法指令只有一條:
MUL AB ;A×B→B和A,結(jié)果16位,高8位存入B,低8位在A中
若乘積大于FFH則將溢出標(biāo)志OV置1。
除法指令也只有一條:
DIV AB ; A÷B商→A,余數(shù)→B
注意:當(dāng)除數(shù)為0時(shí)結(jié)果不確定,則溢出將OV置1。
5.INC(加1)和DEC(減1)類指令
加1類指令共5條,其功能是將操作數(shù)內(nèi)容加1。
INC A ;A+1→A, A加1
INC Rn ;Rn+1→Rn, Rn中內(nèi)容加1
INC direct ;(direct)+1→(direct), 直接地址中內(nèi)容加1
INC @Ri ;(Ri)+1→(Ri), Ri間址中的內(nèi)容加1
INC DPTR ;DPTR+1→DPTR, 數(shù)據(jù)指針加1
例 判斷INC R0和INC @R0兩條指令結(jié)果,比較兩者的區(qū)別。設(shè)R0=30H,(30H)=00H。
執(zhí)行 INC R0 ;R0+1=30H+1→R0, 結(jié)果R0=31H
執(zhí)行 INC @R0 ;(R0)+1=(30H)+1→(R0),結(jié)果(30H)=01H,R0中內(nèi)
容不變,仍為30H
減1類指令共4條,其功能是將操作數(shù)指定單元內(nèi)容減1。
DEC A ;A-1→A, A中內(nèi)容減1
DEC Rn ;Rn-1→Rn, Rn中內(nèi)容減1
DEC direct ;(direct)-1→(direct), 直接地址中內(nèi)容減1
DEC @Ri ;(Ri)-1→(Ri), Ri間址中的內(nèi)容減1
操作過程與加1指令類似,這里不再舉例。
6.十進(jìn)制加法調(diào)整指令(1條)
DA A
功能:在加法指令后,把A中二進(jìn)制碼自動(dòng)調(diào)整成BCD碼。
例 MOV A, #05H ;05H→A
ADD A, #08H ;05H+08H→A=0DH
DA A ;結(jié)果調(diào)整A=13H,即是13的BCD碼
注意:DA A指令只能跟在ADD或ADDC加法指令后,不適用于減法。
邏輯運(yùn)算指令
1.ANL類指令(6條)
ANL類是邏輯與指令,其功能是將源操作數(shù)作數(shù)內(nèi)容和目的操作數(shù)內(nèi)容按位相“與”,結(jié)果存入目的操作數(shù)指定單元中,源操作數(shù)不變。
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)
例 設(shè)A=F6H,(30H)=0FH
執(zhí)行 ANL A, 30H ;A∩ (30H) →A
操作如下:
11110110 (F6H)
∩ 00001111 (0FH) 注意:按位相“與”
00000110 (06H)
結(jié)果:A=06H, 30H地址內(nèi)容不變,即(30H)=0FH
若執(zhí)行ANL 30H, A ;(30H)∩ A→(30H)
操作同上,結(jié)果放在30H地址中,A中內(nèi)容不變,即(30H)=06H, A=F6H。
2.ORL類指令(6條)
ORL類指令是邏輯或指令,其功能是將源操作數(shù)作數(shù)內(nèi)容和目的操作數(shù)內(nèi)容按位邏輯“或”,結(jié)果存入目的操作數(shù)指定單元中,源操作數(shù)不變。
ORL A, Rn ;A∪Rn→A
ORL A,direct ;A∪(direct) →A
ORL A, @Ri ;A∪(Ri) →A
ORL A, #data ;A∪data→A
ORL direct, A ;(direct)∪A→(direct)
ORL direct, #data ;(direct)∪data→(direct)
“或”運(yùn)算和“與”運(yùn)算過程類似,這里不再舉例。
3.XRL類指令(6條)
XRL類是異或指令,其功能是將兩個(gè)操作數(shù)指定內(nèi)容按位“異或”,結(jié)果存于目的操作數(shù)指定單元中?!爱惢颉痹瓌t是相同為“0”,相異為“1”。
XRL A, Rn ;A⊕Rn→A
XRL A, direct ;A⊕(direct) →A
XRL A, @Ri ;A⊕(Ri) →A
XRL A, #data ;A⊕data→A
XRL direct, A ;(direct)⊕A →(direct)
XRL direct, #data ;(direct)⊕data→(direct)
例 (50H)=05H
執(zhí)行 XRL 50H, #06H ;(50H)⊕06H→(50H)
操作如下:
00000101 (05H)
⊕ 00000110 (06H)
00000011 (03H)
結(jié)果:(50H)=03H
4.循環(huán)移位指令(4條)
循環(huán)移位指令的功能是將累加器A中內(nèi)容循環(huán)位移或者和進(jìn)位位一起移位。
例 A=01H, Cy=1
若執(zhí)行一次 RRC A后,結(jié)果為:A=10000000B Cy=1
若執(zhí)行一次 RLC A后,結(jié)果為:A=00000011B Cy=0
5.取反、清0指令
CPL A ;累加器內(nèi)容按位取反。如果1就變0,如果0就變1
CLR A ;累加器A清0
控制轉(zhuǎn)移類指令
計(jì)算機(jī)運(yùn)行過程中,有時(shí)因?yàn)椴僮鞯男枰绦虿荒馨错樞蛑饤l執(zhí)行指令,需要改變程序運(yùn)行方向,即將程序跳轉(zhuǎn)到某個(gè)指定的地址再順序執(zhí)行下去。
控制轉(zhuǎn)移類指令的功能就是根據(jù)要求修改程序計(jì)數(shù)器PC的內(nèi)容,以改變程序運(yùn)行方向,實(shí)現(xiàn)轉(zhuǎn)移。
控制轉(zhuǎn)移類指令可分為:無條件轉(zhuǎn)移、條件轉(zhuǎn)移、絕對(duì)轉(zhuǎn)移、相對(duì)轉(zhuǎn)移和調(diào)用、返回指令。下面我們將分類介紹。
1.無條件轉(zhuǎn)移指令(4條)
LJMP add16 ;add16→PC,無條件跳轉(zhuǎn)到add16地址,可在64KB范圍內(nèi)
轉(zhuǎn)移,稱為長轉(zhuǎn)移指令
AJMP add11 ;add11→PC,無條件轉(zhuǎn)向add11地址,在2KB范圍內(nèi)轉(zhuǎn)移
SJMP rel ;PC+2+rel→PC,相對(duì)轉(zhuǎn)移,rel是偏移量,8 位有符號(hào)
數(shù),范圍-128~127,即可向后跳轉(zhuǎn)128,向前可跳轉(zhuǎn)127
JMP @A+DPTR ;A+DPTR→PC ,屬散轉(zhuǎn)指令,無條件轉(zhuǎn)向A與DPTR內(nèi)容相
加后形成的新地址
例1 執(zhí)行指令
LJMP 9100H
不管這條指令存放在哪里,執(zhí)行時(shí)將使程序轉(zhuǎn)移到9100H,和AJMP,SJMP指令是有差別的。
例2 程序
2000H MOV R0 , #10H ;10H→PC
2002H SJMP 03H ;PC+2+rel=2002H+2+03H=2007H→PC
┇ ┇
2006H ┇
2007H ┇
從說明中可見,執(zhí)行SJMP 03H 指令后,馬上跳轉(zhuǎn)到2007H地址執(zhí)行程序。
2.條件轉(zhuǎn)移指令(8條)
條件轉(zhuǎn)移指令是根據(jù)某種特定條件轉(zhuǎn)移的指令。條件滿足時(shí)轉(zhuǎn)移,條件不滿足時(shí)則順序
執(zhí)行下面的指令。
JZ rel ;A=0轉(zhuǎn)向PC+2+rel→PC,A≠0順序執(zhí)行
JNZ rel ;A≠轉(zhuǎn)向PC+2+rel→PC ,A=0順序執(zhí)行
CJNE A, direct, rel ;A≠ (direct)轉(zhuǎn)向PC+3+rel→PC且當(dāng)A>(direct),Cy=0
;當(dāng)A(direct),Cy=1
;否則A=(direct),PC+3→PC即順序執(zhí)行
CJNE A, #data, rel ;A data P轉(zhuǎn)向PC+3+rel→PC且當(dāng)A >data,Cy=0
;當(dāng)A data,Cy=1,
;A=data,PC+3→PC順序執(zhí)行
CJNZ Rn, #data, rel ;Rn≠data轉(zhuǎn)向PC+3+rel→PC
;且當(dāng)Rn>data,Cy=0,當(dāng)Rndata,Cy=1
;Rn=data,PC+3→PC順序執(zhí)行
CJNE @Ri,#data, rel ;(Ri) ≠data ,PC+3+rel→PC
;且當(dāng)(Ri)>data ,Cy=0,當(dāng)(Ri)data,Cy=1
;(Ri)=data, PC+3→PC順序執(zhí)行
DJNZ Rn, rel ;Rn-1→Rn ,Rn ≠0轉(zhuǎn)向PC+2+rel→PC
;Rn=0,PC+2→PC順序執(zhí)行
DJNZ direct, rel ;(direct)-1→(direct),(direct) ≠0轉(zhuǎn)向 PC+2+rel
→PC
;(direct)=0 ,PC+2→PC順序執(zhí)行
注意:
1)CJNE類指令借用進(jìn)位標(biāo)志Cy作為比較結(jié)果的標(biāo)志位。從指令中可知,目的操作數(shù)內(nèi)容小于原操作數(shù)內(nèi)容Cy置1,反之Cy清0,該類指令多用于分支程序。
2) DJNZ指令執(zhí)行時(shí)Rn或direct先減1,然后再判斷Rn或direct內(nèi)容是否等于0。不為0則轉(zhuǎn),為0順序執(zhí)行。DJNZ用在循環(huán)程序中,控制循環(huán)次數(shù)很方便。
3) JZ和JNZ的操作數(shù)只有一個(gè),是對(duì)A的內(nèi)容的進(jìn)行判斷的指令。
例1 以下程序的循環(huán)次數(shù)是多少,最后(R0)=?
MOV R0 , #0
LL: ┇
DJNZ R0 , LL
分析:由于DJNZ是減1再判斷大小的,因?yàn)镽0=0,所以第一次執(zhí)行DJNZ R0 , LL后R0=FFH=255,則程序要執(zhí)行的次數(shù)為256次,R0最后的值為0。
解:程序要循環(huán)的次數(shù)為256次,最后R0=0
3.調(diào)用、返回、控操作指令
在程序設(shè)計(jì)中,常常要把具有一定功能的公用程序編制成子程序。當(dāng)主程序轉(zhuǎn)至子
程序時(shí)用調(diào)用指令,而在子程序的最后安排一條返回指令,使執(zhí)行完子程序后再返回到主程序。
(1) LCALL addr16 ;調(diào)用入口地址為addr16的子程序
這是一條長調(diào)指令,可調(diào)用64KB范圍內(nèi)的子程序,因此,可放在程序的任何位置。
指令的執(zhí)行過程分兩步:第一步把斷點(diǎn)(當(dāng)前執(zhí)行指令的下一條指令地址)壓入堆棧。第二步將調(diào)用的子程序的入口地址裝入PC。即addr16(16位地址)→PC,轉(zhuǎn)向執(zhí)行子程序。
(2) ACALL addr11 ;子程序入口地址為addr11的子程序
這是一條短調(diào)指令,只能實(shí)現(xiàn)2KB范圍內(nèi)的子程序的調(diào)用。其指令執(zhí)行過程與LCALL
指令一樣。但是需要注意的是:ACALL中addr11只占用PC的PC.0~PC.10位。
(3) RET ;放在子程序最后,使程序準(zhǔn)確返回到主程序斷點(diǎn)處
執(zhí)行過程為:(SP)→PC.8~PC.15斷點(diǎn)地址高字節(jié)送入PC
SP-1→SP,(SP) →PC.0~PC.7斷點(diǎn)低字節(jié)送入PC,
這時(shí)PC中為主程序斷點(diǎn)地址,程序準(zhǔn)確返回到調(diào)用指令的下一條。
例 設(shè)SP=62H,(62H)=07H,(61H)=30H,執(zhí)行指令RET
結(jié)果:SP=60H,(PC)=0730H,CPU從0730H開始執(zhí)行程序。
(4) RETI ;中斷返回指令
該指令用于中斷服務(wù)程序,使中斷程序結(jié)束后準(zhǔn)確返回到主程序斷點(diǎn)處,執(zhí)行過程同RET,它還能清除優(yōu)先級(jí)狀態(tài)。
(5) NOP ;空操作
執(zhí)行該指令時(shí),CPU只進(jìn)行取指令、譯碼,而不進(jìn)行任何操作,故稱為控操作。常用于產(chǎn)生一個(gè)機(jī)器周期延時(shí)。
位操作指令
MCS-51單片機(jī)的特色之一是具有很強(qiáng)的位處理功能。位操作指令又稱為布爾指令,其功能是對(duì)內(nèi)部RAM中可進(jìn)行位操作的區(qū)域進(jìn)行位操作。
在進(jìn)行位操作時(shí),位累加器C即進(jìn)位標(biāo)志Cy,位地址是片內(nèi)RAM字節(jié)地址20H~2FH單元中連續(xù)的128個(gè)位(位地址00H~7FH)和部分功能寄存器。凡SFR中字符等地址能被8整除的特殊功能寄存器都具有可尋址的位地址,其中ACC(位地址E0H~E7H),B(位地址F0H~F7H)和片內(nèi)RAM中128個(gè)位都可作軟件標(biāo)志或存儲(chǔ)位變量。
1. 位數(shù)據(jù)傳送類指令(2條)
MOV C , bit ;(bit) →C,尋址位的狀態(tài)送入C
MOV bit , C ;C→(bit),C的狀態(tài)送入位地址中
2. 位修正指令(6條)
CLR C ;0→C, 清0累加器
CLR bit ;0→(bit);清0尋址位
CPL C ;/C→C,取反
CPL bit ;(/bit) →(bit),尋址位取反
SETB C ;1→C,C置1
SETB bit ;1→ (bit),尋址位置1
3. 位邏輯運(yùn)算指令(4條)
ANL C , bit ;C∩(bit) →C,尋址位和C“與”,結(jié)果放在C
ANL C , /bit ;C∩(/bit) →C,尋址位的非和C“與”,結(jié)果放在C
ORL C , bit ;C∪(bit) →C,尋址位和C“或”,結(jié)果放在C
ORL C , /bit ;C∪(bit) →C,尋址位和C的非“或”,結(jié)果放在C
4. 位條件轉(zhuǎn)移指令(5條)
JC rel ;C=1轉(zhuǎn)向PC+2+rel→PC
C=0順序執(zhí)行PC+2→PC
JNC rel ;C=0轉(zhuǎn)向PC+2+rel→PC
C=1順序執(zhí)行PC+2→PC
JB bit , rel ;(bit) =1轉(zhuǎn)向PC+3+rel→PC
(bit) =0順序執(zhí)行PC+3→PC
JNB bit , rel ;(bit) =0轉(zhuǎn)向PC+3+rel→PC
(bit) =1順序執(zhí)行PC+3→PC
JBC bit , rel ;(bit) =1轉(zhuǎn)向PC+3+rel→PC;同時(shí)0→(bit)
(bit) =0順序執(zhí)行PC+3→PC
注意:JBC與JB指令區(qū)別,前者轉(zhuǎn)移后并把尋址位清0,后者只轉(zhuǎn)移不清0尋址位。
例1 設(shè)P1為輸入口,P3.0作輸出線,執(zhí)行下列指令:
MOV C , P1.0 ;(P1.0) →C
ANL C , P1.1 ;(C)∩(P1.1) →C
ANL C , /P1.32 ;(C)∩(/P1.2) →C
MOV P3.0 , C ;C→P3.0
結(jié)果是:P3.0=(P1.0) ∩(P1.1) ∩(/P1.2)
例2 用位操作指令編程計(jì)算邏輯方程
P1.5=ACC.0 ∩ (B.0∪P1.2) ∪P1.3
解: MOV C , B.0 ;B.0→C
ORL C , P1.2 ;C∪P1.2→C 即B.0+P1.2→C
ANL C , ACC.0 ;C∩ACC.0→C 即ACC.0∩(B.0∪P1.2)→C
ORL C , P1.3 ;C∪P1.3→C 即 ACC.0∩(B.0∪P1.2)∪P1.3→C
MOV P1.5 , C ;C→P1.5
評(píng)論