han*_*fan 1 assembly arm reverse-engineering program-counter
我有一个指令块,我想知道电脑寄存器是如何工作的。维基百科上说,pc 寄存器保存下一条要执行的指令的值,但是,查看二进制忍者的反汇编图以查找同一指令块,似乎这并不完全正确。
这是二进制忍者的反汇编图的一部分,其中每个内存加载前面都写入了加载发生的内存地址。

000080ec ldr r3, [pc, #76] -> 0x813c = 0x80f0 + 0x4c -> pc = 80f0 ?? (shouldnt it be 80ee).
000080ee cmp r3, #0
000080f0 it eq
000080f2 ldreq r3, [pc, #68] -> 0x8138 = 0x80f4 + 0x44 -> pc = 80f4 (this makes sense).
000080f4 mov sp, r3
000080f6 sub.w sl, r3, #65536 (edited)
Run Code Online (Sandbox Code Playgroud)
这也发生在代码中,并不总是电脑保存下一条要执行的指令的地址..有什么我应该考虑的吗?
您缺少的关键是PC拇指中的价值ldr Rd, [Pc, #imm]指令中的值在使用之前已对齐到 4 个字节。ARMv7 架构参考手册中稍微删节的伪代码是:
t = UInt(Rt);\nimm32 = ZeroExtend(imm8:\xe2\x80\x9900\xe2\x80\x99, 32);\nbase = Align(PC,4);\naddress = base + imm32;\ndata = MemU[address,4];\nR[t] = data;\nRun Code Online (Sandbox Code Playgroud)\n回到你的例子:
\n000080ec ldr r3, [pc, #76]\nRun Code Online (Sandbox Code Playgroud)\n我们知道PC在 Thumb 模式下读取为当前地址加 4 个字节,因此 PC 读取为0x80f0. 该值已与 4 字节对齐,因此base具有相同的值。对此我们添加76(立即数始终是四的倍数,并且不存储两个最低有效位)0x813c。
对于第二个例子:
\n000080f2 ldreq r3, [pc, #68]\nRun Code Online (Sandbox Code Playgroud)\n这与上面的指令相同ldr。反汇编器eq在助记符中添加后缀,因为该指令受前一个IT块的条件执行的影响。但这不会以任何方式影响指令编码。\nPC读取为0x80f6,与 4 字节对齐0x80f4。对此我们添加68,获得0x8138作为加载的地址。
有关详细信息,请参阅 ARM 体系结构参考手册。
\n