如何在ARM中使用MOV指令,并使用立即数作为第二个操作数

时间:2010-04-12 18:40:20

标签: assembly arm

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

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

MOV     R2, #0xFFFFFFFF

表现很好。根据规范,数字0xFFFFFFFF不在范围之外吗?

希望有人能帮助我。

问候。

7 个答案:

答案 0 :(得分:13)

请记住,ARM可以对立即值执行一组操作,作为包含在ARM操作码中的桶形移位器的一部分。

这篇小文章对ARM汇编程序可用于将大型立即数装入ARM指令的小可用空间的一些技巧有一个最清晰的解释:

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

这些操作不能用所有直接值来完成,但ARM组装者应该对它非常聪明(当然C编译器也是如此)。如果不能执行移位/补充技巧,则通常会从PC相对位置加载该值,或者可以通过“累积”来自多个指令的值来加载该值。

答案 1 :(得分:12)

单个ARM指令只能编码一个立即数,可以表示为8位立即数,移位任何偶数 2的幂。

但是,还有一个MVN指令,类似于MOV但反转所有位。因此,虽然MOV R2, #0xFFFFFFFF无法编码为MOV指令,但可以将其编码为MVN R2, #0。汇编程序可能会为您执行此转换。

答案 2 :(得分:2)

确定给定的常量是否在有效范围内有点困难。

就像马修已经提到过的那样,汇编程序通过用类似的,否定的指令替换给定的指令,如mov / mvn,cmp / cmn,tst / tne等。

答案 3 :(得分:2)

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

  • 通过将a中的任意位数左移8位值产生的任何常数 32位字。
  • 任何形式为0x00XY00XY的常量。
  • 任何形式为0xXY00XY00的常量。
  • 任何形式为0xXYXYXYXY的常量。

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

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

答案 4 :(得分:1)

您可能会看到原始值的符号扩展名中的工件。如果您用来查看反汇编的工具将0..255作为带符号的字节处理,那么当它将其加载到更大的int类型(或寄存器)时,它将使用原始的符号位填充所有高位值。换句话说,如果0xFF是有符号字节,则其十进制值为-1。将它放入32位寄存器,十六进制看起来像0xFFFFFFFF,其十进制值仍为-1。

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

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

答案 5 :(得分:0)

如果要将0xffffffff移至寄存器,则可以始终执行以下操作:

MOV R0, #-1

因为0xffffffff是-1的二进制补码表示形式

答案 6 :(得分:-2)

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

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

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

MOV BL, 80h, ; 8bit
MOV BX, ACACh ;16bit
MOV EBX, 12123434h ; 32bit