THUMB 或 ARM 模式下的动态汇编

Dynamic assembly in THUMB or ARM mode

据我所知,在 GNU 中可以使用统一语法,有时可以让 ARM 代码自动编译为 Thumb 代码。在某些情况下,这可以显着提高代码密度,但在许多情况下,它只是行不通,因为有些 ARM 指令无法在 Thumb 模式下执行。

我想要的是 GNU AS 在尝试以 Thumb 模式编译功能块时“回退”到 ARM 的某种方式。因此,如果有一条指令在 Thumb 中不起作用,它会在 ARM 模式下编译,但如果可以,那么我会得到代码缩减。

无需为大约 50,000 个存根函数中的每一个添加注释。

我试过谷歌搜索但没有找到任何东西,所以任何帮助将不胜感激。

编辑:

感谢输入,我能够获得一个 makefile,它首先尝试构建 Thumb,然后成功回退到 ARM。它现在很慢,但它有效。非常高兴,感谢所有的输入。

assembler 应该有这个功能,但 GAS 没有。 GAS 是 designed as a one-pass assembler 所以它不喜欢回溯。 (对于 x86,它确实进行了分支置换优化,因此它可以在发出代码之前对其表示代码的内部数据结构进行多次传递。这可能足以也可能不足以添加这样的功能。)

有一些仅限 Thumb 的指令,例如 tbb。如果一个函数不能在 Thumb ARM 模式下 assembled,assembler 将不得不告诉你它和错误。但对于某些用例来说,这仍然是一种有用且可取的行为。对于最初只为 ARM 编写的旧代码,您不会 运行 遇到这个问题。


部分问题在于了解函数 end 的位置。 MASM 风格的 proc / endp 模型将使这成为可能,但 ARM 汇编(GAS 或 Keil/ARMASM)不会那样做。 而只是函数顶部的标签。

您可以引入一个新指令,例如 .auto_func(相对于 .thumb_func.arm_func),并将这三个指令中的任何一个视为该假设特征的函数之间的边界。

当看似无害的指令导致整个函数回退到 ARM 时,您还需要一些东西来警告您,例如 add r0, #123。 (而不是 adds。)

对于支持 Thumb-2 的 CPU,add 可以使用 32 位 Thumb-2 编码进行编码。例如not Cortex-M0。 M0 根本不支持 ARM 模式,但很容易 CPU 记住,因为(大部分)不支持 Thumb 2 来测试 assemble.


原来是我误解了这个问题。我在下面的部分回答指出,在单个函数中进行混合是不可行的(或一个好主意)。

如果您确实使用了不能编码为 16-位(或 32 位 Thumb-2,它显着扩展了您在 Thumb 模式下的功能)。

在 Thumb 和 ARM 模式解码之间切换 CPU 需要一个“thumb 互通”分支指令,如 bx <reg>blx <relative address>,因此每个 ARM-only 指令都需要两个额外的分支指令(除非多个 ARM 指令背靠背。或者对于不那么天真的 assembler,当 ARM 指令之间只有 1 或 2 个 Thumb 指令时,请不要费心切换)。

因此直线解码可以实现正确性(但不是性能)(尽管如果没有 Thumb 互通分支采用相对地址而不将 LR 设置为 return地址)。如果它需要破坏像 lr 这样的寄存器,那么与编写的 asm 相比,这甚至不是真正正确的。您必须将 lr 视为类似于 MIPS $at(assembler 临时),assembler 可以在扩展您的源代码伪代码时用作划痕指令转换为多条机器指令。

条件分支和跳转表都可以工作,如果目标指令是 ARM 并且分支在一个 Thumb 模式块。跳转表可以将标签地址作为缩略图模式的 addr+1。但这意味着您根本无法使用 tbb and tbh 指令,除非每个目标也处于 Thumb 模式,因为它们不进行交互操作并且需要寄存器才能正确模拟。

因此,您唯一真正难以正确完成的事情是计算跳跃,其中某些目标处于不同模式。 (如 add r0, pc, r1 / b r0)。 assembler 无法生成代码来修复地址。因此,可以编写尽可能多地阻止使用 Thumb 的尝试的代码。

当然,出于性能原因,所有这些都是不可能的, 即使在没有破坏的情况下是可能的 lr,所以要找出可实现的正确性的限制虽然尝试愚蠢的计算机技巧很有趣。 :P

问问也没什么坏处,但事实证明你找不到任何东西是有充分理由的。