assembly - 为什么 'LDR' 不能替换为 'B' ?

标签 assembly arm

我有一个程序(arm)和一些指令(IDA 拒绝):

.plt:000083F0   ADRL   R12, 0x83F8
.plt:000083F8   LDR    PC, [R12,#(off_90D8 - 0x83F8)]! ; sub_83D0

地址0x90D8存储0x83D0:

000090D8  D0 83 00 00

所以,在ldr之后,pc是0x83D0并且将执行0x83D0中的inst,不是吗?

这里我想直接跳转到0x83D0而不是使用09D8,我修改了二进制机器码并通过IDA重新加载:

.plt:000083F0   B   sub_83D0

IDA显示会跳转到0x83D0,所以我认为修改是有效的。
但修改后程序无法运行。
我的修改有什么问题以及如何实现我的目标?请帮助我...

我在这里添加了一些更多的缺点:
SRC

.plt:000083E4
.plt:000083E4 ; =============== S U B R O U T I N E =======================================
.plt:000083E4
.plt:000083E4 ; Attributes: thunk
.plt:000083E4
.plt:000083E4 sub_83E4                                ; CODE XREF: .text:00008410j
.plt:000083E4                 ADRL            R12, 0x83EC
.plt:000083EC                 LDR             PC, [R12,#(off_90D4 - 0x83EC)]! ; sub_83D0
.plt:000083EC ; End of function sub_83E4
.plt:000083EC
.plt:000083F0
.plt:000083F0 ; =============== S U B R O U T I N E =======================================
.plt:000083F0
.plt:000083F0 ; Attributes: thunk
.plt:000083F0
.plt:000083F0 sub_83F0                                ; CODE XREF: sub_8430+6p
.plt:000083F0                                         ; sub_8430+Ep ...
.plt:000083F0                 ADRL            R12, 0x83F8
.plt:000083F8                 LDR             PC, [R12,#(off_90D8 - 0x83F8)]! ; sub_83D0
.plt:000083F8 ; End of function sub_83F0
.plt:000083F8
.plt:000083F8 ; .plt          ends
.plt:000083F8

已修改

.plt:000083E4
.plt:000083E4 ; =============== S U B R O U T I N E =======================================
.plt:000083E4
.plt:000083E4 ; Attributes: thunk
.plt:000083E4
.plt:000083E4 sub_83E4                                ; CODE XREF: .text:00008410j
.plt:000083E4                 ADRL            R12, 0x83EC
.plt:000083EC                 LDR             PC, [R12,#(off_90D4 - 0x83EC)]! ; sub_83D0
.plt:000083EC ; End of function sub_83E4
.plt:000083EC
.plt:000083F0
.plt:000083F0 ; =============== S U B R O U T I N E =======================================
.plt:000083F0
.plt:000083F0
.plt:000083F0 sub_83F0                                ; CODE XREF: sub_8430+6p
.plt:000083F0                                         ; sub_8430+Ep ...
.plt:000083F0                 ADRL            R12, loc_83F8
.plt:000083F8
.plt:000083F8 loc_83F8                                ; DATA XREF: sub_83F0o
.plt:000083F8                 B               sub_83D0
.plt:000083F8 ; End of function sub_83F0
.plt:000083F8
.plt:000083F8 ; .plt          ends
.plt:000083F8

在 0x90D4 中:

000090D4  D0 83 00 00 D0 83 00 00

最佳答案

指令B sub_83D0是相对于PC的。指令顺序,

.plt:000083F0   ADRL   R12, 0x83F8
.plt:000083F8   LDR    PC, [R12,#(off_90D8 - 0x83F8)]! ; sub_83D0

000090D8:  D0 83 00 00

是相对于PC的,但它跳转到绝对地址。您假设链接地址是运行时地址。这并不总是正确的,特别是在可能重新定位或启用MMU引导代码中。

上面的序列可以从任何地址运行,并将控制权转移到绝对地址 0x83d0branch 变体仅通过添加来更改 PC一个偏移量。即,

PC = PC + (SignExtend) (immediate << 2);

等效项是 mov pc, #0x83D0,但这不符合 mov 立即数旋转 8 位 的限制2.你可以尝试,

mov r12, #0x8300
orr pc, r12, #0xd0

但传输到的代码可能还需要将 r12 值设置为较旧的运行时地址。

关于assembly - 为什么 'LDR' 不能替换为 'B' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17428025/

相关文章:

cmake add_subdirectory 无法正确编译

c - gcc 版本 4.6.3 上的 c 程序汇编版本

assembly - 如何使用 div 指令在 x86 汇编中求余数?

arm - 无中断嵌入式编程

assembly - 为什么ARM说 "A link register supports fast leaf function calls"

arm - 如何使用 QEMU 的简单跟踪后端?

c - Linux 中的结构分配在 ARM 中失败但在 x86 中成功

c - 如何编写 Makefile 将 C 代码与 Arm 汇编代码链接?

c++ - 什么时候应该使用 ASM 调用?

assembly - 如何在 IDA/Olly 中的反汇编代码之间添加汇编指令?