# 微處理機概論_期中檢討
## 1. 第一大題
> Rewrite the UART Program in Sec. 16.2.5 by using full descending stack for subroutine UARTconfig and empty descending stack for subroutine Transmit (both with initial stack pointer 0x40000020, to STM and LDM in the subroutine)
### (1).
- (a) to configure the UART 5 data bits, even parity, 2 stop bits, a Baud rate if the UART is to generate a serial signal at a Baud rate of 12800 Baud using 48 MHz, and show the results in the window of UART0 after execution.
- (b) calculate the system clock frequency from the window of UART0 in (a).
- to configure the UART 8 data bits, odd parity, 1 stop bits, a Baud rate if the UART is to generate a serial signal at a Baud rate of 12800 Baud using Keil Tool LPC 2104 CPU frequency and show the above results in the window of UART0 after execution.
#### (a)
> 依照第33行的數值來設定 UART 板子的設定
> 依題目所述須設定 `5 data bits, even parity, 2 stop bits` 則可知為`10011100` = `0x9C`
> 注意 Divisor Latch Access 為 1,Break Control 為 0
> 由於本題敘述是要使用 `full descending stack` 所以要使用 `STBDB` 和 `LDMIA` 來達成
**用於解釋 `STBDB` & `LDMIA` 的程式碼**
```assembly=
my_function:
STMDB sp!, {r4-r7, lr} ; 將寄存器 r4、r5、r6、r7 和返回地址 lr 壓入堆疊
; 函數的其他操作...
LDMIA sp!, {r4-r7, pc} ; 將寄存器 r4、r5、r6、r7 和返回地址 lr 從堆疊彈出,並返回
```
STMDB sp!, {r4-r7, lr} 指令將寄存器 r4、r5、r6、r7 和返回地址 lr 的值壓入堆疊。由於我們使用了 !,堆疊指針 sp 在執行指令前會先減少,然後再壓入數值
LDMIA sp!, {r4-r7, pc} 指令將寄存器 r4、r5、r6、r7 和返回地址 lr 的值從堆疊彈出。同樣,由於我們使用了 !,堆疊指針 sp 在執行指令前會先減少,然後再彈出數值,確保了完全降序的堆疊操作。

