补坑计划——ARM(二)

主要记录一下今天遇到的关于B指令和相对地址偏移的问题


B跳转指令是一个相对跳转指令

最高处4为(28~31)为条件码,后4位(24~27)“1010”表示B跳转,“1011”表示BL跳转

剩下24位(0~23)表示相对偏移地址,偏移地址是这样计算的:

先将24位补充为32位,然后左移两位,再与PC寄存器的相加,保存到PC寄存器

计算公式如下

(srcAddr + 8) + (x << 2) =  desAddr

srcAddr表当前指令地址,x表偏移值

那srcAddr + 8 是什么意思呢?这就牵涉到PC寄存器

要解释这个,先了解一下ARM三级流水线


有点复杂,看一张稍微简单的图


ARM下每条指令4个字节,每条指令都要经过取指、译码、执行三个过程

比如上图中的指令

0000:  add    r0, r1, #5

0004:  sub    r2, r3, r6

0008:  cmp    r2, #3

当第一行指令被执行的时候,第二行指令被译码,第三行取指

而PC寄存器保存的是取指的指令的位置,也就是假设第一行代码的地址为0000,那么现在PC的值为0008


如果是使用BL执行了正常程序的跳转,那么执行这条BL指令时,由于是正常的跳转指令,所以cpu会将返回地址存放在LR中,即当前指令地址加4,当从子程序跳转回来的时候,那么就需要将保存在LR寄存器中的值恢复给PC寄存器,

mov PC, LR     这样的指令返回



IRQ异常发生时,因为这个异常是在指令执行时候发生的,PC的值等于当前执行指令加8,然后将这个值保存在LR中。但是LR寄存器中保存的是PC+8,指向的是后面的第二条指令,如果不进行减4处理,将会漏执行一条指令,所以PC恢复的时候就需要LR减4,所以正常从子程序返回的时候会使用如:

SUBS PC, LR,#4     返回到当前指令的下一条指令

未定义指令异常时,因为这个异常发生在指令译码阶段,所以,此时PC的值就是未定义指令加4,然后保存到LR(参考流水线图);因为该指令未定义,所以返回时就不应该返回到这条未定义指令,而是返回到它的下一条指令,R14中保存的刚好就是下一条指令的地址,所以就不用计算了,直接将R14赋值给PC就行了

预取指令异常是在流水线的执行阶段时才进入异常,所以PC的值是当前执行指令地址加8,所以返回时应该返回到下一条指令,所以PC恢复的时候就需要R14减4

数据中止异常,这个异常是在本指令执行完成后才发生的,表示当前存储器的访问不能完成,从流水线图可以看出,当第一条指令执行完成时,当前PC值已经指向了第一条指令地址加12的地址,LR中保存的其实是第四条指令的地址了,所以从异常返回时,需要从第一条指令的下一条指令(第二条指令)开始执行,所以PC恢复的时候就需要R14减8



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值