ldr的奇怪行为[pc,#value]

XAd*_*der 11 c++ assembly arm

我正在调试一些c ++代码(ARM平台上的WinCE 6),我发现一些奇怪的行为:

    4277220C    mov         r3, #0x93, 30
    42772210    str         r3, [sp]
    42772214    ldr         r3, [pc, #0x69C]
    42772218    ldr         r2, [pc, #0x694]
    4277221C    mov         r1, #0
    42772220    ldr         r0, [pc, #0x688]
Run Code Online (Sandbox Code Playgroud)

Line 42772214 ldr r3, [pc, #0x69C]用于从.DATA部分得到一些常量,至少我是这么认为的.

奇怪的是,根据代码r2应该填充来自地址pc = 0x42772214 + 0x69C = 0x427728B0的内存,但是根据它从0x427728B8(8字节+)加载的内存内容,它也适用于其他ldr用法.

它是调试器的错误还是我对ldr/pc的理解?我没有得到的另一个问题 - 为什么访问.data部分是相对于执行的代码?我觉得有点奇怪.

还有一个问题:我找不到第一个mov命令的语法(任何一个都可以指向我的Thumb(1C2)的optype规范)

对于laic描述很抱歉,但我只是熟悉程序集.

ken*_*ytm 17

这是对的.当pc用于读取时,ARM模式下有8字节偏移,Thumb模式下有4字节偏移.

来自ARM-ARM:

当指令读取PC时,读取的值取决于它来自哪个指令集:

  • 对于ARM指令,读取值是指令的地址加上8个字节.此值的位[1:0]始终为零,因为ARM指令始终是字对齐的.
  • 对于Thumb指令,读取值是指令的地址加上4个字节.该值的位[0]始终为零,因为Thumb指令始终是半字对齐的.

这种读取PC的方式主要用于对附近指令和数据进行快速,位置无关的寻址,包括程序内与位置无关的分支.

pc相对寻址有两个原因.

  1. 与位置无关的代码,在您的情况下.
  2. 得到一些复杂的常量,这些常量不能用1个简单的指令写入,例如mov r3, #0x12345678不可能在1个指令中完成,因此编译器可以将此常量放在函数的末尾,并使用例如ldr r3, [pc, #0x50]加载它.

我不知道是什么mov r3, #0x93, 30意思.可能是mov r3, #0x93, rol 30(给出0xC0000024)?

  • `mov r3,#0x93,30`实际上意味着`mov r3,#0x93,ror 30`,给出'0x24c`. (3认同)
  • @Mike - 很好的解释,并且很适合引用 ARM ARM。在ARM 3级流水线中,PC始终指向正在取指的指令,PC-4指向正在解码的指令,PC-8是“当前指令”,即正在执行的指令。这也是异常返回前必须调整LR值的原因。正如您所指出的,这适用于 ARM(32 位)指令,因此每个管道阶段需要 4 字节调整。 (2认同)