【问题标题】:ARM: Why only 12 bits for immediate constants?ARM:为什么立即数只有 12 位?
【发布时间】:2013-12-03 00:27:00
【问题描述】:

这是什么意思:我只有 12 位用于立即常数,所以我可以只表示从 0 到 2^12 = 4096 的立即常数吗?操作数 2 如果是寄存器,可以有 32 位,但为什么立即数只有 12 位呢?这个数字是从哪里来的?

【问题讨论】:

  • 因为如果它有 32 位,就只有一条指令。数字是任意的。这是拥有足够的操作码来做有用的事情和给用户足够的常数范围之间的平衡。 ldr rX, =constant 是您可能感兴趣的另一种形式。值 4096 在两条指令中给出了“三字节”掩码。 ldr rx, =constant 可能被视为加载 32 位值的 64 位指令。
  • 同理为什么mips只能有16条固定指令长度
  • ldr rX, =constant 术语只是汇编器的辅助语句,不会直接转换为机器码。当constant 可以用12 位表示时,它转换为mov rX, #constant。如果不是,则该值存储在汇编器生成ldr rX, [pc, #offset] 附近的某个位置
  • @ensc 这正是我的观点。使用ldr rX, =constant。如果它需要超过 12 位,那么它在代码空间中是 64 位……您可以将其视为 64 位指令。我知道它们不是按顺序排列的,但它们将位于附近。只有关心缓存效果的人才会关心。通常,您应该在热路径之外加载常量。 area.ltorg 发出,通常称为literal pool

标签: assembly arm cpu-architecture instruction-set immediate-operand


【解决方案1】:

是的,只有 12 位可用意味着只能表示 212 = 4096 个不同的值。

这些状态可以以恒定步长分布,即。从 0 到 4095(忽略负值),或者它们可以非线性分布。正如here 解释的那样,ARM 体系结构使用 8 个最低有效位(256 个值)来表示一个数字,并使用 4 个最高有效位(16 个状态)来按 2 的幂放大或缩小这个数字。

由于这种缩放属性,ARM 架构能够表示大量有用的大数,而这些大数本来是无法表示的(即使是 16 位)。不幸的是,4096 个状态中的一些现在映射到与here 解释的相同的数字,因此这种方法只能表示 3073 个不同的值。

想要使用不在 3073 个有效立即数集合中的立即数的程序员可以使用需要多个时钟周期和/或内存的变通方法来获得所需的结果。

结论:这只是分配可用数字的一种不同方式,而不是使用 212 = 4096 表示 232 = 4294967296 个不同数字的(神奇)方式状态!

【讨论】:

    【解决方案2】:

    Arm 指令编码为 32 位长,与 x8086 指令中的指令编码不同,它是固定的。您不能在指令本身中编码任意 32 位常量。如果您查看 arm v7 指令集,对于算术指令,您可以在指令中直接编码 一些 32 位数字。这些数字被编码为 12 位(在指令中编码为 12 位的 32 位数字) .查看 arm 的架构手册。对不起,我没有给你的链接。

    【讨论】:

      【解决方案3】:

      它由指令集定义。例如。 MOV 指令编码为

      31 28 | 27 26 | 25 | 24 23 22 21 20 | 19   16 | 15    12 | 11        0      |
      cond  | 0  0  | I  | 1  1  0  1  S  | SBZ     | Rd       | shifter operand  |
      
      (see "ARM Architecture Reference Manual, 4.1.29 "MOV")
      

      “立即”常量在“移位器操作数”中编码,只有 12 位。其他指令有类似的定义有时是其他宽度。

      存在此限制是因为 - 与 x86 不同 - 使用 Thumb(2) 时,ARM 上的指令始终为 32 位或有时为 16 位。为了支持 12 位二进制数字无法直接表示的值,移位器操作数允许不同的寻址模式(例如左移、右移、旋转)。

      【讨论】:

      • 指令并不总是 32 位,例如 Thumb2。
      • Thumb(2) 和 ARM 是不同的指令集。但我会添加一个注释。
      • 我认为说立即常量只是“在移位器操作数中编码”也是错误的。立即数有多种类型,您描述的那一种不是问题中提到的那一种。您提到的称为“修改后的立即数”A5.2.4。问的问题与 imm12 更相关,它允许 [0-4095] 范围内的常量。
      • 问题根本没有提到指令或类型。但是没问题;关于价值范围的答案不正确,我会修复它。
      • 好的,但是这个立即数来自什么样的寄存器?我的意思是这是什么寄存器? 1-12是常规的,13,14,15是留给我认为的其他功能的...
      【解决方案4】:

      在 ARM 指令中通常是这样的,例如ADD and SUB

      imm12 是 0-4095 范围内的任意值。

      这样的指令通常是 4 个字节,32 位,但你不需要那么多位来告诉核心从 2 个寄存器中提取并将结果放入另一个寄存器。因此指令集架构允许您以某种方式使用剩余位以避免额外的内存使用。例如,如果您要从寄存器中提取 256,您可以从堆栈中加载该 256(这是内存且速度较慢),或者您可以将其嵌入到指令中,这样会更快。当然,这种方法的缺点是空间有限,在这种情况下为 12 位用于此类操作数的使用。

      立即数常量允许的值范围因指令而异,大多数时候汇编程序似乎将您的指令更改为其他指令以获得相同的效果 - 或者它提供伪指令来完成类似的工作(如ldr)。但是,有时它无法组装您的代码并失败。在这些情况下,最好返回 ARM ARM 并阅读有关嵌入立即常量的特定指令功能。

      【讨论】:

        猜你喜欢
        • 2020-06-29
        • 2021-01-12
        • 1970-01-01
        • 1970-01-01
        • 2020-07-13
        • 1970-01-01
        • 2016-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多