# 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 )。
### 過程
---

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 來實現。