|
初学ARM,可能会被异常返回这个东西搞得头大。一会儿直接MOV PC,LR,一会儿LR-4,甚至有时要LR-8。为什么要-4,又或者为什么要-8?
当然了,如果你只是简单地想编个程序,基本上照抄ARM公司给的范例就可以了。但是凡事总想知道个所以然来,所有在这里简单地想议一议ARM的异常返回,到底为什么要-4,为什么要-8。
想了解这些,至少要了解以下几个方面的问题:一、异常的种类。什么行为导致了异常,这一点非常重要,它关系到产生异常的指令是否要重新执行一遍,如果要重新执行,LR就要多减一个4(4字节,一个指令增量),这样PC才能指向你要重新执行的指令。二、异常发生时,PC值有没有更新?这一点也非常重要,如果PC值没有更新,LR就要少减一个4,如果PC值更新了,就要多减一个4。为了弄懂这一点,需要我们去了解ARM指令执行过程,到底是什么时候更新的PC值。刚才好像想到还有一点,只是刚接了一个电话,忘了。汗!
当然,在了解上面所有问题之前,首先需要清楚的就是ARM7的“取指->译码->执行”三级流水线。另外,需要明白的还有一个就是在异常发生时,处理器已经做过了SUBS LR,PC,#4。也就是说,LR已经进行了一次减4。
举一个最简单的例子:IRQ和FIQ(为啥举这个例子捏,因为,介个…..,别的异常我还没搞清楚哈!):
首先是IRQ和FIQ发生在什么时候,这时候PC有没有更新。“通常处理器执行完当前指令后,查询IRQ中断引脚和FIQ中断引脚,并且查看系统是否允许IRQ中断和FIQ中断。如果有中断引脚有效,并且系统允许中断产生,处理器将产生IRQ异常中断或FIQ异常中断。”我们可以看到,当前指令(设该指令为I0)已经执行完毕,即使我们不知道指令执行过程,也可以猜到这时PC已经更新,系统即将执行下一条执行,设该指令为I1,PC应该是I3。另外,我们还应该知道中断时候的指令是否应该被重新执行。我们通过IRQ或FIQ发生时的情况可以知道,I0已经执行完毕,也就是说I0不需要重新执行。于是我们知道,异常返回时应该执行I1。而当前LR中存放的是什么呢?LR中存放的应该是PC-4,也就是I3前面一条指令I2,我们要执行I1,这时,就应该是MOV PC,I1。I1不合法啊,那就应该是I1=I2-4=LR-4。于是返回指令就是SUBS PC,LR,#4。
以上就是俺一点心得,很小,但是得来的很不容易啊!现在ARM的资料很多,中用的很少,大家基本都是抄来抄去。翻了无数的参考书,查了很多论文,终于算是基本知道中断返回应该怎么做了。自己看书,周围基本没有人可以交流,不知道理解是不是对的,大家指正。另外,对其它几个异常产生的原因还不是非常了解,在此不敢妄自揣度,向大家请教!