强制 GNU AS 使用替代方案

The*_*ter 1 assembly arm disassembly

我有一个 ARM 二进制文件和一些汇编代码。从二进制读取反汇编

1e40 -> subs r0,r0,#1

汇编代码中的指令读起来是一样的。(代码使用.syntax unified指令)

但是,当我使用 GNU AS(来自 ARM 2017 Q4 的 gcc 工具链)时,它会评估

subs r0,r0,#1

3801-> subs r0,#1

使用 objdump

我想这两个可能是相同的,但是我仍然想知道是否有一种方法可以选择第一个操作码而不是第二个操作码的生成,因为我相信这会导致我正在使用的设备出现问题。

too*_*ite 5

您没有说明架构,但由于它显然是 Thumb,所以我将使用 Cortex-M 作为基础。

\n\n

查阅《ARMv7-M应用级架构参考手册》,可以轻松解码操作码。尝试一下,这是一个很好的做法,并且在编写机器级代码时将其放在附近总是一个好主意。

\n\n

它们实际上是两个不同的指令,但效果相同。

\n\n

第一个操作码是指具有小型 3 位立即数(零扩展,范围 0\xe2\x80\xa67)的双寄存器(源、目标)操作。这里,两个寄存器恰好是同一个寄存器,这使得它实际上是单寄存器递减。

\n\n

第二个是带有 8 位立即数操作数的单寄存器减法(零扩展,范围 0\xe2\x80\xa6255)。目前尚不清楚为什么会得到两种不同的变体,但它们应该没有实际区别(至少对于 Cortex-M4 来说都需要一个时钟,如果其他架构具有不同的值,我会感到惊讶)。

\n\n

因此反汇编反映了实际指令。Gas 似乎将原始的两寄存器指令转换为单寄存器操作码。

\n\n

请注意,有多种操作可能会导致不同的操作码。对于所提供的信息,尚不清楚为什么选择他们。我认为,第二个更合理,第一个只有在涉及两个不同的寄存器时才有意义。

\n\n

如果您的代码有问题,则很可能是这条指令造成的。也许是时候启动调试器了。

\n

  • @The19thFighter:根据我对 UAL 的解释,汇编器可以自由使用两者中的任何一个。**如果**有任何问题,那就相反。但我可以向你保证,这个操作码的代码执行没有问题。当然,如果您使用肮脏的黑客技巧,例如自修改代码等,情况可能会有所不同。如果答案令人满意,请记得点赞和/接受。 (2认同)