先来看看一些特殊的寄存器,以后可能经常用到:R13、R14、R15。
寄存器R13,经常用做栈指针。至于栈是用来干啥的,呵呵,进出中断,就得有个临时存放数据的地方,老外就管他叫栈(stack)。注意,堆和栈是不一样的两个概念。关于堆和栈的区别,其实还不是很理解,以后在查资料补充吧。
R15就是PC:程序计数器。这个单片机也有,作用是一样的。但是要注意的是,ARM采用的是三级流水线方式,我们把当前的PC的内容读取来一看,哇塞,不是当前正在执行的指令的地址!!?!!是当前指令的地址的值加8个字节。嘿,对于ARM指令来说,PC指向当前指令的下两条指令的地址。 讲到PC,很多人不理解
MOV PC, PC
这指令是让代码停那不动了??其实不是。这是将程序跳转到当前指令的下2条指令处执行。记住,执行该指令时,肯定要先去读取PC的值,否则PC的值哪里来?对吧?这读取出来的PC的值,是当前指令往后的第2条指令哦~所以实际上是将程序跳转到当前指令的下2条指令处执行。 ADD PC, PC, #0 会有什么样的结果?执行结果是,把当前指令后的第2条指令地址给PC。 由于在执行的时候,需要先知道PC的值,才能相加。因此需要先读取出后一个PC的值。 而这后一个PC的值,是当前指令后的第2条指令的地址。因此,该指令的执行结果是,把当前指令后的第2条指令地址给PC。
R14是硬性被规定用于连接寄存器的,也叫LR。用于存放返回地址的。这要和R13区别开来哈!R13是栈指针,放的数据的指针(地址)。R14是放程序的返回地址的。返回的时候,R14的值复制到PC中,那程序就跳转回来了。值得注意的是,异常发生时,处理器一般都将(PC – 4)的值保存到相应的LR中。不是PC的值!!
IRQ或FIQ异常中断。一般情况下,处理器会在执行完当前指令后,去查询IRQ中断引脚及FIQ中断引脚,并且看看当前系统是否允许IRQ或FIQ中断。如果中断引脚有效,并系统也允许产生该中断,那么,处理器这才会发生IRQ或FIQ中断。假设现在中断已经产生了,那么此时PC的值是已经更新的PC的值(PC会预取指令的),它会指向当前指令后的第3条指令,也就是往后的第12个字节处。所以我们给LR的值,应该是PC – 4,即当前指令往后第8个字节才对。
一般情况下,发生异常中断时,处理器会将(PC - 4)的值保存到对应异常模式下的LR中。此时(PC - 4)会指向当前指令后的第2条指令。那么是不是所有异常下,这个(PC - 4)都指向当前指令的后第2条指令?
答案是否定的,比如指令预取中止中断就不是这样的。其实指令预取中断发生的时候,程序会重新再读取该指令,因此是返回发生中断指令的地方。而不是返回到发生中断的指令的下一条指令。由于该中断发生是执行指令时产生的(IRQ是执行完指令后查询IRQ引脚才会产生),因此此时PC的值还没有更新,会指向当前指令后面的第2条指令。处理器再把这个(PC - 4)的值保存到LR中,此时PC - 4的值就是指向当前指令的下一条指令,而不是下两条指令。
返回的时候,执行的指令不变,仍旧是执行SUBS PC, LR, #4,即把LR的值减去4,呵呵 明白了吧?LR - 4后,就回到了原先发生中断指令的地址那里了。然后把这个值给PC,就又开始预取、执行了。
阅读(1454) | 评论(0) | 转发(0) |