程序狀態字組(PSW,Program Status Word) PSW里存著一些反應目前CPU執行過程的狀態.PSW如圖所示,它是在SFR里一個位元組,它包含有進位旗號(CY) 、輔助進位旗號(AC)、(在BCD運算時使用)、兩個暫存器庫選擇位元(RS1和RS0)、溢位旗號(0V)、同位元(P,parity)和兩個由使用者定義的旗號(F0和PSW.1). 進位旗號除了作算數運算的進位位元外,也當作布林代數運算的'累加器'(Boolean Accumulator).同位元(P)的作用是反應累加器內的八個位元為"1"的個數,如果P=1,則累加器內有其數個"1",若P=0則累加器內有偶數個"1".也就是偶同位(累加器為"1"的個數+P=偶數)之義.PSW的另兩個位元,CPU未使用,因此可當作一般旗號使用. 所有MCS-51族的微處理機都執行相同的指令集.MCS-51的指令集是設計給控制應用.它提供了一些快速且多種定址模式以存取內部RAM之資料,使得在這一小小的結構里更容易做位元組操作.另外指令集更支援了單一位元變數的資料型態,以幫助需要作布林代數運算的控制和邏輯系統里直接作位元運算. 定址法 定址法就是資料所在處的表示方法,MCS-51指令集之定址法有下列六種: 直接定址法--直接定址模式時,運算元是由一個八位元的位址所指定.其中只有內部記憶體(低128位元)和SFR才可以使用直接定址法. 間接定址法--間接定址法是指令指定一個暫存器,而此暫存器的內容即為運算元的位址.無論內部或外部的RAM都可以使用間接定址法.被選擇到的暫存器庫中的R0 、 R1和堆疊指標(SP)可當作此8位元位址之暫存器.16位元的位址站存器只能使用16位元的"資料指標"暫存器,DPTR. 暫存器指令--暫存器庫內的R0至R7暫存器,可以被某些指令直接定址,其定址法是由指令的運算碼(OP Code)里的3個位元所指定,使用這種指定法去存取暫存器會使得指令碼減少,而顯得相當有效率,因為這種方法減少了一個位元組的位址位元組.當執行這種指令時,被選擇到的暫存器庫中的一個暫存器的資料會被存取.但四組暫存器庫可以在程序執行時由PSW里的兩個位元加以選擇. 暫存器指定指令--有些指令只針對所指定的暫存器運作,例如:有些指令,只操作累加器或資料指標(DPTR)等,因此就不須位址位元組去定址它,只要運算碼本身就可以指到它了 立即常數--在程序記憶體里一個常數的值可以緊跟在操作碼之後,例如:將一個十進位100這個值載入累加器中,也可以使用十六進位64H. 索引定址法--只有程序記憶體可以使用索引定址法,且只能讀入.這種定址法的最主要用途是作為程序記憶體查表.此法是以16位元的基底暫存器( DPTR或程序計數器PC)指到表的基底,而累加器則指出表的進入點.也就是進入程序記憶體的表的位址是將累加器的值加上基底指標的值所組成. 另一個索引定址的型式是使用在"條件跳躍指令",在此情況下跳躍指令的目的位址是由基底指標加上累加器的值所計算出的值. ADD A,7FH 直接定址 7FH代表數據所在之內部RAM地址 | ADD A,@R0 間接定址 R0內所存的是數據所在之內部RAM地址,間接定址須加"@"符號 | ADD A,R7 緩存器定址 可使用R0至R7,數據在緩存器中 | ADD A,#127 立即定址 127為要運算的數據,閑接定址須加"#"符號 | INC指令可以直接操作16位元的資料指標.而資料指標是用來產生16位元的外部資料記憶體位址,因此可以直接對16位元的暫存器加1是很有用的功能. MUL AB指令是將累加器的內容乘上B暫存器的內容,且將16位元的乘積的低8位元放到A,高8位元放到B中. DA A指令是用在BCD算術運算;在作BCD運算時,ADD和ADDC指令之後必須緊跟著DA A指令,以保證運算后的結果也是BCD,請特別注意DA A指令並不能直將一個二進位數字轉換成BCD碼.DA A指令只有在執行兩個BCD碼的加算后再執行才有意義. 邏輯運算指令 | 指令 | 說明 | 周期 | ANL A,Rn | A←A and Rn | 12 | ANL A,direct | A←A and direct | 12 | ANL A,@Ri | A←A and Ri | 12 | ANL A,#data | A←A and data | 12 | ANL direct,A | direct←direct and A | 12 | ANL direct,#data | direct←direct and data | 24 | ORL A,Rn | A←A or Rn | 12 | ORL A,direct | A←A or direct | 12 | ORL A,Rn | A←A or Rn | 12 | ORL A,@Ri | A←A or Ri | 12 | ORL A,#data | A←A or data | 12 | ORL direct,A | direct←direct or A | 12 | ORL direct,#data | direct←direct or data | 24 | XRL A,Rn | A←A xor Rn | 12 | XRL A,direct | A←A xor direct | 12 | XRL A,@Ri | A←A xor Ri | 12 | XRL A,#data | A←A xor data | 12 | XRL direct,A | direct←direct xor A | 12 | XRL direct,#data | direct←direct xor data | 12 | CLR A | 清除累加器 | 12 | CPL A | 累加器反相 | 12 | RL A | 累加器向左旋轉 | 12 | RLC A | 累加器和C左旋 | 12 | RR A | 累加器向右旋轉 | 12 | RRC A | 累加器和C右旋 | 12 | 這些指令是以位元組裡的位元對位元執行邏輯運算,例如:累加器的內容為01010101B而<byte>的內容為10101010B,則ANL A,<byte>會使得累加器的內容變成00000000B 。 請注意:在內部資料記憶空間里的任一位元組都可直接執行邏輯運算,而不需透過累加器。如XRL <byte>,#data這個指令可以提供很快速得將P1上的位元資料做轉換,例如: XRL P1,#0FFH 旋轉指令( RL A、RLC A等)將累加器位移1位元至左邊或右邊,對一個左旋轉指令是將MSB轉至LSB之位置,而右旋轉指令將LSB轉至MSB位置。 SWAP A指令是將累加器的高4位元和低4位元的資料交換,這對於BCD的操作相當有用. 若累加器的內容為一個二進位數字,且已知其值小於十進位之100,則它可以很快地用如下列程序轉換成BCD碼: MOV B,#10 DIV A,B SWAP A ADD A,B 將其除已10,會使得10位數落在累加器的低4位里,其各位數則在B緩存器里,而SWAP和ADD指令則十位數移到高4位而個位數則移至4位。 | 數據轉移指令 | 指令 | 說明 | 周期 | MOV A,Rn | A←Rn | 12 | MOV A,direct | A←direct | 12 | MOV A,@Ri | A←Ri | 12 | MOV A,#data | A←data | 12 | MOV Rn,A | Rn←A | 12 | MOV Rn,direct | Rn←direct | 24 | MOV Rn,#data | Rn←data | 12 | MOV direct,A | direct←A | 12 | MOV direct,Rn | direct←Rn | 24 | MOV direct,direct | direct←direct | 24 | MOV direct,@Ri | direct←Ri | 24 | MOV direct,#data | direct←data | 24 | MOV @Ri,A | Ri←A | 12 | MOV @Ri,direct | Ri←direct | 24 | MOV @Ri,#data | Ri←data | 12 | MOV DPTR,#data 16 | Ri←16bit data | 24 | MOVC A,@A+DPTR | A←程序內存的數據 | 24 | MOVC A,@A+PC | A←程序內存的數據 | 24 | MOVX A,@Ri | A←外部RAM的數據(8bit地址) | 24 | MOVX A,@DPTR | A←外部RAM的數據(16bit地址) | 24 | MOVX @Ri,A | 外部的RAM(8bit)←A | 24 | MOVX @DPTR,A | 外部的RAM(16bit)←A | 24 | PUSH direc | 推迭區←direct | 24 | POP direc | direct←堆棧區 | 24 | XCH A,Rn | A和Rn互換 | 12 | XCH A,direct | A和direct互換 | 12 | 資料轉移 SFR內的暫存器則只能使用直接定址法。注意到所有MCS-51的堆疊區都是晶元內部的RAM里,PUSH指令首先將堆疊指標(SP)加1,然後將一個位元組拷貝進去堆疊區。 PUSH和POP都只能使用直接定址法來指出被存入或取出的位元組,但是堆疊本身只能使用SP暫存器的間接定址法加以存取。這意思是說,堆疊區可以使用較高的128位元組,如果他們有的話,但卻不是在SFR空間里。在8051、80C51BH;或內部沒有ROM的8031或EPROM版本的8751都沒有較高的128位元組的RAM,使用這些版本時,如果SP指向較高128位元組時,若PUSH一個位元組,此資料將遺失,而POP一個位元組時將會得到一個不確定的資料。 資料轉移指令里包含了一個16位元的MOV,它可以用來設定資料指標(DPTR)的初值,以當作在程序記憶體查表支用,或作為16位元的外部資料記憶存取。 XCH A,<byte>指令可以將累加器的內容與被定址到位元組的內容互換。 XCHD A,@Ri指令也類似,只不過是交換其中的低4位元(Low Nibble)。 外部RAM 外部資料記憶體資料轉移指令,只能使用間接定址法。但有兩種方式可供選擇,那就是使用單位元組定址或是兩位元組定址,單位元組位址的產生是使用暫存器庫中的R0或R1。雙位元組位址則由DPTR所產生。使用16位元位址較不方便的地方是,假如只有幾K位元組的外部RAM時,16位元不只是使用了介面2里的所有八位元當作位址匯流排。然而,使用八位元的位址也可以定址到幾K位元組的外部RAM,而不須使用介面2的所有位元。請注意:所有的外部資料存取時,累加器都是當作指令資料的目的地(destination)或來源地(source)。對外部RAM的讀(RD)和寫(WR)的激發信號只有在執行MOVX指令時會動作,在一般情形下這些信號不會動作。事實上如果RD和WR不再使用時,這些腳還可以當作額外的I/O現使用。 讀取在程序記憶體的查表指令 這些指令只讀取程序記憶體的資料,因此表中的資料只能被讀而不能更改。其中MOVC是"MOVE constant"的意思。如果要讀的表是再外部的程序記憶體時,則讀取的激發信號是PSEN。第一個MOVC指令中容納256位元的表,即OOH至FFH。首先將想要進入的位址在載入累加器中,再將資料指標設定指到表的開始點,然後執行: MOVC A,@A+DPTR就會將想要的值載入累加器。 另一個MOVC指令的動作情形也相同,只不過是使用程序計數器(PC)當作表的基底,因此這個表就要透過副程序加以讀取。首先將想要進入的位址載入累加器,然後作一個副程序呼叫。 MOV A,ETRY_NUMBER CALL TABLE 而副程序"TABLE"的寫法就像這樣: TABLE:MOVC A,@A+PC RET DB 23H DB 45H 這個表本身緊跟著一個RET指令,因此這種型式的表只能有255位元組,即從1到255,其中0不可以使用,因為執行MOVC指令時,PC的內容是RET這個指令的位址,所以讀到的值會是RET的機械碼。 布爾運算指令 | 指令 | 說明 | 周期 | CLR C | 清除進位旗標 | 12 | CLR bit | 清除直接位 | 12 | SETB C | 設定進位旗標 | 12 | SETB bit | 設定直接位 | 12 | CPL C | 進位旗標反相 | 12 | CPL bit | 直接位反相 | 12 | ANL C,bit | C←C and bit | 24 | ANL C,/bit | C←C and bit(反相) | 24 | ORL C,bit | C←C or bit | 24 | ORL C,/bit | C←C or bit(反相) | 24 | MOV C,bit | C←bit | 12 | MOV bit,C | bit←C | 24 | JC rel | 若C=1跳至rel | 24 | JNC rel | 若C=0跳至rel | 24 | JB bit,rel | 若bit=1跳至rel | 24 | JNB bit,rel | 若bit=0跳至rel | 24 | JBC bit,rel | 若bit=1跳至rel,且清除此位 | 24 | 布林指令 MCS-51內部包含有一完整的布林(單一位元)指令。在內部RAM有128個可定址位元,而SFR也提供了另128個可定址位元。因此所有I/O介面的位元都是可定址位元,且都可被當成分開的單位元介面。這些指令存取這些位元不僅只條件式跳躍指令,還有完整的轉移(move)、設定(set)、清除(clear)、取補數(complement)、OR和AND指令。所以這些指令在八位元的微處理器里是很難能可貴的布林處理器的指令集如表所示。表中所有位元資料的存取都是使用直接定址法。位元位址00H至7FH是在內部RAM的較低128位元里,而位元位址80H至FFH是在SFR里。 請看:將一個內部的旗號轉移至I/O介面的接腳上是多容易: MOV C,FLAG MOV P1.0,C 在這個例子里,FLAG是在較低128位元或SFR里的可定址位元,而I/O線上的信好是設定或清除就決定旗號位元"1"或"0"。在PSW里的進位旗號(C)位元就當作布林處理器的單位元累加器。而進位位元是個直接位址,因為它是在PSW裡面的一個位元,且是個可定址位元。 |