1.未定義指令異常示例
- 根據5.1可知,執行異常處理函數之前,硬件會處理的事情:
- 1.lr_und保存有被中斷模式中的下一條即將執行的指令的地址
- 2.SPSR_und保存被中斷模式CPSR
- 3.CPSR的[M4:M0]=[11011],進入到und模式
- 4.跳到0x04的模式執行程序,即跳到
b do_und
這一指令
/*====================================異常向量表===========================================*/
_start:
b reset //vector 0: reset(0地址對應reset)
ldr pc, =und_addr //絕對跳轉,跳轉至sdram中,vector 4: und (發生未定義指令異常,則進入“處理未定義異常函數”)
und_addr:
.word do_und //存放地址,確保這一地址存放在內存的前4K中
/*=================================處理未定義異常=========================================*/
do_und:
/*執行到這裏之前:
*1.lr_und保存有被中斷模式中的下一條即將執行的指令的地址
*2.SPSR_und保存被中斷模式CPSR
*3.CPSR的[M4:M0]=[11011],進入到und模式
*4.跳到0x04的模式執行程序,即跳到`b do_und`這一指令
*/
/* sp_und 設置棧,因爲後面函數需要棧 */
ldr sp, =0x34000000
/* 保存現場 */
/* lr是異常處理完後的返回地址,也需要保存 */
stmdb sp!, {r0-r12,lr} //在und異常處理函數總有可能需要用到r0~r12,因此先保存下來
/* 處理und異常 */
mrs r0,cpsr //把cpsr的值放入r0
ldr r1, =und_string
bl printException
/* 恢復現場 */
ldmia sp,{r0-r12,pc}^ //將lr的值賦給pc ,`^`會把spsr的值恢復到cpsr中
und_string:
.string "undefined instruction exception"
.align 4 //確保4字節對齊
1.1 在彙編中加入string
-
.string "str"
Copy the characters in str to the object file. You may specify more than one string to copy, separated by commas. Unless otherwise specified for a particular machine, the assembler marks the end of each string with a 0 byte. You can use any of the escape sequences described in section Strings. -
在字符串後最好加一句
·.align 4
,確保後續的程序4字節對齊
und_string:
.string "undefined instruction exception"
.align 4 //確保4字節對齊
1.2 MRS & MSR
ARM中有兩條指令用於在狀態寄存器和通用寄存器之間傳送數據
- MRS: 狀態寄存器到通用寄存器的傳送指令
mrs r0,cpsr
//將CPSR的值讀出放在r0
- MSR: 通用寄存器到狀態寄存器的傳送指令
msr cpsr, r0
//將r0的值寫入CPSR
1.3 設置und的棧
- 由於後面需要保存寄存器數數據、以及發生函數調用並且需要傳遞參數,需要用到棧,因此需要先設置棧(隨便指向一塊未使用的內存)
/* sp_und 設置棧,因爲後面函數需要棧 */
ldr sp, =0x34000000
1.4 保存現場
- 根據未定義指令異常寄存器資源,在und異常處理函數總有可能需要用到r0~r12,因此先保存下來(保存在棧中)
- 以及lr寄存器,後面還需要返回
stmdb sp!, {r0-r12,lr}
1.5 處理異常
- 打印提示發生未定義異常,並打印CPSR的值
mrs r0,cpsr //把cpsr的值放入r0
1.6 恢復現場
- 依次恢復r0~r12的值,恢復cpsr的值,並把lr的值賦給PC,
ldmia sp,{r0-r12,pc}^ //`^`會把spsr的值恢復到cpsr中
1.7 驗證
- CPSR = 0x600000db
- 確實滿足CPSR的 [M4:M0] = 11011,爲未定義指令異常