C++ 为什么ARM的这个分支指令不';行不通

C++ 为什么ARM的这个分支指令不';行不通,c++,c,assembly,arm,C++,C,Assembly,Arm,现在我正在编写一个库来模拟C/C++的普通函数。它的用法如下:MOCK(MOCK,substitute) 如果调用模拟函数,则将调用替换函数 我修改了代码页的属性,并将跳转代码注入到函数中来实现它。我已经为x86cpu实现了它,我想把它移植到armcpu。但是我在注入二进制代码时遇到了一个问题 例如,替换函数的地址是0x91f1,模拟函数的地址是0x91d1。因此,我想将ARM分支代码注入0x91d1以跳转到替换函数 根据在线文件,相对地址为 (0x91f1 - (0x91d1 + 8)) /

现在我正在编写一个库来模拟C/C++的普通函数。它的用法如下:
MOCK(MOCK,substitute)
如果调用模拟函数,则将调用替换函数

我修改了代码页的属性,并将跳转代码注入到函数中来实现它。我已经为
x86cpu
实现了它,我想把它移植到
armcpu
。但是我在注入二进制代码时遇到了一个问题

例如,替换函数的地址是
0x91f1
,模拟函数的地址是
0x91d1
。因此,我想将ARM分支代码注入
0x91d1
以跳转到替换函数

根据在线文件,相对地址为

(0x91f1 - (0x91d1 + 8)) / 4 = 6
所以二进制指令是:

0xea000006
因为我的arm emulator(我使用Android arm v7 emulator)是little endian,所以要注入的二进制代码是:

0x060000ea

但当我在注入分支代码后执行模拟函数时,出现了段错误。我不知道为什么分支指令是错误的。我还没有学习ARM体系结构,所以我不知道ARM的分支指令是否有一些限制。

ARM系列允许加载带有值的寄存器。其中一个寄存器是PC(程序计数器)

一些备选方案:

  • 您可以使用一个函数来加载带有 目的地址(绝对)
  • 添加带有偏移量的PC寄存器
  • 在PC寄存器中使用乘法和加法指令
  • 将目标寄存器推到堆栈上并弹出到PC中 登记

  • 这些选项加上修改分支指令的目标都是不同的选项,但不是“最佳”选项。选择一个最适合你并且最容易维护的

    分支到的地址是奇数,这意味着它们处于拇指模式

    你的方法有一个明显的问题

    如果目标处于Thumb模式,则需要在分支点处于Thumb模式,或者需要使用
    bx
    (分支和交换)指令


    您的功能处于Thumb模式(+1在目标位置),但您使用的是ARM模式分支编码(B A1编码?),因此很明显,您不是在Thumb模式下,就是在Thumb模式下使用ARM模式指令。

    您确定不是注入导致了故障吗?您运行的操作系统是什么?您是如何确保对.text进行数据访问的?要插入的字节是
    0x06、0x00、0x00、0xea
    ,但如果您将其作为整数插入,则应保留
    0xea000006
    ,因为将酌情对其应用endianness。假设您的模拟器有一些调试功能,请使用它。确保代码不在内存中。现在大多数ARM平台默认使用Thumb。ARM没有对齐要求吗?函数的单词边界?0x91f1看起来很可疑。哪种ARM体系结构?这些都是很好的解决方法,但您没有回答OP使用的简单分支有什么问题。除了最后一句,这个答案看起来是正确的。当分支汇编程序助记符使用汇编源中的绝对地址时,指令操作码包含26位
    PC
    相对偏移量(操作码中指定的24位带有两个隐式最低有效零位)。@MichaelBurr谢谢!直到某物。