```assembly=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
LDR r1, =CharData ; starting address of characters
ADD r1, #28 ; TKU-ECE 411446510 TsaiPingCen has 29 character
MOV r2, #29 ; to print string times
Loop
LDRB r0, [r1], #-1 ; load character, increment address
CMP r2, #0 ; null terminated
SUB r2, #1
BLNE Transmit ; send character to UART
BNE Loop ; contiune if not a '0'
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x9C
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xEA ; 9400 baud @15 MHz VPB clock
STRB r6, [r5]
MOV r6, #0x1C ; set DLAB=0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
CharData
DCB "TKU-ECE 411446510 TsaiPingCen", 0
END
```
#### (b)
System clock frequency = 234 x 16 x 801 = 2,998,994
#### (c)
> 依照第33行的數值來設定 UART 板子的設定
> 依題目所述須設定 `8 data bits, odd parity, 1 stop bits` 則可知為`10011100` = `0x9C`
> 注意 Divisor Latch Access 為 1,Break Control 為 0
```asm=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
LDR r1, =CharData ; starting address of characters
ADD r1, #28 ; TKU-ECE 411446510 TsaiPingCen has 29 character
MOV r2, #29 ; to print string times
Loop
LDRB r0, [r1], #-1 ; load character, increment address
CMP r2, #0 ; null terminated
SUB r2, #1
BLNE Transmit ; send character to UART
BNE Loop ; contiune if not a '0'
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x8B ; set 8 bits, odd parity, 1 stop bit
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xF ; 12800 baud @3 MHz VPB clock
STRB r6, [r5]
MOV r6, #0xB ; set DLAB = 0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
CharData
DCB "TKU-ECE 411446510 TsaiPingCen", 0
END
```
### (2).
> to include the declaration of the string “(ID-Name)-Midterm Exam in Spring 2024!” as variable StudentData. Use calls to subroutine Transmit to do the following 3 steps
- (a) display reversely the string and continuously the
- (b) display reversely the string characters in multiple-of-3 positions (assuming the last character starts from position 0)
- (c) display reversely the string “words”
> in the UART #1 window after program executions (a) by using F5 (Run), F10 (Step over) and F11 (Step) respectively (b&c) by using F5 (Run) only.
#### (a)
> 第(a)題目先輸出反向字串再輸入正常字串
> ex: (411446510-Tsai)-Midterm Exam in Spring 2024!
> 輸出反向字串主要先跳到最後面的字串然後再將從最後面 `位移-1` 輸出
> (F5)的結果會全部輸出出來
> (F10)的結果會有兩個值無法輸出
> (F11)沒有模擬輸出端
```asm=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start ; 411446510 Tsai Ping Cen
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
LDR r1, =StudentData ; starting address of characters
ADD r1, #44 ;
MOV r2, #45 ; to print string times
Loop1
LDRB r0, [r1], #-1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop1 ; contiune if not a '0'
LDR r1, =StudentData
Loop
LDRB r0, [r1], #1
CMP r0, #0
BLNE Transmit
BNE Loop
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x8B ; set 8 bits, odd parity, 1 stop bit
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xF ; 12800 baud @3 MHz VPB clock
STRB r6, [r5]
MOV r6, #0xB ; set DLAB = 0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
StudentData
DCB "(411446510-Tsai)-Midterm Exam in Spring 2024!", 0
END
```
#### (b)
> 一樣先跳到字串最後的位置,然後以每次 `位移-3` 的方式輸出
```asm=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start ; 411446510 Tsai Ping Cen
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
LDR r1, =StudentData ; starting address of characters
ADD r1, #44 ;
SUB r1, #3
MOV r2, #14
Loop1
LDRB r0, [r1], #-3 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop1 ; contiune if not a '0'
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x8B ; set 8 bits, odd parity, 1 stop bit
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xF ; 12800 baud @3 MHz VPB clock
STRB r6, [r5]
MOV r6, #0xB ; set DLAB = 0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
StudentData
DCB "(411446510-Tsai)-Midterm Exam in Spring 2024!", 0
END
```
#### (C)
> 將每一個字串分開分析並印出
```asm=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start ; 411446510 Tsai Ping Cen
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
; !
LDR r1, =StudentData ; starting address of characters
ADD r1, #44
LDRB r0, [r1] ; load character, increment address
BL Transmit
; 2024
LDR r1, =StudentData
ADD r1, #40
MOV r2, #4
Loop1 ; 411446510 Tsai Ping Cen
LDRB r0, [r1], #1
CMP r2, #0
BLNE Transmit
SUB r2, #1
BNE Loop1
; blank
LDR r1, =StudentData
ADD r1, #39
LDRB r0, [r1]
BL Transmit
; Spring
LDR r1, =StudentData
ADD r1, #33
MOV r2, #6
Loop2
LDRB r0, [r1], #1
CMP r2, #0
BLNE Transmit
SUB r2, #1
BNE Loop2
; blank
LDR r1, =StudentData
ADD r1, #32
LDRB r0, [r1]
BL Transmit
; 411446510 Tsai Ping Cen
; in
LDR r1, =StudentData
ADD r1, #30
MOV r2, #2
Loop3
LDRB r0, [r1], #1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop3 ; contiune if not a '0'
; blank
LDR r1, =StudentData
ADD r1, #29
LDRB r0, [r1]
BL Transmit
; 411446510 Tsai Ping Cen
; Exam
LDR r1, =StudentData
ADD r1, #25
MOV r2, #4
Loop4
LDRB r0, [r1], #1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop4 ; contiune if not a '0'
; blank
LDR r1, =StudentData
ADD r1, #24
LDRB r0, [r1]
BL Transmit
; 411446510 Tsai Ping Cen
; Midterm
LDR r1, =StudentData
ADD r1, #17
MOV r2, #7
Loop5
LDRB r0, [r1], #1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop5 ; contiune if not a '0'
; -
LDR r1, =StudentData
ADD r1, #16
LDRB r0, [r1]
BL Transmit
; )
LDR r1, =StudentData
ADD r1, #15
LDRB r0, [r1]
BL Transmit
; 411446510 Tsai Ping Cen
; Tsai
LDR r1, =StudentData
ADD r1, #11
MOV r2, #4
Loop6
LDRB r0, [r1], #1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop6 ; contiune if not a '0'
; -
LDR r1, =StudentData
ADD r1, #10
LDRB r0, [r1]
BL Transmit
; 411446510
LDR r1, =StudentData
ADD r1, #1
MOV r2, #9
Loop7
LDRB r0, [r1], #1 ; load character, increment address
CMP r2, #0 ; null terminated
BLNE Transmit ; send character to UART
SUB r2, #1
BNE Loop7 ; contiune if not a '0'
; 411446510 Tsai Ping Cen
; (
LDR r1, =StudentData
ADD r1, #0
LDRB r0, [r1]
BL Transmit
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x8B ; set 8 bits, odd parity, 1 stop bit
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xF ; 12800 baud @3 MHz VPB clock
STRB r6, [r5]
MOV r6, #0xB ; set DLAB = 0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
StudentData
DCB "(411446510-Tsai)-Midterm Exam in Spring 2024!", 0
END
```
### (3).
> to include subroutines Receive (using empty ascending stack with initial stack pointer 0x40000020, to STM and LDM in the subroutine) to receive an error-free byte data from the receiver buffer register to R1.
- (a) to copy the string (variable StudentData) reversely to memory starting from address 0x40000070.
- (b) to use calls to subroutine Transmit to display a sequence of 10 characters at memory address 0x40000078 in the UART #1 window after program execution by using F5 (Run).
- (c) to use calls to subroutine Receive to receive a sequence of error-free 20 characters from the UART0 and put them in memory starting from address 0x400000A0. (Show execution results by using F10 (Step over) and F11 (Step).)
> (Be sure to show and explain in Problem (2)&(3) the Line Status results in the UART0 window and the output in the UART #1 window after execution. Also, be sure to highlight the stack elements with the related registers stored for subroutines Receive and Transmit.)
#### (a), (b), (c)
> (a) 將要印出的字串存放在位置 `0x40000070` 這個位置
> (b) 將要印出的字串存放在位置 `0x40000078` 並且只存放 20 筆資料
> (c) 將要印出的字串存放在位置 `0x400000A0` 並且只存放 20 筆資料,另外 "Error-free" 在這個上下文中指的是在傳輸過程中沒有出現錯誤或損壞的資料。在通過UART0接收資料時,"error-free 20 characters" 意味著接收到的資料序列應該是連續的、完整的。
>
```asm=
AREA UARTDEMO, CODE, READONLY
PINSEL0 EQU 0XE002C000 ; controls the function of pins
U0START EQU 0xE000C000 ; start of UART0 register
LCR0 EQU 0xC ; line control register for UART0
LSR0 EQU 0x14 ; line status register for UART0
RAMSTART EQU 0x40000020 ; start of onboard RAM for 2104
ENTRY
start ; 411446510 Tsai Ping Cen
LDR sp, =RAMSTART ; set up stack pointer
BL UARTConfig ; initialize/configure UART0
LDR r1, =StudentData ; starting address of characters
; 1-(3)-(a)
LDR r3, =0x40000070
LDR r1, =StudentData
ADD r1, #44
MOV r2, #45
MOV r4, #0
Loop
LDRB r5, [r1], #-1
STRB r5, [r3], #1
SUB r2, #1
CMP r2, #0
STRB r4, [r3]
BNE Loop
; 1-(3)-(b)
LDR r1, =0x40000078
MOV r2, #10
Loop1
LDRB r0, [r1], #1
CMP r2, #0
BLNE Transmit
SUB r2, #1
BNE Loop1
; 1-(3)-(c)
MOV r9, #20
LDR r1, =0x400000A0
Loop2
BL Receive
STRB r1, [r0], #1
SUBS r9, r9, #1
BNE Loop2
done B done
; full descending stack
UARTConfig ; 411446510 Tsai Ping Cen
STMDB sp!, {r5, r6, LR}
LDR r5, =PINSEL0 ; base address of register
LDR r6, [r5] ; get contents
BIC r6, r6, #0xF ; clear out lower nibble
ORR r6, r6, #0x5 ; sets p0.0 to Tx0 and P0.1 to Rx0
STR r6, [r5]
LDR r5, =U0START
MOV r6, #0x8B ; set 8 bits, odd parity, 1 stop bit
STRB r6, [r5, #LCR0] ; write control byte to LCR
MOV r6, #0xF ; 12800 baud @3 MHz VPB clock
STRB r6, [r5]
MOV r6, #0xB ; set DLAB = 0
STRB r6, [r5, #LCR0] ; Tx and Rx buffers set up
LDMIA sp!, {r5, r6, PC}
Transmit
STMDA sp!, {r5, r6, LR}
LDR r5, =U0START
wait
LDRB r6, [r5, #LSR0] ; get staus of buffer
TST r6, #0x20 ; buffer empty?
BEQ wait ; spin until buffer's empty
STRB r0, [r5]
LDMIB sp!, {r5, r6, PC}
Receive
STMIA sp!, {r5, r6, LR}
LDR r5, =U0START
wait1
LDRB r6, [r5, #LSR0]
TST r6, #1
BEQ wait1
TST r6, #0xE
LDRB r1, [r5]
BNE wait1
LDMDB sp!, {r5, r6, PC}
; 411446510 Tsai Ping Cen
StudentData
DCB "(411446510-Tsai)-Midterm Exam in Spring 2024!", 0
END
```
## 2. 第二大題
Rewrite Program 15-1 to include the following 2 declarations and
MSG_with_Error DCB “DIVIDE-BY-0 Happened!”, 0
MSG_without_Error DCB “DIVIDE-BY-0 Not Happened!”, 0
### (1).
> check the usage fault status register, write string MSG_with_Error to memory with starting address 0x20000030 if a divide-by-zero has taken place, and write string MSG_without_Error to memory with starting address 0x20000090 if a divide-by-zero has not taken place.
> (Be sure to show the first step (stacking) in the entry sequence upon processor exception and give the type of the stack used here.)
> 檢查使用錯誤狀態寄存器(Usage Fault Status Register),如果發生了除以零的錯誤,則將字符串 "MSG_with_Error" 寫入到記憶體,起始地址為 0x20000030;如果沒有發生除以零的錯誤,則將字符串 "MSG_without_Error" 寫入到記憶體,起始地址為 0x20000090。
```asm=
Stack EQU 0x00000100
DivbyZ EQU 0xD14
SYSHNDCTRL EQU 0xD24
Usagefault EQU 0xD2A
NVICBase EQU 0xE000E000
AREA STACK, NOINIT, READWRITE, ALIGN = 3
StackMem
SPACE Stack
PRESERVE8
AREA RESET, CODE, READONLY
THUMB
DCD StackMem+Stack
DCD Reset_Handler
DCD NmiISR
DCD FaultISR
DCD IntDefaultHandler
DCD IntDefaultHandler
DCD IntDefaultHandler
EXPORT Reset_Handler
ENTRY
Reset_Handler
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
;base: 0xE000E000
;offset: 0xD14
;bit: 4
LDR r6, =NVICBase
LDR r7, =DivbyZ
LDR r1, [r6, r7]
ORR r1, #0x10 ;enable bit 4
STR r1, [r6, r7]
;turn on the usage fault exception
LDR r7, =SYSHNDCTRL
LDR r1, [r6, r7]
ORR r1, #0x40000
STR r1, [r6, r7]
;try out a divide by 2 then a divide by 0!
MOV r0, #0
MOV r1, #0x11111111
MOV r2, #0x22222222
MOV r3, #0x33333333
;this divide works just fine
UDIV r4, r2, r1
;this divide takes an exception
UDIV r5, r3, r0
Exit B Exit
NmiISR B NmiISR
FaultISR B FaultISR
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200
BNE Happened
BEQ NotHappened
Happened
LDR r3, =MSG_with_Error
LDR r1, =0x20000030 ; starting address of characters
Loop
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
BX LR
NotHappened
LDR r3, =MSG_without_Error
LDR r1, =0x20000090 ; starting address of characters
Loop2
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop2
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
BX LR
LDRNE r9, =0xDEADDEAD
;r1 should have bits 9 set indicating
;a divide-by-zero has taken place
done B done
MSG_with_Error
DCB "DIVIDE-BY-0 Happened!", 0
MSG_without_Error
DCB "DIVIDE-BY-0 Not Happened", 0
END
```
### (2) to switch modes and show the mode changes
>(a) from privileged thread mode to unprivileged thread mode
(b) from privileged thread mode to privileged handler mode
(c) from privileged handler mode to privileged thread mode
(d) from privileged handler mode to unprivileged thread mode
> 如果跑到IntDefaultHandler分支的話,修改模式從 Privileged thread mode 改為 privileged Handler mode
pivileged handler mode => 中斷服務程式
privileged thread mode => 被中斷服務程式
```asm=
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200 ; read bit 9 of the Usage Fault Status Register
done B done ; 若改為 `BX LR` 將會回去出錯的地方
```
> 若放在 `thread mode` 的地方,則`privileged -> unprivileged`
```asm=
IntDefaultHandler
; switch to user Thread mode
; 若放在thread mode
MRS r8, CONTROL
ORR r8, r8, #1
MSR CONTROL, r8
BX LR ; 回去被中斷的地方
```

(a)
> 將原本的 `privileged` 更改為 `ununprivileged` 加入第27行的程式碼即可以更改,注意因為調整為`unprivileged` 存取系統傳存器,這是一種 Hard fault,所以執行此程式碼會跳到 FaultISR。

```asm=
Stack EQU 0x00000100
DivbyZ EQU 0xD14
SYSHNDCTRL EQU 0xD24
Usagefault EQU 0xD2A
NVICBase EQU 0xE000E000
AREA STACK, NOINIT, READWRITE, ALIGN = 3
StackMem
SPACE Stack
PRESERVE8
AREA RESET, CODE, READONLY
THUMB
DCD StackMem + Stack
DCD Reset_Handler
DCD NmiISR
DCD FaultISR
DCD IntDefaultHandler
DCD IntDefaultHandler ; MPU Fault Handler
DCD IntDefaultHandler ; Usage Fault Handler
EXPORT Reset_Handler
ENTRY
Reset_Handler
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
; 411446510 Tsai Ping Cen
;base: 0xE000E000
;offset: 0xD14
;bit: 4
LDR r6, =NVICBase
LDR r7, =DivbyZ
LDR r1, [r6, r7]
ORR r1, #0x10 ;enable bit 4
STR r1, [r6, r7]
;turn on the usage fault exception
LDR r7, =SYSHNDCTRL
LDR r1, [r6, r7]
ORR r1, #0x40000
STR r1, [r6, r7]
;try out a divide by 2 then a divide by 0!
MOV r0, #0
MOV r1, #0x11111111
MOV r2, #0x22222222
MOV r3, #0x33333333
;this divide works just fine
UDIV r4, r2, r1
;this divide takes an exception
UDIV r5, r3, r0
Exit B Exit
NmiISR B NmiISR
FaultISR B FaultISR
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200
BNE Happened
BEQ NotHappened
Happened
LDR r3, =MSG_with_Error
LDR r1, =0x20000030 ; starting address of characters
Loop
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop
;MRS r8, CONTROL
;ORR r8, #1
;MSR CONTROL, r8
; 411446510 Tsai Ping Cen
BX LR
NotHappened
LDR r3, =MSG_without_Error
LDR r1, =0x20000090 ; starting address of characters
Loop2
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop2
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
BX LR
;r1 should have bits 9 set indicating
;a divide-by-zero has taken place
done B done
MSG_with_Error
DCB "DIVIDE-BY-0 Happened!", 0
MSG_without_Error
DCB "DIVIDE-BY-0 Not Happened", 0
ALIGN
END
```
(b)
>
```asm=
Stack EQU 0x00000100
DivbyZ EQU 0xD14
SYSHNDCTRL EQU 0xD24
Usagefault EQU 0xD2A
NVICBase EQU 0xE000E000
AREA STACK, NOINIT, READWRITE, ALIGN = 3
StackMem
SPACE Stack
PRESERVE8
AREA RESET, CODE, READONLY
THUMB
DCD StackMem + Stack
DCD Reset_Handler
DCD NmiISR
DCD FaultISR
DCD IntDefaultHandler
DCD IntDefaultHandler ; MPU Fault Handler
DCD IntDefaultHandler ; Usage Fault Handler
EXPORT Reset_Handler
ENTRY
Reset_Handler
; 411446510 Tsai Ping Cen
;base: 0xE000E000
;offset: 0xD14
;bit: 4
LDR r6, =NVICBase
LDR r7, =DivbyZ
LDR r1, [r6, r7]
ORR r1, #0x10 ;enable bit 4
STR r1, [r6, r7]
;turn on the usage fault exception
LDR r7, =SYSHNDCTRL
LDR r1, [r6, r7]
ORR r1, #0x40000
STR r1, [r6, r7]
;try out a divide by 2 then a divide by 0!
MOV r0, #0
MOV r1, #0x11111111
MOV r2, #0x22222222
MOV r3, #0x33333333
;this divide works just fine
UDIV r4, r2, r1
;this divide takes an exception
UDIV r5, r3, r0
; 411446510 Tsai Ping Cen
Exit B Exit
NmiISR B NmiISR
FaultISR B FaultISR
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200
BNE Happened
BEQ NotHappened
Happened
LDR r3, =MSG_with_Error
LDR r1, =0x20000030 ; starting address of characters
Loop
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
; 411446510 Tsai Ping Cen
BX LR
NotHappened
LDR r3, =MSG_without_Error
LDR r1, =0x20000090 ; starting address of characters
Loop2
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop2
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
BX LR
;r1 should have bits 9 set indicating
;a divide-by-zero has taken place
done B done
MSG_with_Error
DCB "DIVIDE-BY-0 Happened!", 0
MSG_without_Error
DCB "DIVIDE-BY-0 Not Happened", 0
ALIGN
END
```
(c)
```asm=
Stack EQU 0x00000100
DivbyZ EQU 0xD14
SYSHNDCTRL EQU 0xD24
Usagefault EQU 0xD2A
NVICBase EQU 0xE000E000
AREA STACK, NOINIT, READWRITE, ALIGN = 3
StackMem
SPACE Stack
PRESERVE8
AREA RESET, CODE, READONLY
THUMB
DCD StackMem + Stack
DCD Reset_Handler
DCD NmiISR
DCD FaultISR
DCD IntDefaultHandler
DCD IntDefaultHandler ; MPU Fault Handler
DCD IntDefaultHandler ; Usage Fault Handler
EXPORT Reset_Handler
ENTRY
Reset_Handler
; 411446510 Tsai Ping Cen
;base: 0xE000E000
;offset: 0xD14
;bit: 4
LDR r6, =NVICBase
LDR r7, =DivbyZ
LDR r1, [r6, r7]
ORR r1, #0x10 ;enable bit 4
STR r1, [r6, r7]
;turn on the usage fault exception
LDR r7, =SYSHNDCTRL
LDR r1, [r6, r7]
ORR r1, #0x40000
STR r1, [r6, r7]
;try out a divide by 2 then a divide by 0!
MOV r0, #0
MOV r1, #0x11111111
MOV r2, #0x22222222
MOV r3, #0x33333333
;this divide works just fine
UDIV r4, r2, r1
;this divide takes an exception
UDIV r5, r3, r0
; 411446510 Tsai Ping Cen
Exit B Exit
NmiISR B NmiISR
FaultISR B FaultISR
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200
BNE Happened
BEQ NotHappened
Happened
LDR r3, =MSG_with_Error
LDR r1, =0x20000030 ; starting address of characters
Loop
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
; 411446510 Tsai Ping Cen
BX LR
NotHappened
LDR r3, =MSG_without_Error
LDR r1, =0x20000090 ; starting address of characters
Loop2
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop2
;MRS r8, CONTROL
;ORR r8, #1
;MSR CONTROL, r8
BX LR
;r1 should have bits 9 set indicating
;a divide-by-zero has taken place
done B done
MSG_with_Error
DCB "DIVIDE-BY-0 Happened!", 0
MSG_without_Error
DCB "DIVIDE-BY-0 Not Happened", 0
ALIGN
END
```
(d)
```asm=
Stack EQU 0x00000100
DivbyZ EQU 0xD14
SYSHNDCTRL EQU 0xD24
Usagefault EQU 0xD2A
NVICBase EQU 0xE000E000
AREA STACK, NOINIT, READWRITE, ALIGN = 3
StackMem
SPACE Stack
PRESERVE8
AREA RESET, CODE, READONLY
THUMB
DCD StackMem + Stack
DCD Reset_Handler
DCD NmiISR
DCD FaultISR
DCD IntDefaultHandler
DCD IntDefaultHandler ; MPU Fault Handler
DCD IntDefaultHandler ; Usage Fault Handler
EXPORT Reset_Handler
ENTRY
Reset_Handler
; 411446510 Tsai Ping Cen
;base: 0xE000E000
;offset: 0xD14
;bit: 4
LDR r6, =NVICBase
LDR r7, =DivbyZ
LDR r1, [r6, r7]
ORR r1, #0x10 ;enable bit 4
STR r1, [r6, r7]
;turn on the usage fault exception
LDR r7, =SYSHNDCTRL
LDR r1, [r6, r7]
ORR r1, #0x40000
STR r1, [r6, r7]
;try out a divide by 2 then a divide by 0!
MOV r0, #0
MOV r1, #0x11111111
MOV r2, #0x22222222
MOV r3, #0x33333333
;this divide works just fine
UDIV r4, r2, r1
;this divide takes an exception
UDIV r5, r3, r0
; 411446510 Tsai Ping Cen
Exit B Exit
NmiISR B NmiISR
FaultISR B FaultISR
IntDefaultHandler
LDR r7, =Usagefault
LDRH r1, [r6, r7]
TST r1, #0x200
BNE Happened
BEQ NotHappened
Happened
LDR r3, =MSG_with_Error
LDR r1, =0x20000030 ; starting address of characters
Loop
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
; 411446510 Tsai Ping Cen
BX LR
NotHappened
LDR r3, =MSG_without_Error
LDR r1, =0x20000090 ; starting address of characters
Loop2
LDRB r5, [r3], #1
STRB r5, [r1], #1
CMP r5, #0
BNE Loop2
MRS r8, CONTROL
ORR r8, #1
MSR CONTROL, r8
BX LR
;r1 should have bits 9 set indicating
;a divide-by-zero has taken place
done B done
MSG_with_Error
DCB "DIVIDE-BY-0 Happened!", 0
MSG_without_Error
DCB "DIVIDE-BY-0 Not Happened", 0
ALIGN
END
```
