ARM 汇编指令“ADDS Rn, #1”与“ADDS Rd, Rn, #1”

jeb*_*boo 3 assembly arm

  1. ADDS Rn, #1
  2. ADDS Rd, Rn, #1

ARM 文档指定在第一条指令中 Rd 是否可选,并且如果省略 Rd 等于 Rn。所以编译时两条指令应该是相同的。但我们的编译器正在生成:

二进制0x3F01SUBS R7,#1 和二进制0x1E7F​SUBS R7,R7,#1

使用指令解码 0x3F01 等于 001 11 111 00000001 001

001 -> 加/减/比较/移动立即数

11 -> 操作码减去imm

111 -> R7

00000001 -> 值 1

使用指令译码

0x1E7F 等于 000111 1 001 111 111

000111 -> 加/减寄存器

1 -> 减去立即数

001 -> 值 1

111 -> R7

111 -> R7

所以两条指令都执行相同的操作。知道为什么编译器可能会生成不同的二进制文件吗?

Mar*_*nau 6

ARM 文档指定在第一条指令中 Rd 是否可选,并且如果省略 Rd 等于 Rn。所以编译时两条指令应该是相同的。

首先,您应该注意有两种不同的 ARM 指令集:“传统”32 位指令集和“Thumb”指令集。

您的 CPU 显然使用“Thumb”指令集。

许多有关 ARM 指令集的表述都指的是“传统”指令集。

在传统指令集中,两种形式(SUBS R7, #1和SUBS R7, R7, #1)确实产生相同的指令:0xE2577001。

然而,在“Thumb”指令集中,有两种不同的编码:

SUBS Rd, Rn, #immRd允许为和指定两个不同的寄存器Rn,但只允许 0...7 范围内的立即数。

SUBS Rd, #imm只允许单寄存器形式,但允许 0...255 范围内的立即数。

然而,SUBS R7, R7, #1并SUBS R7, #1做同样的事情。

知道为什么编译器可能会生成不同的二进制文件吗?

如果您显式键入SUBS R7, R7, #1或SUBS R7, #1汇编代码?

因为您可能还键入SUBS R7, R6, #1或SUBS R7, #90。在这些情况下,编译器必须以不同的方式处理这两种变体!

因此它总是以不同的方式处理这两个变体,因为它会花费更多的精力来检查两个寄存器是否相等或检查立即数是否小于 8。