我正在调试一些C代码(ARM平台上的WinCE 6)
我发现一些行为很奇怪:
我发现一些行为很奇怪:
4277220C mov r3,#0x93,30 42772210 str r3,[sp] 42772214 ldr r3,[pc,#0x69C] 42772218 ldr r2,#0x694] 4277221C mov r1,#0 42772220 ldr r0,#0x688]
线42772214 ldr r3,#0x69C]用于从.DATA部分获取一些常量,至少我认为是这样.
什么是奇怪的是,根据代码r2应该从地址pc = 0x42772214 0x69C = 0x427728B0填充内存,但根据内存内容,它从0x427728B8(8bytes)加载,它也适用于其他ldr用法.
调试器是否出错或者我对ldr / pc的理解?
另一个我没有的问题 – 为什么访问.data部分是相对于执行的代码?我觉得有点奇怪.
还有一个问题:我找不到第一个mov命令的语法(任何人都可以指向Thumb(1C2)的optype规范)
对不起,说笑话,但我只是熟悉大会.
解决方法
这是对的.当pc用于读取时,ARM模式下有8位偏移量,Thumb模式下有4位偏移量.
从ARM-ARM:
When an instruction reads the PC,the value read depends on which instruction set it comes from:
- For an ARM instruction,the value read is the address of the instruction plus 8 bytes. Bits [1:0] of this value are always zero,because ARM instructions are always word-aligned.
- For a Thumb instruction,the value read is the address of the instruction plus 4 bytes. Bit [0] of this value is always zero,because Thumb instructions are always halfword-aligned.
This way of reading the PC is primarily used for quick,position-independent addressing of nearby instructions and data,including position-independent branching within a program.
pc相对寻址有两个原因.
>与位置无关的代码,在你的情况下.
>附近有一些复杂的常数,不能用一个简单的指令写出,例如mov r3,#0x12345678在1个指令中是不可能完成的,所以编译器可能会在函数结束时将这个常数置为0. ldr r3,#0x50]来加载它.
我不知道mov r3,30是什么意思.可能是mov r3,rol 30(给出0xC0000024)?