2010-04-12 56 views
14

我刚开始学习ARM汇编语言,并不清楚如何使用MOV将立即数传送到寄存器中。如何在ARM中使用MOV指令作为第二个操作数

从ARM参考手册和我的教科书都可以看出,MOV指令后的立即数范围是0-255。但是当我在ADS 1.2 IDE的个人电脑上测试时,指令

MOV  R2, #0xFFFFFFFF 

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

希望有人能帮我一把。

问候。

回答

12

请记住,ARM可以对立即数值执行一些操作,作为集成到ARM操作码中的桶形移位器的一部分。

这个小文章有一些的ARM汇编程序可以使用,以适应大量直接进入次数ARM指令的小可用空间的招数最清晰的解释之一:

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

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

+0

@Michael谢谢你的提示。这就是我想知道的! :-) – 2010-04-12 19:12:02

+0

有谁知道**为什么**汇编程序会建立一些值,但会直接加载其他值?环视牛顿ROM代码(StrongArm 110)有很多“单指令加载”(比如“MOV r1,0x0c1b518”),但是我的所有代码都带有“构建加载” - 就像下面的代码一样: – 2012-01-16 16:00:47

+0

..(哎呀,提前发布错误)..就像“MOV r1,0x0C000000/ADD r1,r1,0x100000”。我认为这可能与处理器如何编码32位值有关。处理器微码使用单个MOV然后ADD添加数字是否更高效? – 2012-01-16 17:21:52

-1

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

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

例如从x86组下述MOV指令是

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

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

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

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

11

单条ARM指令只能编码一个立即数,它可以表示为一个8位立即数值,移位两个幂的任意一个甚至

但是,还有一个MVN指令,它与MOV类似,但会反转所有位。所以,虽然MOV R2, #0xFFFFFFFF不能编码为MOV指令,但它可以编码为MVN R2, #0。汇编器可能会为您执行此转换。

1

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

像马修已经提到,汇编借给你的手用类似的替换作出批示,否定的,如MOV/MVN,CMP/CMN,TST/TNE等

2

MOV指令可以接受imm16值或算子2的值(由于相对于存储器对准指令长度),必须符合下列任一规则(从CortexM指令集手动复制,X和Y是任何十六进制值):

  • 任何恒定,可以是通过在32位字内移位任意位数的8位值而产生。
  • 任何形式为0x00XY00XY的常量。
  • 任何形式为0xXY00XY00的常量。
  • 任何形式为0xXYXYXYXY的常量。

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

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

+0

那为什么不允许0x45454545?其实也是0x00450045。 – JSmyth 2015-05-27 16:30:54

相关问题