# Chaper 7 Assembly Language Programming for PIC18F: Part 2 ###### tags: `microcontroller` ## PIC18F Jump/Branch instructions #### GOTO k ( e.g. GOTO start ) - 會跳到一個 21-bit address。 - 會從 20-bit 的 k 讀進 PC 的前 20-bit 裡面,而<font color = "#F00">最後一位放 0</font> ,這樣保證 PC 裡面一定會是偶數。 #### Bcc d ( e.g. Bcc start )(這是通式) - 如果 cc 是 true 的話,會 branch 到 d (8-bit signed number )這個位置。 - 計算: PC = PC + 2 + 2 * d - 這個 instruction 是一個 <font color = "#F00">two-cycle</font> instruction 。 - 共有: 1. BC 2. BNC 3. BZ 4. BNZ 5. BN 6. BNN 7. BOV 8. BNOV :::warning 去看一下第 8 頁 ppt 的例子,計算看看會比較了解。 ::: #### BRA d ( e.g. BRA start ) - 會直接 branch 到 ( PC + 2 + 2 * d )的位置。 - d is a signed 11-bit number. ## Test, Compare, and Skip instructions ### Test Bit and Skip #### BTFSC F, b, a ( e.g. BTFSC 0x40, 5 ) - 會先檢查 F register 的第 b 個 bit ,如果是 0 就跳過下一個指令。 - 常被用在 GOTO 和 BRA 前面。 #### BTFSS F, b, a ( e.g. BTFSS 0x70, 0 ) - 會先檢查 F register 的第 b 個 bit ,如果是 1 就跳過下一個指令。 ### Compare and Skip - ⭐不會影響任何 STATUS register 的 flag 。 #### CPFSEQ F, a ( e.g. CPFSEQ 0x20 ) - 會比較 F register 和 WREG register 有沒有相等。(會透過 unsigned subtraction ) - 如果 F = WREG 就會跳過下一個指令。 #### CPFSGT F, a ( e.g. CPFSGT 0x10 ) - 會讓 F register 和 WREG register 比大小。(透過 unsigned subtraction ) - 如果 F > WREG 會跳過下一個指令。 #### CPFSLT F, a ( e.g. CPFSLT 0x70 ) - 會讓 F register 和 WREG register 比大小。(透過 unsigned subtraction ) - 如果 F < WREG 會跳過下一個指令。 ### Decrease and Skip #### DECFSNZ F, d, a ( e.g. DECFSNZ 0x30, W or DECFSNZ 0x30, F ) - 會先把 F register 中的值先減 1 ,如果結果不為 0 就會跳過下一個指令。 #### DECFSZ F, d, a ( e.g. DECFSZ 0x30, W or DECFSNZ 0x30, F ) - 會先把 F register 中的值先減 1 ,如果結果為 0 就會跳過下一個指令。 ### Increase and Skip #### INCFSNZ F, d, a ( e.g. INCFSNZ 0x40, W or INCFSNZ 0x40, F ) - 會把 F register 中的值加 1 ,如果結果不為 0 就會跳過下一個指令。 #### INCFSZ F, d, a ( e.g. INCFSZ 0x40, W or INCFSZ 0x40, F ) - 會把 F register 中的值加 1 ,如果結果為 0 就會跳過下一個指令。 :::success 這 4 個 Increase/Decrease and Skip instruction 可以用來當作一個跑 n 次的 loop 。 ::: ### Test and Skip #### TSTFSZ F, a ( e.g. TSTFSZ 0x60 ) - 會去檢查 F register ,如果其值為 0 ,就會跳過下一個指令。 :::danger 注意沒有 TSTFNZ 這個指令!!! ::: ## PIC18F Table Read/Write Instruction - 分別有四種 Table Read/Write instructions ,靠 8-bit TABLAT register 和 21-bit TBLPTR 做轉換。 ( TBALAT 就是底下的 table latch ) - TBLPTR 包含三個 register ,由 high to low 分別為: TBLPTRU TBLPTRH TBLPTRL 。 - 有兩種 instruction 去轉換 program meory and data memory : 1. Table Read ( TBLRD ) - 讓 program memory ( 16-bit ) 轉成 data memory ( 8-bit )。 - 由四種 addressing mode 實做而成( register indirect, postincrement, postdecrement, and predecrement )。 2. Table Write ( TBLWT ) - 讓 data memory ( 8-bit )轉成 program memory ( 16-bit )。 - Table operation work with data bytes.又因為 table block 只有 data 沒有 program instruction 所以他可以 start and end at any byte address. #### TBLRD* - 把 Table pointer 指到地址裡面的值,存到 Table latch 裡面。 #### TBLRD*+ - 把 Table pointer 指到地址裡面的值,存到 Table latch 裡面,然後把 Table pointer 裡面的值加 1 。 #### TBLRD*- - 把 Table pointer 指到地址裡面的值,存到 Table latch 裡面,然後把 Table pointer 裡面的值減 1 。 #### TBLRD+* - 把 Table pointer 裡面的值先加 1 ,然後把 Table pointer 指到地址裡面的值,存到 Table latch 裡面。 #### TBLWT* - 把 Table latch 裡面的值,存到現在 Table pointer 指到的地址裡面。 #### TBLWT*+ - 把 Table latch 裡面的值,存到現在 Table pointer 指到的地址裡面,然後把 Table pointer 裡面的地址加 1 。 #### TBLWT*- - 把 Table latch 裡面的值,存到現在 Table pointer 指到的地址裡面,然後把 Table pointer 裡面的地址加 1 。 #### TBLWT+* - 把 Table pointer 裡面的地址先加 1 ,然後把 Table latch 裡面的值,存到 Table pointer 加完 1 後指到的地址裡面。 :::warning 注意!!!似乎沒有 TBLRD-* and TBLWT-* ::: :::danger 我看不太懂 ppt 裡面的 example ,懂的話記得跟我講一下 QQ ::: ## PIC18F Subroutine Instructions - 包含 PUSH/POP and subroutine CALL/RETURN instructions 。 - subroutine instructions 自動使用 hardware stack 去實做; programmer 可以自己寫 software stack 去存 local variables 。 - **CALL** and **RETURN** 要 <font color = "#F00">two</font> instruction cycles 。 - **POP** and **PUSH** 要 <font color = "#F00">one</font> instruction cycle 。 - **CALL** is <font color = "#F00">two</font> words. ## PIC18F Hardware vs. Software stack ### Hardware stack - Hardware stack 是由 31 個 21-bit registers 所組成。 - ⭐ Hardware stack 不屬於 data memory 或 program memory 。 - the stack size 和 the size of PC 一樣(同為 21-bit )。 - 而 SP ( Stack Pointer )是 5-bit wide ( 00001 to 11111 )。 - " 在程式 call subroutine 時會用到 ",但是如果還要儲存 local variable 的話空間可能會不夠,所以可以使用 **software stack** 。 ### Software stack - 使用 File Select Register ( FSRs ) 來當作 SP 。 - 任何 bank 的 data registers 都可以拿來當作 software stack 的儲存位置。 - 可以由 HIGH 存到 LOW memory ( Top of stack )或 LOW 存到 HIGH memory ( Buttom of the stack )。 ### 過程 --- ![](https://i.imgur.com/VMxebry.png) 1. PC 在 0x000100 時遇到 subroutine call ,所以把下一個 0x000102 存到 STKPTR 中並把 STKPTR + 1 。 2. 再來就直接改掉 PC 中要到的位置就好了(圖中為 0x000200 )。 ## Multiplication and Division algorthms - PIC18F 只提供 unsigned multiplication instruction 其他的乘除法都不提供。 ### Signed Multiplication algorithm 設兩數字 M 和 Q 1. 如果 $M_{MSB} = 1$ ,計算 $M$ 的 two's complement 。 2. 如果 $Q_{MSB} = 1$ ,計算 $Q$ 的 two's complement 。 3. 將兩數的 n-1 bits 以 unsigned multiplication 相乘。 4. 計算 $S = M_{MSB} \oplus Q_{MSB}$ 。 5. 如果 $S = 1$ ,計算步驟 3 的 two's complement 及為答案。 ### Unsigned Division algorithm 1. 將除數和被除數做比較。 2. 如果相等,將 counter 加 1 ,然後做 (被除數 - 除數) ,將結果存於被除數的 register 中。 3. 如果 被除數 > 除數,將 counter 加 1 ,然後做 (被除數 - 除數),將結果存於被除數的 register 中。 4. 回到步驟 1 ,直到 被除數 < 餘數。 5. 當結束時, counter 裡面存的就是 quotient ,而 data register 裡面的是 remainder 。 ### Signed Division algorithm 就跟 signed multiplication 一樣只是過程變成除法而已。 :::warning 這邊要注意餘數的符號一定會和被除數相同!!! ::: ## Delay Routine - 一般的 Delay Routine 是使用作減法的 machine cycles 來實現。