【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.程序执行过程

在这里插入图片描述

发布了42 篇原创文章 · 获赞 176 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39492932/article/details/104111202