? 利用sub lr,lr,#4:程序是如何进行返回的?_Linux编程_Linux公社-Linux系统门户网站 bet36手机投注_bet36 无法登陆 解决_bet36体育投注平台
手机版
你好,游客 登录 注册
背景:
阅读新闻

利用sub lr,lr,#4:程序是如何进行返回的?

[日期:2017-04-11] 来源:Linux社区? 作者:yu-chen [字体: ]

1: ARM采用的是3级流水线

  ARM的流水线结构为: ? 取指 -----> 译码 ------> 执行

? ? ? ARM代码: ? ? ? ? ? ? ? ? ?PC ? ? ? ? ? PC- 4 ? ? ? ?PC - 8

?   地址: ? ? ? ? ? ? ? ? ? 0x1008 ? 0x1004 ? ? 0x1000

  PC是指向被取指的指令,而不是正在执行的指令。(也就是说在此 PC值为0x1008 ,执行的是0x1000的代码)

  (即:书上摘录:由于ARM 体系结构采用了多级流水线技术,对于ARM 指令集而言,PC 总是指向当前指令的下两条指令的地址,PC 的值为当前指令的地址值加8 个字节)

2: 当发生BL跳转前,会在寄存器 R14 (即LR)中保存当前PC-4,即bl跳转指令的下一条指令的地址。所以在返回时只要 MOV pc,lr

3:中断

? ? (1)当发生中断的时候,把是此时寄存器pc当前值(0x1008)存入LR_irq(此时的LR是中断模式下的LR),所以返回时,应该是将LR-4赋值给PC(0x1004)注:有些异常中断可能要将LR-8或LR赋值给PC。详细请仔细看ARM数据手册).

? ? (2)当发生IRQ或FIQ后,系统要进入相应的异常模式进行处理,这些是由硬件实现的。

? 产生异常后,ARM核会做以下工作:
? ? <1>. 将正在执行代码的地址加4(或者加8)存到LR_irq寄存器里,即把处于译码指令的地址存入LR_irq
? ? ?<2>. 将CPSR复制到SPSR,
? ? ?<3>. 然后将异常模式的状态强制写入CPSR
? ? ?<4>. 强制PC从相关的异常向量处取指!!

? 中断结束后:

? ? ? ?1. 将SPSR复制回CPSR

? ? ? 2. 关中断

? ? ? 3. 返回原程序,LDR PC,LR_irq

4:因为每个模式下面都有LR_mode,所以当返回原来模式时,原来模式下的LR并没有被破坏。

5:需要注意的是,当前使用指令STM/STR保存R15时候,保存的可能是当前指令地址值+8字节,也可能保存的是当前的指令地址+12字节.到底是哪种,取决于芯片的具体的设计方式。无论如何,在同一芯片中,要么采用当前的指令地址+8,要么采用当前的指令地址+12。因此对于用户来讲,尽量避免使用STM/STR指令来保存R15的值。但是可以在开始的时候用一段程序对芯片的offset进行测试!

?代码如下:
SUB?R1,?PC,?#4? ;获得下面的存放下面存放STR指令的地址,
STR?PC,[R0] ? ? ? ; [R0] = PC
LDR?R0,[RO] ? ? ?; ?R0 ?= PC
SUB?R0,?R0,?R1 ?; ?R0 ?= PC - R1

大致流程如下:

   程序运行方向: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 取指 -----> 译码 ------> 执行

? ? ? ? ? ? ? ? ? ? 指令: ? ? ? ? ?SUB?R0,?R0,?R1  LDR?R0,[RO]  STR?PC,[R0]  SUB?R1,?PC,?#4

      STR(+ 8) ? ? ? ? 0x1010   ? ? ? ? ?0x100C   ? ? ? ? ?0x1004   ? ? ? ? 0x1000

      STR(+12)? ? ? ? 0x1014   ? ? ? ? ?0x1010   ? ? ? ? ?0x1004   ? ? ? ? 0x1000

       1): 执行第一条指令SUB时:PC=?0x1004

       2): 执行第二条指令STR时:[R0] = 0x1010(+8) 或?[R0] = 0x1014(+12)?

       3): 执行第三条指令LDR时:R0?= 0x1010(+8) 或 R0 = 0x1014(+12)?

       ? 3): 执行第四条指令SUB时:R0 =?0x1010-?0x1004 = 0x08 ?或 ?R0 =?0x1014-?0x1004 = 0x10 ?

ARM7中断与PC、LR的问题:

1,假设当前是PC,PC-4,PC-8(三级流水)
2,发生IRQ异常,执行保护操作,LR中保存由于FIQ或IRQ占先而没有被执行的指令的地址(即有些资料上把这个地址写成PC或者当前地址,很费解甚至误解)的下一条地址
3,清空流水线
4,进入中断服务程序
5,待流水线填满,执行操作才被重新挂起(解释了ARM7为什么是0.9MIPS)
6,中断返回前,对LR处理,LR=LR-4,指向之前被清空的已译码但没被执行的指令的地址
7,清空流水线,返回
8,重新对丢弃的前一次已译码指令取指
9,待流水线满,开始继续执行

本文永久更新链接地址http://www.linuxidc.com/Linux/2017-04/142697.htm

linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款