繁体   English   中英

PC寄存器上的ARM LDR指令

[英]ARM LDR instruction on PC register

我在这里理解这个故事:

  • PC寄存器保存指向下一条指令的指针
  • LDR指令将第二个操作数的值加载到第一个操作数中(例如)
      LDR r0,[pc,0x5678] 
    相当于这个“C代码”
    \n r0 = *(pc + 0x5678)\n
    它是使用基本偏移量解引用的指针。

我的问题是:

我找到了这段代码

LDR PC, [PC,-4]

它被评论为猴子修补等。

我如何理解这段代码

pc = *(pc - 4)

在这种情况下,“pc”寄存器将取消引用前一条指令的地址,并将包含指令的“机器代码”(不是指令的地址),程序将跳转到该无效地址继续执行,可能我们将“分段故障”。 那么我缺少或不理解?



让我思考的是LDR指令中第二个操作数的括号。 据我所知,x86架构上的括号已经取消引用指针,但我无法理解ARM架构中的含义。

mov r1, 0x5678
add r1, pc
mov r0, [r1]

这段代码相当于?

LDR r0, [pc, 0x5678]

引自ARM指令集文档(ARM DDI 0029E)的4.9.4节:

使用R15作为基址寄存器时,必须记住它包含当前指令地址8字节的地址。

因此该指令将加载位于当前指令之后 4个字节的字,该字有望包含有效地址。

由于ARM体系结构的一个怪癖LDR PC, [PC,-4] 以下指令的分支(假设我们在谈论ARM,而不是Thumb),因此在正常情况下它没有效果(性能除外) )。 关键是,通过将该指令放在函数的开头,然后代码在运行时通过重写 LDR指令的底部12位来改变偏移,从而非常简单,从而将该函数重定向到其他地方。 分支到紧跟在指令之后的字中存储在存储器中的地址。 Herp derp,我让ADRLDR混淆了 - 如果它是ADR ,上面的情况就是如此,但这种情况更为直白。

现在我已经失去了自己,这只是一个简单的函数调用蹦床。 函数地址将紧跟在LDR指令之后存储为数据字(可能由链接器设置为某个初始值),并且可以在运行时简单地重写为数据以重定向分支,而无需求助于自修改代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM