【ARM裸板】未定義指令異常分析及示例

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,爲未定義指令異常
    在這裏插入圖片描述

在這裏插入圖片描述

2.程序執行過程

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章