2011年6月7日 星期二

Chapter 9

註: 本文為中文翻譯,原文請見底下網址:

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 得應付這些指令。

image

資料傳送指令

微控制器裏的資料傳送發生於工作暫存器 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

image  
Fig. 9-1 f Register

 

範例 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

image  
Fig. 9-2 f Register

範例 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 稱它們為 "特殊指令",因為它們實際是結合現有指令而成的。

image

0 意見: