ARM立即值编码和BIC指令

ARM immediate value encoding and BIC instruction

我是 ARM 世界的新手。在ARM Cortex-A系列:程序员指南(第71页)中,有一个BIC指令的例子:

BIC R0, R0, #0x800

根据文本,这基本上清除了 R0 中的第 11 位。我了解到 BIC 在这里的工作方式类似于 R0 = R0 & (~val)(请纠正我)。但我在这里不明白的是 #0x800 是如何按原样翻译成 1000 0000 0000 的。相反,它应该按照立即编码规则分成 4 位:8 位部分。

根据我对 ARM 常量编码的理解:

0x800 = 0000 1000 0000 0000

在这些位中,我们只考虑最后 12 位进行编码,在这 12 位中 - 前 4 位决定以 2 为步长向右旋转,最后 8 位是向右旋转的数字(考虑它作为 32 位)。所以在这种情况下,由于最后 8 位都是零,我应该在 2*8 次右旋转后得到 FFFF 0000

对于上面的完整 BIC 指令,它应该被视为:

R0 = R0 & (0000 FFFF)

我知道我哪里错了。有人可以纠正我吗

简短的回答是,您没有在程序集中包含编码文字字段,而是包含了您实际想要使用的有意义的值。汇编器的工作包括为指定的程序集确定(最好的,如果有的话)指令编码。


汇编程序负责将汇编中提供的值编码到指令的文字字段中。 #0x800 是文字。作为汇编程序员,你只需要确保文字是可编码的。

必须计算编码旋转会很烦人而且令人难以置信 error-prone。这种类型的转换是汇编代码和机器代码之间的主要区别。看实际生成的字面值字段,看汇编后的结果

这也导致了一些 ISA 中出现的汇编代码和机器代码之间的非一对一关系。


0x800直接就是0b1000_0000_0000.

组装

BIC R0, R0, #0x800

给我

02 0B C0 E3

所以 Operand2 字段是 0xB02。这意味着 Immediate 是 0x02,而 Rotate 是 0xB。取 0x00000002 并向右旋转 2 * 0xB,我们得到预期的 0x800.

你自己试试看吧

.syntax unified

bic r0,r0,#0x800
.thumb
bic r0,r0,#0x800

Disassembly of section .text:

00000000 <.text>:
   0:   e3c00b02    bic r0, r0, #2048   ; 0x800
   4:   f420 6000   bic.w   r0, r0, #2048   ; 0x800

A1编码

e3c00b02

101100000010 (b02)
1011 00000010

将位模式00000010右移11*2位,与左移10相同

00000010 0000000000
000000100000000000
000000 1000 0000 0000
0x800

T1编码

f420 6000
1111010000100000 0110000000000000
xxxxx1xxxxxxxxxx x110xxxx00000000

11100 0000000
11100 abcdefg

1bcdefg0 shifted left 3

1abc defg 0000
1000 0000 0000 
0x800

ARM 文档中都清楚地描述了所有内容。该指令指向文档(ARM ARM)的一部分,其中显示了立即位的编码。这不是mips,这是ARM;它不一定直接映射到指令中,ARM is/was 以其桶形移位器而闻名。

我避免使用 ARM 的一份文档(类型)是程序员指南,它不是他们更好的文档之一。

您需要相关核心的技术参考手册 (ARM TRM) 和该核心架构(在本例中为 armv7-ar)的架构参考手册 (ARM ARM)。

对于 ARM(aarch32,因为现在没有更好的术语)它是 8 个有效位,可以移动偶数次所以

bic r0,r0,#0x102

100000010 (0x102)
10000001 (0x81)

行不通

so.s:2: Error: invalid constant (102) after fixup

但是

bic r0,r0,#0x204

是 (0x81 >> 30)

拇指

bic r0,r0,#0x00220022

非常好,但不适用于 arm

so.s:3: Error: invalid constant (220022) after fixup

刚看了ARM文档,描述的很清楚