18

我刚开始学习ARM汇编语言,不清楚如何使用MOV将立即数转移到寄存器中。

从 ARM 参考手册和我的教科书中,都说 MOV 指令后面的立即数范围是 0-255。但是当我在自己的 PC 上使用 ADS 1.2 IDE 进行测试时,指令

MOV     R2, #0xFFFFFFFF

表现良好。根据规范,数字 0xFFFFFFFF 是否超出范围?

4

7 回答 7

16

请记住,作为合并到 ARM 操作码中的桶形移位器的一部分,ARM 可以对立即数执行一组特定的操作。

这篇小文章对 ARM 汇编程序可以用来将大立即数放入 ARM 指令的小可用空间中的一些技巧进行了最清晰的解释:

本文讨论了在生成 MVN 操作码以加载立即值的按位补码的具体示例中可能使用的技巧。

这些类型的操作不能用所有的立即数来完成,但是 ARM 汇编器据说对此非常聪明(C 编译器当然也是如此)。如果无法执行移位/补码技巧,则通常将从 PC 相对位置加载该值,或者可能通过从多个指令“构建”该值来加载该值。

于 2010-04-12T18:58:30.440 回答
14

一条 ARM 指令只能编码一个立即数,该常数可以表示为一个 8 位立即数,按 2 的任意偶数次幂移位。

但是,还有一条MVN指令,它类似于MOV但将所有位反转。因此,虽然MOV R2, #0xFFFFFFFF不能编码为MOV指令,但可以编码为MVN R2, #0. 汇编器可能会很好地为您执行此转换。

于 2010-04-12T18:58:59.157 回答
3

MOV 指令可以接受 imm16 值或 Operator2 值(由于指令长度与内存对齐相反),它必须符合以下任何规则(复制自 CortexM 指令集手册,X 和 Y 是任何十六进制值):

  • 可以通过将 8 位值左移 32 位字中的任意位数来生成的任何常数。
  • 0x00XY00XY 形式的任何常量。
  • 0xXY00XY00 形式的任何常量。
  • 0xXYXYXYXY 形式的任何常量。

这就是接受 0xFFFFFFFF 的原因(符合第四条规则)。

如果你想组装你自己的 32 位常数,你可以使用指令MOVT,它写入寄存器的上半部分。

于 2014-11-05T17:00:41.940 回答
2

很难确定给定的常数是否在有效范围内。

就像 Matthew 已经提到的那样,汇编器通过用类似的否定指令替换给定的指令来帮助您,例如 mov/mvn、cmp/cmn、tst/tne 等。

于 2011-11-07T04:59:15.107 回答
1

您可能会从原始值的符号扩展中看到伪影。如果您用来查看反汇编的工具将 0..255 作为有符号字节处理,那么当它将它加载到更大的 int 类型(或寄存器)中时,它将用原始的符号位填充所有高位价值。或者换一种说法,如果 0xFF 是有符号字节,它的十进制值为 -1。把它放到一个 32 位寄存器中,十六进制看起来像 0xFFFFFFFF,它的十进制值仍然是 -1。

尝试使用没有设置高位的值,例如 0x7F。由于未设置符号位,我猜当加载到更大的 int 类型寄存器或字段时,它将用零填充高位。

编译器/汇编器也可能截断您提供的任何值。我认为这是源代码错误,但汇编程序是有趣的野兽。如果给它 0x7FF,它会编译为 0x7FF(未截断,大于 0..255)还是 0xFFFFFFFF(截断为 0..255,有符号字节)?

于 2010-04-12T18:48:18.153 回答
-1

如果您想将 0xffffffff 移动到寄存器中,您可以随时执行以下操作:

MOV R0, #-1

因为 0xffffffff 是 -1 的补码表示

于 2019-05-31T13:24:02.210 回答
-3

一种可能性是 ARM 汇编程序丢弃了数字的有效位并仅使用最低的 FF。

MOV 指令是许多 CPU 指令集中的主要内容,通常汇编器会解析目标寄存器的大小和提供的立即数。

例如,x86 集中的以下 MOV 指令是

MOV BL, 80h, ; 8bit
MOV BX, ACACh ;16bit
MOV EBX, 12123434h ; 32bit
于 2010-04-12T18:47:44.757 回答