从thumb指令集开始,编码就一直存在。
0001110xxxnnnddd
是一种
adds rd,rn,#xxx
如果您可以修改标志,那么它是更有效的编码方式。
伪指令mov rd,rn表示标志可能会改变(根据文档和gas的表现)。因此原始编码没有问题。
现在由解決器选择是否使用immed == 0时打印mov rd,rn vs adds rd,rn,#0,两种反汇编都是正确的。
现在带有一个高位寄存器和一个低位寄存器的mov表示:
Unlike the low register MOV instruction described in MOV (2) on page A7-73, this instruction does not change the flags.
现在进入了汇编语言阶段,这完全由汇编器定义,而不是目标(不是 ARM),还有可怕的统一语法等等。因此,现在它变成了一个特定于工具的事情。例如,Gnu 汇编器不喜欢使用 adds 的方式(非统一语法,我发现在 thumb 中使用它要容易得多),你执行 add 命令会得到 adds。
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1
arm-none-eabi-as so.s -o so.o
so.s: Assembler messages:
so.s:5: Error: instruction not supported in Thumb16 mode -- `adds r0,r1,#0'
.thumb
add r0,r1,#0
mov r0,r1
movs r0,r1
00000000 <.text>:
0: 1c08 adds r0, r1, #0
2: 1c08 adds r0, r1, #0
4: 1c08 adds r0, r1, #0
对于Movs指令,它非常好。
0x1c08 = 0x0001110000001000,这是一个Adds Thumb指令,回到armv4t的时期,当所有这一切开始时。
.syntax unified
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1
0: f101 0000 add.w r0, r1, #0
4: 4608 mov r0, r1
6: 1c08 adds r0, r1, #0
8: 0008 movs r0, r1
所以在这种情况下,它是一种不同的汇编语言(相同的工具不同的汇编语言)。
因此,此汇编语言尊重add vs adds和mov vs movs。
为了进行没有标志位的加法,您需要使用thumb2编码。没有标志位的mov是高寄存器mov 0x4608 0100011000001000 0x46xx。
adds仍然是原来的样子,而movs现已被编码为左移,但是它们不会反汇编成 lsl r0, r1,#0,而是反汇编成mov r0,r1,这让您更容易理解,而不仅仅是将mov反汇编为add。为什么他们不使用adds?这里还有另一个问题,如果您查看arm arm中低寄存器的mov指令,至少在旧的arm arm中,它描述了标志位的变化并显示了adds编码。但是如果您查看lsl的说明,标志位是不同的,在最长生命周期的ARM ARM(带有thumb)中描述时,lsl不能替换带标志位的mov。
好了,这很有意义,在旧版的arm arm中,它们很有帮助。如果立即数为零,则没有进位,因此它被描述为设置为零以及带符号溢出标志。
Lsl在一个文档中将进位保持不变,而在另一个文档中将其设置为零。因此,在指令的实现中可能会发生一些变化或者其中一个ARM ARM是错误的(这经常发生)。
简短地说,mov rd,rn一直是伪指令,并记录为adds,反汇编器可以选择以任何一种方式打印它,这取决于反汇编器。
汇编语言由工具定义而不是目标,因此工具确定在其语法中使用哪个标志解决方案,并且可以在adds、mov高寄存器、thumb2编码或其他编码之间进行选择。
我们不知道为什么会选择一种编码,而有多种相等编码可用时,通常会选择较短的编码(x86中的xor vs带零立即数的mov)。但是lsl vs add vs sub vs ...
在arm文档中您还会找到其他伪指令(记录了其工具的汇编语言),以及汇编器添加到其汇编语言中的伪指令,如nop。
.thumb
nop
mov r8,r8
mov r4,r4
00000000 <.text>:
0: 46c0 nop
2: 46c0 nop
4: 1c24 adds r4, r4, #0
现在的问题是为什么他们不只是将其打印出来:
0: 1c08 mov r0,r1
我也很喜欢反汇编器隐含了分号作为注释边界的功能,而汇编语言奇怪地不支持这一点(就像地球上其他大多数汇编器一样)。
当然,反汇编器不知道创建该机器码的汇编器是什么,因此对于显示伪指令的情况,同时展示两者将会很好。
adds Rd,Rn,#0
更改为lsls Rd,Rn,#0
,现在有一个真正的不设置标志位的mov Rd,Rn
,使用前一个Hi / Lo寄存器移动指令的扩展形式。 - fuz