註: 本文為中文翻譯,原文請見底下網址:
http://www.mikroe.com/eng/chapters/view/10/chapter-9-instruction-set/
TOC Introduction Ch. 1 Ch. 2 Ch. 3 Ch 4. Ch. 5 Ch. 6 Ch. 7 Ch. 8 Ch. 9 App. A App. B App. C
Chapter 9: Instruction Set
我們曾經提到,微控制器跟其它積體電路不同。積體電路大部分都準備好安裝到目標設備上使用,但微控制器並不是這樣。為了使微控制器可以操作,它需要精確的指令告訴它做什麼。換言之,微控制器應該執行的程式必須先撰寫好並燒錄到微控制器裏。本章涵蓋了微控制器 "認識” 的命令。16FXX 機器的指令集總共包括 35 條指令。這樣小數目的指令是 RISC 微控制器所特有的,因為 RISC 微控制器從幾個方面做過優化:運行的速度、簡潔的架構、代碼緊密小巧。 RISC 架構唯一的缺點是 programmer 得應付這些指令。
資料傳送指令
微控制器裏的資料傳送發生於工作暫存器 W (稱為累加器) 與其它暫存器之間,該暫存器表示內部 RAM 上的任何位置,不管是特殊暫存器或者是通用暫存器。
前三個指令分別為:把定字 (literal) 搬移到 W 暫存器 (MOVLW 為 move Literal to W 的縮寫),從 W 暫存器搬資料到 RAM,以及從 RAM 搬到 W 暫存器 (或搬到同一個 RAM 位置,只對 Z 旗號有影響)。指令 CLRF 清除 f 暫存器,而 CLRW 則是清除 W 暫存器。SWAPF 指令交換暫存器前後的 nibbles (一個 nibble 包含 4 個位元)。
算術邏輯指令
類似大多數的微控制器,PIC 只支援兩個算術指令 – 加法和減法。根據加法或減法的結果 C, DC, Z 旗號會自動設定,唯一的例外是 C旗號。由於減法是使用負數執行加法運算,C 旗號在減法運算後會反向。這表示如果小數減去大數 C 旗號會被設定。PIC 的邏輯 0 可以執行這些運算: AND, OR, EX-OR, 反向 (COMF) 和旋轉 (RLF 和 RRF)。
旋轉暫存器的指令實際上是經由 C 旗號向左旋轉一個位元 (朝 bit 7 旋轉) 或向右旋轉一個位元 (朝 bit 0 旋轉)。從暫存器移出來的位元會被搬到 C 旗號,而 C 旗號則會自動被搬到暫存器反方向的位元。
位元導向指令 (Bit-oriented Instructions)
BCF 和 BSF 指令清除或設定記憶體中的任何位元。雖然它似乎是一個簡單的運算,事實卻不是這樣的。CPU 首先讀出整個位元組,改變其中一個位元,然後再把整個位元組寫回同一個位置。
程式控制指令
PIC16F887 跟所有其它微控制器以同樣的方式執行 GOTO, CALL, RETURN 指令。唯一的不同是 stack 是內部 RAM 的一塊獨立的空間,而且有 8 層。'RETLW k' 指令跟 RETURN 指令是一樣的,除了一點不同,在從副程式回傳之前,指令的常數運算元會被寫到 W 暫存器。這個指令使 Lookup table 得以很容易的建立,透過建立一個當作 table 用的副程式,該副程式由 'RETLW k' 指令組成,其中定字 'k' 屬於該表格。下一步是把定字 k (0, 1, 2, 3, …n) 的位置寫到 W 暫存器,並且使用 CALL 指令呼叫副程式 (table)。下表由 k0, k1, k2, …kn 這些定字組成。
副程式的第一行 (指令 ADDWF PLC, F) 只是把 W 暫存器的內容加到 PCL,表格的起始位置儲存在 PCL 暫存器,結果是真正資料在 program memory 中的位址。在從副程式回傳之後,W 暫存器會包含定字 k 的內容,在目前的情況下是,其值為 "k2" 定字。
RETFIE (RETurn From IntErrupt) 代表從中斷服務常式返回。相較於 RETURN 指令,RETFIE 會自動設定 GIE 位元 (Global Interrupt Enable)。當發生中斷時,這個位元會自動清除。只有 program counter 被推到 stack,這意味著不會自動保存暫存器的狀態以及 STATUS 暫存器的狀態。這個問題的解法是在中斷服務常式起頭保存所有重要暫存器的內容,並在離開中斷服務常式前將這些值回原到暫存器中。
條件式跳躍是由兩個指令執行的: BTFSC 和 BTFSS。根據受測暫存器的位元狀態,決定下一個指令被略過與否。
指令執行時間
所有指令都是單一週期的指令 (single-cycle instructions)。唯一的例外是條件式分支指令 (假如有符合條件),或執行於 program counter 之上的指令。在兩種情況下,指令的執行都需要2個週期,而第二個週期則是當作在執行 NOP 指令 (No Operation)。一個指令由 4 個時脈週期 (clock cycles) 組成。如果使用 4 MHz 的振盪器,指令執行時間面值 (nominal time) 是 1 μS。在 jump 指令的情況下,指令執行時間是 2 μS。
指令 (Instructions)
圖例 (Legend)
f – 任何記憶體位 (暫存器);
W – 工作暫存器 (累加器);
b – 8 位元暫存器內的位元位址;
d – 目的位元;
[label] – 表示程式特定起始位址的 8 個字元的標記;
TOS - Top of stack;
[] – 選項;
<> - 暫存器中的位元欄 (多個位元位址);
C – STATUS 暫存器的進位/借位位元;
DC – STATUS 暫存器的數位進位元位;及
Z – STATUS 暫存器的 Zero 位元。
ADDLW - Add literal and W
語法: [label] ADDLW k
說明: W 暫存器的內容與8位元的定字相加,結果存於 W 暫存器。
運作: (W) + k -> W
運算元: 0 ≤ k ≤ 255
影響旗號: C, DC, Z
週期: 1
範例:
ADDWF - Add W and f
語法: [label] ADDWF f, d
說明: W 與 f 暫存器的內容相加。
如果d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (W) + (f) -> d
運算元: 0 ≤ f ≤ 127, d [0,1]
影響旗號: C, DC, Z
週期: 1
範例 1:
範例 2 :
ANDLW - AND literal with W
語法: [label] ANDLW k
說明: W 暫存器的內容與 8 位元的定字作 AND 運算。這表示如果相對應的位元都是 1,結果將會是 1。結果存於 W 暫存器。
運作: (W) AND k -> W
運算元: 0 ≤ k ≤ 255
影響旗號: Z
週期: 1
範例 1:
範例 2 :
ANDWF - AND W with f
語法: [label] ANDWF f,d
說明: W 暫存器與 f 暫存器作 AND 運算。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (W) AND (f) -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
BCF - Bit Clear f
語法: [label] BCF f, b
說明: 清除 f 暫存器的 b 位元。
運作: (0) -> f(b)
運算元: 0 ≤ f ≤ 127, 0 ≤ b ≤ 7
影響旗號: -
週期: 1
範例 1:
範例 2 :
BSF - Bit set f
語法: [label] BSF f,b
說明: 設定 f 暫存器的 b 位元。
運作: (1) -> f(b)
運算元: 0 ≤ f ≤ 127, 0 ≤ b ≤ 7
影響旗號: -
週期: 1
範例 1:
範例 2 :
BTFSC - Bit test f, Skip if Clear
語法: [label] BTFSC f, b
說明: 如果 f 暫存器 b 位元是0,下一個指令會略過,並且以 NOP 指令取而代之以使指令成為 2 個週期的指令。
運作: 略過下一條指令,如果 f(b) = 0
運算元: 0 ≤ f ≤ 127, 0 ≤ b ≤ 7
影響旗號:
週期: 1 或 2,取決於 b 位元
範例:
BTFSS - Bit test f, Skip if Set
語法: [label] BTFSS f, b
說明: 如果 f 暫存器 b 位元是 1,下一個指令會略過,並且以 NOP 指令取而代之以使指令成為 2 個週期的指令。
運作: 略過下一條指令,如果 f(b) = 1
運算元: 0 ≤ f ≤ 127, 0 ≤ b ≤ 7
影響旗號:
週期: 1 或 2,取決於 b 位元
範例:
CALL - Calls Subroutine
語法: [label] CALL k
說明: 呼叫 subroutine。首先下一個要執行的指令位址被推到 stack上,為 PC+1 的位址,之後 subroutine 的位址寫到 program counter。
運作: (PC) + 1 -> (Top Of Stack - TOS)
k -> PC (10 : 0), (PCLATH (4 : 3)) -> PC (12 : 11)
運算元: 0 ≤ k ≤ 2047
影響旗號:
週期: 2
範例:
CLRF - Clear f
語法: [label] CLRF f
說明: f 暫存器的內容會被清除,而 STATUS 暫存器的 Z 旗號會被設定。
運作: 0 -> f
運算元: 0 ≤ f ≤ 127
影響旗號: Z
週期: 1
範例 1:
範例 2 :
CLRW - Clear W
語法: [label] CLRW
說明: W 暫存器的內容會被清除,而 STATUS 暫存器的 Z 旗號會被設定。
運作: 0 -> W
運算元:
影響旗號: Z
週期: 1
範例:
CLRWDT - Clear Watchdog Timer
語法: [label] CLRWDT
說明: 重設 watchdog timer 和 WDT prescaler。TO 和 PD 會被設定。
運作: 0 -> WDT 0 -> WDT prescaler 1 -> TO 1 -> PD
運算元:
影響旗號: TO, PD
週期: 1
範例:
COMF - Complement f
語法: [label] COMF f, d
說明: f 暫存器的內容被做補數運算 (0 變 1,1 變 0)。
如果d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f) -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
DECF - Decrement f
語法: [label] DECF f, d
說明: f 暫存器的內容減 1。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f) - 1 -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
DECFSZ - Decrement f, Skip if 0
語法: [label] DECFSZ f, d
說明: f暫存器的內容減1。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
如果結果為 0,會以 NOP 指令取而代之以使指令成為 2 個週期的指令。
運作: (f) - 1 -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1 或 2,取決於執行結果
範例:
在這個範例中,指令區塊的執行次數會與變數 CNT 的初始值一樣,也就是 10 次。
GOTO - Unconditional Branch
語法: [label] GOTO k
說明: 無條件跳至位址 k。
運作: (k) -> PC(10:0), (PCLATH(4:3)) -> PC(12:11)
運算元: 0 ≤ k ≤ 2047
影響旗號: -
週期: 2
範例:
INCF - Increment f
語法: [label] INCF f, d
說明: f 暫存器的內容加 1。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f) + 1 -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
INCFSZ - Increment f, Skip if 0
語法: [label] INCFSZ f, d
說明: f 暫存器的內容加 1。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
如果結果為 0,會以 NOP 指令取而代之以使指令成為 2 個週期的指令
運作: (f) + 1 -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: -
週期: 1 或 2,取決於執行結果
範例:
在指令執行前 program counter 的內容為 PC=LAB_01 的位址。
在執行指令後,REG 的內容為 REG = REG+1。如果 REG=0,program counter 指到 LAB_03 的位址,不然的話,program counter 會指令下一個指令的位址,即 LAB_02 的位址。
IORLW - Inclusive OR literal with W
語法: [label] IORLW k
說明:W 暫存器的內容與 8 位元的定字 k 作 OR 運算。結果存於 W 暫存器。
運作: (W) OR (k) -> W
運算元: 0 ≤ k ≤ 255
影響旗號: -
週期: 1
範例:
IORWF - Inclusive OR W with f
語法: [label] IORWF f, d
說明:f 暫存器的內容與 W 暫存器的內容作 OR 運算。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (W) OR (f) -> d
運算元: 0 ≤ f ≤ 127, d -> [0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
MOVF - Move f
語法: [label] MOVF f, d
說明: f 暫存器的內容會被搬到運算元 d 所決定的目的地。
如果 d = w 或 d = 0,內容被搬至 W 暫存器。
如果 d = f 或 d = 1,內容被搬至 f 暫存器。
選項 d=1 是用來測試 f 暫存器的內容,因為這個指令影響 STATUS 暫存器的 Z 旗號。
運作: (f) -> d
運算元: 0 ≤ f ≤ 127, d -> [0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2 :
MOVLW - Move literal to W
語法: [label] MOVLW k
說明:8位元的定字k被搬至W暫存器。
運作: k -> (W)
運算元: 0 ≤ k ≤ 255
影響旗號: -
週期: 1
範例 1:
範例 2 :
MOVWF - Move W to f
語法: [label] MOVWF f
說明:W 暫存器的內容被搬至 f 暫存器。
運作: (W) -> f
運算元: 0 ≤ f ≤ 127
影響旗號: -
週期: 1
範例 1:
範例 2 :
NOP - No Operation
語法: [label] NOP
說明:沒有任何作用。
運作: -
運算元: -
影響旗號: -
週期: 1
範例:
RETFIE - Return from Interrupt
語法: [labels] RETFIE
說明: 從 subroutine 返回。Stack 上的內容會被 pop 出來並載入到 program counter。中斷會被啟用,透過設定 INTCON 暫存器的 GIE 位元。
運作: TOS -> PC, 1 -> GIE
運算元: -
影響旗號: -
週期: 2
範例:
RETLW - Return with literal in W
語法: [label] RETLW k
說明: 8 位元的定字 k 會載入 W 暫存器。Stack 上端的內容會被 pop 出來並載入到 program counter。
運作: (k) -> W; top of stack (TOP) -> PC
運算元: -
影響旗號: -
週期: 2
範例:
RETURN - Return from Subroutine
語法: [label] RETURN
說明: 從 subroutine 返回。Stack 上端的內容會被 pop 出來並載入到 program counter。這是 2 個週期的指令。
運作: TOS -> program counter PC.
運算元: -
影響旗號: -
週期: 2
範例:
RLF - Rotate Left f through Carry
語法: [label] RLF f, d
說明: f 暫存器的內容會經由 Carry 旗號往左旋轉一個位元。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f(n)) -> d(n+1), f(7) -> C, C -> d(0);
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: C
週期: 1
範例 1:
範例 2:
RRF - Rotate Right f through Carry
語法: [label] RRF f, d
說明: f 暫存器的內容會經由 Carry 旗號往右旋轉一個位元。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f(n)) -> d(n-1), f(0) -> C, C -> d(7);
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: C
週期: 1
範例 1:
範例 2:
SLEEP - Enter Sleep mode
語法: [label] SLEEP
說明: 微處理器進入睡眠模式,振盪器會停止。STATUS 暫存器的 PD 位元 (Power Down) 會被清除,同個暫存器的 TO 位元會被設定。WDT 和 WDT prescaler 會被清除。
運作: 0 -> WDT, 0 -> WDT prescaler, 1 -> TO, 0 -> PD
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: TO, PD
週期: 1
範例:
SUBLW - Subtract W from literal
語法: [label] SUBLW k
說明: 定字 k 減去 W 暫存器的內容,結果存於 W 暫存器。
運作: k - (W) -> W
運算元: 0 ≤ k ≤ 255
影響旗號: C, DC, Z
週期: 1
範例:
SUBWF - Subtract W from f
語法: [label] SUBWF f, d
說明: f暫存器的內容減去W暫存器的內容。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (f) - (W) -> d
運算元: 0 ≤ f ≤ 127, d [0,1]
影響旗號: C, DC, Z
週期: 1
範例:
SWAPF - Swap Nibbles in f
語法: [label] SWAPF f, d
說明: f暫存器的高 nibble 與低 nibble 交換。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: f(0:3) -> d(4:7), f(4:7) -> d(0:3);
運算元: 0 ≤ f ≤ 127, d [0,1]
影響旗號: -
週期: 1
範例 1:
範例 2:
XORLW - Exclusive OR literal with W
語法: [label] XORLW k
說明: W 暫存器內容與定字 k 作 XOR 運算。結果存於 W 暫存器。
運作: (W) .XOR. k -> W
運算元: 0 ≤ k ≤ 255
影響旗號: Z
週期: 1
範例 1:
範例 2:
XORWF - Exclusive OR W with f
語法: [label] XORWF f, d
說明: f 暫存器內容與 W 暫存器的內容作 XOR 運算。只有相對應的位元不同時位元才會被設定。
如果 d = w 或 d = 0,結果存於 W 暫存器。
如果 d = f 或 d = 1,結果存於 f 暫存器。
運作: (W) .XOR. k -> d
運算元: 0 ≤ f ≤ 127, d[0,1]
影響旗號: Z
週期: 1
範例 1:
範例 2:
除了前面的指令外,Microchip 也引進了一些其它的指令。更精確的說,它們不是指令,而是由 MPLAB 提供的巨集 (macros)。Microchip 稱它們為 "特殊指令",因為它們實際是結合現有指令而成的。
0 意見:
張貼留言