固件补丁的ARM/Thumb代码…如何告诉gcc汇编器/链接器到BL到绝对地址?

固件补丁的ARM/Thumb代码…如何告诉gcc汇编器/链接器到BL到绝对地址?,gcc,arm,gnu-assembler,Gcc,Arm,Gnu Assembler,我正在尝试编写一个固件mod(到现有固件,我没有源代码) 所有的拇指代码 在gcc中,是否有人知道如何作为(GAS)汇编程序执行此操作: 当BL连接到某个现有函数时(不在我的代码中,但我知道它的地址),使用BL无需手动计算偏移量 目前,如果我想使用BL…我必须: -返回我的代码 -计算并添加在我正在编写的函数中汇编所有前面的指令所产生的所有字节 -将我的函数的起始地址添加到该地址(我在链接器脚本中指定我正在编写的内容的起始地址) -然后减去我要调用的firmfunc函数的地址 所有这些。。。只是

我正在尝试编写一个固件mod(到现有固件,我没有源代码) 所有的拇指代码

gcc中,是否有人知道如何作为
(GAS)汇编程序执行此操作:
BL
连接到某个现有函数时(不在我的代码中,但我知道它的地址),使用
BL
无需手动计算偏移量

目前,如果我想使用
BL
…我必须: -返回我的代码 -计算并添加在我正在编写的函数中汇编所有前面的指令所产生的所有字节 -将我的函数的起始地址添加到该地址(我在链接器脚本中指定我正在编写的内容的起始地址) -然后减去我要调用的firmfunc函数的地址

所有这些。。。只是为了计算偏移量。。。要能够写入
bl
偏移量。。。调用现有固件函数? 如果我在BL之前更改了任何代码,我必须手动重新执行
这就是为什么我想学习使用
BX
对。。。而不是
BL

还有,我不太懂BX。如果我使用BX跳转到一个绝对地址,那么在从Thumb code校准Thumb code时,我是否必须将实际地址增加1(以保持lsb字节1)。。。CPU会知道它是拇指代码吗?

大编辑:

根据我最近学到的知识和对问题的更好理解修改答案

首先,我不知道如何告诉链接器生成一个bl到一个地址,这是一个硬编码的地址,实际上不是在这个代码。您可能会尝试装配一个elf文件,该文件有标签等,但不知道是否会欺骗链接器。您还必须修改链接器脚本。不值得

你的另一个问题来自于这个问题:

对于分支,这很好:

LDR R6, =0x24000
ADD R6, #1       @ (set lsb to 1)
BX R6
或者保存一条指令,然后执行此操作

LDR R6, =0x24001
BX R6
如果您想要分支链接,并且您知道地址,并且您处于thumb模式,并且想要获得thumb代码,那么

  ldr r6,=0x24001
  bl thumb_trampoline
  ;@returns here
  ...
.thumb_func
thumb_trampoline:
  bx r6
如果您是在arm模式下启动,并且希望在您已经知道的地址获取thumb代码,则几乎完全相同

  ldr r6,=0x24001
  bl arm_trampoline
  ;@returns here
  ...
arm_trampoline:
  bx r6
您必须知道,您可以通过这种方式垃圾处理r6(确保r6没有保存一些调用此代码的代码所使用的值)


非常抱歉用另一个答案误导您,我可以发誓mov lr,pc拉入lsbit作为一种模式,但事实并非如此。

接受的答案达到了预期的目标,但要完全按照要求回答问题,您可以使用.eq指令将常量值与符号相关联,然后可以用作指令的操作数。这使装配工在必要时合成蹦床:

equ myFirmwareFunction, 0x12346570
.globl _start
        mov r0, #42
        b   myFirmwareFunction
它将生成以下程序集[1]

01000000 <_start>:
 1000000:   e3a0002a    mov r0, #42 ; 0x2a
 1000004:   eaffffff    b   1000008 <__*ABS*0x12346570_veneer>

01000008 <__*ABS*0x12346570_veneer>:
__*ABS*0x12346570_veneer():
 1000008:   e51ff004    ldr pc, [pc, #-4]   ; 100000c <__*ABS*0x12346570_veneer+0x4>
 100000c:   12346570    data: #0x12345670
01000000:
1000000:e3a0002a mov r0,#42;0x2a
1000004:eaffffff b 1000008
01000008 :
__*ABS*0x12346570_单板():
1000008:e51ff004 ldr pc,[pc,#-4];100000摄氏度
100000c:12346570数据:#0x12345670
如果immediate值与PC足够接近,偏移量将适合immediate字段,则跳过verneer(蹦床),您将获得一条指向指定常量地址的分支指令

[1] 将codesorcery(2009q1)工具链用于:
arm none eabi gcc-march=armv7-a-x assembler test.spp-o test.elf-Ttext=0x1000000-nostdlib

现在,如果您看到指令bl的编码是相对的,而不是绝对的,那么您只能分支到相对于程序计数器的地址。这是一个固定字长的指令集,您可能希望使用bx,它允许模式切换,但仅限于寄存器,如我上面所示使用它,或者如果可能,根据模式(可能仅在arm模式下工作)ldr pc,=函数名,这是一个长分支,使用另一个字(如可变字长指令)但是像bx是一个分支,而不是一个分支链接。谢谢,很好的解释。但是我希望能够在固件中添加到现有的thumb函数,我知道它的地址。这样我就不必去搞乱LR,但我不知道如何把它放到汇编程序中。。。或链接器脚本。。。就像我做BL标签一样,我必须告诉汇编程序标签所在的地址。。。因为它不在我的代码中。。。我不知道如何告诉它我会接受答案,这是很好的信息。。。如果有人知道。。请回复。一定有办法的。链接器如何链接到您导入的函数(代码调用的外部函数)-在asm或链接器脚本中使用什么指令?啊,我明白您的意思了。是的,你需要让链接器知道带有特定地址的标签。不知道怎么做,你可以取消选中我的答案,让其他人试试,没问题…我的拇指到手臂的代码断了!这样不行,请看这个问题