gpt4 book ai didi

gcc - 在 Thumb 代码中使用 BX 调用 Thumb 函数,或跳转到另一个函数中的 Thumb 指令

转载 作者:行者123 更新时间:2023-12-03 20:23:41 33 4
gpt4 key购买 nike

我正在尝试学习对固件修改有用的技能(我没有源代码)
这些问题涉及使用 BX 从拇指代码跳转或调用其他现有拇指代码。

  • 我如何使用 BX 从我的 THUMB 代码跳转到现有固件 THUMB 代码。
  • 我如何使用 BX 从我的 THUMB 代码中调用现有的 THUMB 函数(必须先设置 LR)。

  • 我的理解是 cpu 查看 lsb 位(位 0),我必须确保将其设置为 1为了保持cpu状态为“拇指状态”。
    所以我想我必须加 1,才能将 lsb 位设置为 1。

    所以...说我只想跳到 0x24000(在一些现有的 THUMB 代码中间)
    LDR R6, =0x24000
    ADD R6, #1 @ (set lsb to 1)
    BX R6

    我认为这是正确的吗?

    现在说我想使用 BX 调用现有的拇指函数,并且我希望它返回给我,所以我需要将 LR 设置为我希望它返回的位置。

    假设我要调用的函数在 0x24000
    它是 suggested to me使用:
    ldr r2, =0x24000
    mov lr, pc
    bx r2

    这是我不明白的:
  • R2 中的地址没有设置 lsb 位...所以不会 bx r2切换模式到ARM模式??
  • LR..
    有人告诉我,PC 的地址为(当前指令的开始,+ 4)。
    在 Thumb 和 Arm 中,任何指令地址都必须对齐(16 位或 32 位),因此不会将 LSB 位设置为 1。只有奇数的 LSB 位设置为 1。

  • 因此,在上面的代码中,我将 LR 设置为 (PC),该地址也没有设置 lsb 位 1。因此,当我调用的函数进入尾声时, BX LR , ... 嗯.. 怎么能返回到我的 THUMB 代码呢?我肯定错过了什么...

    通常 BL 用于调用函数。手册说 BL 指令将 LR 设置为下一行代码...
    这是否意味着(通常使用的) BL THUMB 指令,将 LR 设置为 return addr + 1自动地?

    最佳答案

    哇,谢谢你叫我出来这个。我知道我在 http://github.com/dwelch67/yagbat 中尝试了 qemu 代码并认为 XPUT32 以您描述的方式调用 PUT32,并且它起作用了。但它似乎不起作用。我创建了许多实验并且很惊讶,这不是我所期望的。现在我明白了为什么 gnu 链接器会做它所做的。抱歉,这是一个很长的回复,但我认为它非常有值(value)。这是一个令人困惑的话题,我知道多年来我一直认为电脑会拖拽模式位,但事实并非如此。

    在我开始下面的实验之前,如果你要这样做:

    LDR R6, =0x24000
    ADD R6, #1 @ (set lsb to 1)
    BX R6

    因为您碰巧知道 0x24000 是拇指代码,所以只需执行以下操作:
    LDR R6, =0x24001
    BX R6

    是的,如果您碰巧知道硬编码地址 0x24000 是拇指指令,这就是您从 arm 或拇指分支到拇指代码的方式 bx带有一个包含地址加一的寄存器。

    如果您不知道地址但知道地址名称:
    ldr r6,=something
    bx r6

    这样做的好处是某些东西可以是 ARM 或拇指地址,并且上面的代码可以正常工作。好吧,如果链接器正确地知道 ARM 或拇指是什么类型的标签,它就可以工作,如果搞砸了,它将无法正常工作,正如您在此处看到的:
    .thumb
    ping:
    ldr r0,=pong
    bx r0
    .code 32
    pong:
    ldr r0,=ping
    bx r0


    d6008148 <ping>:
    d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
    d600814a: 4700 bx r0

    d600814c <pong>:
    d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
    d6008150: e12fff10 bx r0

    d6008158: d600814c strle r8, [r0], -ip, asr #2
    d600815c: d6008148 strle r8, [r0], -r8, asr #2

    那没用 pong想从 0xD600815C 中提取拇指地址,但得到了一个 ARM 地址。

    顺便说一句,这都是 gnu 汇编程序的东西,对于其他工具,您可能需要做其他事情。对于气体,您需要输入 .thumb_func在要声明为拇指标签的标签之前(术语 func 暗示函数具有误导性,不要担心 .thumb_func 意味着它只是一个汇编器/链接器游戏)。
    .thumb
    .thumb_func
    ping:
    ldr r0,=pong
    bx r0
    .code 32
    pong:
    ldr r0,=ping
    bx r0

    现在我们得到了我们想要的:
    d6008148 <ping>:
    d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
    d600814a: 4700 bx r0

    d600814c <pong>:
    d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
    d6008150: e12fff10 bx r0

    d6008158: d600814c strle r8, [r0], -ip, asr #2
    d600815c: d6008149 strle r8, [r0], -r9, asr #2

    0xD600815C 有 lsbit设置,以便您不必做任何工作。例如,当您调用 C 函数时,编译器会处理所有这些。对于汇编程序,尽管您必须使用该 .thumb_func (或其他一些指令,如果有的话)让气体知道这是一个拇指标签并设置 lsbit为你。

    所以下面的实验是在一个 ARM11 的 mpcore 上完成的,但我也试过 testthumb ARM7TDMI 和 qemu 上的函数 1 到 4 具有相同的结果。
    .globl testarm
    testarm:
    mov r0,pc
    bx lr

    armbounce:
    mov r0,lr
    bx lr

    .thumb
    .thumb_func
    .globl testthumb1
    testthumb1:
    mov r0,pc
    bx lr
    nop
    nop
    nop
    bounce:
    bx lr
    .thumb_func
    .globl testthumb2
    testthumb2:
    mov r2,lr
    mov r0,pc
    bl bounce
    bx r2
    nop
    nop
    nop
    .thumb_func
    .globl testthumb3
    testthumb3:
    mov r2,lr
    mov lr,pc
    mov r0,lr
    bx r2
    nop
    nop
    nop
    .thumb_func
    .globl testthumb4
    testthumb4:
    push {lr}
    ldr r2,=armbounce
    mov r1,pc ;@ -4
    add r1,#5 ;@ -2
    mov lr,r1 ;@ +0
    bx r2 ;@ +2
    pop {r2} ;@ +4
    bx r2
    .thumb_func
    .globl testthumb5
    testthumb5:
    push {lr}
    ldr r2,=armbounce
    mov lr,pc
    bx r2
    pop {r2}
    bx r2
    .thumb_func
    .globl testthumb6
    testthumb6:
    push {lr}
    bl testthumb6a
    .thumb_func
    testthumb6a:
    mov r0,lr
    pop {r2}
    bx r2

    .thumb_func
    .globl testthumb7
    testthumb7:
    push {lr}
    bl armbounce_thumb
    pop {r2}
    bx r2

    .thumb_func
    .globl testthumb8
    testthumb8:
    push {lr}
    bl armbounce_thumb_two
    pop {r2}
    bx r2

    .align 4
    armbounce_thumb:
    ldr r1,[pc]
    bx r1
    .word armbounce

    nop
    .align 4
    armbounce_thumb_two:
    bx pc
    nop
    .code 32
    b armbounce

    变成:
    d60080b4 <testarm>:
    d60080b4: e1a0000f mov r0, pc
    d60080b8: e12fff1e bx lr

    d60080bc <armbounce>:
    d60080bc: e1a0000e mov r0, lr
    d60080c0: e12fff1e bx lr

    d60080c4 <testthumb1>:
    d60080c4: 4678 mov r0, pc
    d60080c6: 4770 bx lr
    d60080c8: 46c0 nop ; (mov r8, r8)
    d60080ca: 46c0 nop ; (mov r8, r8)
    d60080cc: 46c0 nop ; (mov r8, r8)

    d60080ce <bounce>:
    d60080ce: 4770 bx lr

    d60080d0 <testthumb2>:
    d60080d0: 4672 mov r2, lr
    d60080d2: 4678 mov r0, pc
    d60080d4: f7ff fffb bl d60080ce <bounce>
    d60080d8: 4710 bx r2
    d60080da: 46c0 nop ; (mov r8, r8)
    d60080dc: 46c0 nop ; (mov r8, r8)
    d60080de: 46c0 nop ; (mov r8, r8)

    d60080e0 <testthumb3>:
    d60080e0: 4672 mov r2, lr
    d60080e2: 46fe mov lr, pc
    d60080e4: 4670 mov r0, lr
    d60080e6: 4710 bx r2
    d60080e8: 46c0 nop ; (mov r8, r8)
    d60080ea: 46c0 nop ; (mov r8, r8)
    d60080ec: 46c0 nop ; (mov r8, r8)

    d60080ee <testthumb4>:
    d60080ee: b500 push {lr}
    d60080f0: 4a15 ldr r2, [pc, #84] ; (d6008148 <armbounce_thumb_two+0x8>)
    d60080f2: 4679 mov r1, pc
    d60080f4: 3105 adds r1, #5
    d60080f6: 468e mov lr, r1
    d60080f8: 4710 bx r2
    d60080fa: bc04 pop {r2}
    d60080fc: 4710 bx r2

    d60080fe <testthumb5>:
    d60080fe: b500 push {lr}
    d6008100: 4a11 ldr r2, [pc, #68] ; (d6008148 <armbounce_thumb_two+0x8>)
    d6008102: 46fe mov lr, pc
    d6008104: 4710 bx r2
    d6008106: bc04 pop {r2}
    d6008108: 4710 bx r2

    d600810a <testthumb6>:
    d600810a: b500 push {lr}
    d600810c: f000 f800 bl d6008110 <testthumb6a>

    d6008110 <testthumb6a>:
    d6008110: 4670 mov r0, lr
    d6008112: bc04 pop {r2}
    d6008114: 4710 bx r2

    d6008116 <testthumb7>:
    d6008116: b500 push {lr}
    d6008118: f000 f80a bl d6008130 <armbounce_thumb>
    d600811c: bc04 pop {r2}
    d600811e: 4710 bx r2

    d6008120 <testthumb8>:
    d6008120: b500 push {lr}
    d6008122: f000 f80d bl d6008140 <armbounce_thumb_two>
    d6008126: bc04 pop {r2}
    d6008128: 4710 bx r2
    d600812a: 46c0 nop ; (mov r8, r8)
    d600812c: 46c0 nop ; (mov r8, r8)
    d600812e: 46c0 nop ; (mov r8, r8)

    d6008130 <armbounce_thumb>:
    d6008130: 4900 ldr r1, [pc, #0] ; (d6008134 <armbounce_thumb+0x4>)
    d6008132: 4708 bx r1
    d6008134: d60080bc ; <UNDEFINED> instruction: 0xd60080bc
    d6008138: 46c0 nop ; (mov r8, r8)
    d600813a: 46c0 nop ; (mov r8, r8)
    d600813c: 46c0 nop ; (mov r8, r8)
    d600813e: 46c0 nop ; (mov r8, r8)

    d6008140 <armbounce_thumb_two>:
    d6008140: 4778 bx pc
    d6008142: 46c0 nop ; (mov r8, r8)
    d6008144: eaffffdc b d60080bc <armbounce>
    d6008148: d60080bc ; <UNDEFINED> instruction: 0xd60080bc
    d600814c: e1a00000 nop ; (mov r0, r0)

    以及调用和打印所有这些函数的结果:
    D60080BC testarm
    D60080C8 testthumb1
    D60080D6 testthumb2
    D60080E6 testthumb3
    D60080FB testthumb4
    testthumb5 crashes
    D6008111 testthumb6
    D600811D testthumb7
    D6008127 testthumb8

    那么所有这些是做什么的,它与您的问题有什么关系。这与从拇指模式(也从更简单的 ARM )调用混合模式有关

    多年来,我一直在这个级别对 ARM 和拇指模式进行编程,不知何故一直犯了这个错误。我以为程序计数器总是保持这种模式 lsbit ,我知道您知道在执行 bx 指令时要设置或不设置它。

    在 ARM 架构引用手册中对 ARM 处理器的 CPU 描述的早期(如果您正在编写汇编程序,您应该已经有了这个,如果没有,也许您的大部分问题都会得到解答)。
    Program counter Register 15 is the Program Counter (PC). It can be used in most
    instructions as a pointer to the instruction which is two instructions after
    the instruction being executed...

    所以让我们检查一下这到底意味着什么,这是否意味着在 arm 模式下两条指令,前面 8 个字节?在拇指模式下,提前两条指令,还是提前 4 个字节?

    所以 testarm验证程序计数器是否超前 8 个字节。这也是两个指令。
    testthumb1验证程序提前 4 个字节,在这种情况下也是两条指令。
    testthumb2 :
    d60080d2:   4678        mov r0, pc
    d60080d4: f7ff fffb bl d60080ce <bounce>
    d60080d8: 4710 bx r2

    如果程序计数器前面有两个“指令”,我们将得到 0xD60080D8,但我们得到的是 0xD60080D6,它比前面四个字节,这更有意义。 Arm 模式提前 8 个字节,thumb 模式提前 4 个字节,不会干扰正在执行的代码之前的解码指令(或数据),只需添加 4 或 8。
    testthumb3是希望 mov lr,pc很特别,其实不是。

    如果您还没有看到模式, lsbit程序计数器的未设置,我想这对于例如分支表是有意义的。所以 mov lr,pc在拇指模式下不会为返回设置链接寄存器。
    testthumb4如果您在 mov r1,pc 之间更改该指令序列,则会以一种非常痛苦的方式获取程序计数器,无论该代码发生在何处结束,并根据精心放置的指令计算返回地址。和 bx r2你必须返回添加。现在为什么我们不能做这样的事情:
    add r1,pc,#1
    bx r2

    用拇指指令你不能,用拇指2你可能可以。并且似乎有一些处理器 (armv7) 支持 arm 指令和 thumb/thumb2,所以你可能会想要这样做。但是您不会添加#1,因为thumb2 添加指令,如果有一个允许高位寄存器并具有三个操作数的指令将是一个4 字节的thumb 2 指令。 (您需要添加#3)。

    所以 testthumb5直接来自我向您展示的导致此问题的一部分的代码,并且它崩溃了。这不是它的工作原理,对不起,我误导了人们,我会尝试回去修补我使用过的 SO 问题。
    testthumb6是一个实验,以确保我们都没有疯。一切都很好,链接寄存器确实得到了 lsbit设置以便当您 bx lr后来它知道了那个位的模式。
    testthumb7 ,这是从 ARM 侧蹦床派生而来的,当您从 ARM 模式转到拇指模式时,您会看到链接器所做的 Action ,在这种情况下,尽管我将从拇指模式转到 ARM 模式。为什么链接器不能这样做?因为在拇指模式下,至少你必须使用一个低寄存器,而在游戏的这一点上,在编译代码之后,链接器无法知道它可以丢弃哪个寄存器。在 arm 模式下,虽然 ip 寄存器(不确定可能是 r12 是什么)可能会被丢弃,但我猜它是保留供编译器使用的。在这种情况下,我知道 r1可以被丢弃并使用它,这可以按需要工作。 armbounce 代码被调用,它在返回到哪里时获取链接寄存器,这是在 lsbit set 之后的拇指指令( bl armbounce_thumb )。在 testthumb7功能,正是我们想要的地方。
    testthumb8这就是 gnu 链接器在需要从拇指模式到 ARM 模式时的工作方式。 bl指令设置为去蹦床。然后他们做了一些非常非常棘手的事情,看起来很疯狂:
    d6008140 <armbounce_thumb_two>:
    d6008140: 4778 bx pc
    d6008142: 46c0 nop ; (mov r8, r8)
    d6008144: eaffffdc b d60080bc <armbounce>

    一个 bx pc .我们从上面的实验中知道 pc前面四个字节,我们也知道 lsbit未设置。因此,这意味着跳转到 ARM CODE 之后的四个字节。 nop是一个两字节的间隔,那么我们必须在四个字节之前生成一条 ARM 指令并在四字节边界上对齐,然后我们将其无条件分支到我们要去的任何地方,这可能是 b 某物或 ldr pc ,= 取决于你需要走多远。非常棘手。

    原版 bl arm_bounce_thumb_two设置链接寄存器返回之后的指令 bl .蹦床不会修改链接寄存器,它只是执行分支。

    如果您想从 arm 进入拇指模式,请执行链接器的操作:
    ...
    bl myfun_from_arm
    ...


    myfun_from_arm:
    ldr ip,[pc]
    bx ip
    .word myfun

    当他们这样做时看起来像这样(从不同的二进制文件中抓取,不是在 0xD6008xxx 而是在 0x0001xxxx)。
       101f8:   eb00003a    bl  102e8 <__testthumb1_from_arm>


    000102e8 <__testthumb1_from_arm>:
    102e8: e59fc000 ldr ip, [pc] ; 102f0 <__testthumb1_from_arm+0x8>
    102ec: e12fff1c bx ip
    102f0: 00010147 andeq r0, r1, r7, asr #2

    所以无论这个 ip 寄存器是什么( r12 ?),他们都不介意把它扔掉,我想你可以自己扔掉它。

    关于gcc - 在 Thumb 代码中使用 BX 调用 Thumb 函数,或跳转到另一个函数中的 Thumb 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9368360/

    33 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com