我刚开始学习ARM汇编语言,并不清楚如何使用MOV将立即数传送到寄存器中。如何在ARM中使用MOV指令作为第二个操作数
从ARM参考手册和我的教科书都可以看出,MOV指令后的立即数范围是0-255。但是当我在ADS 1.2 IDE的个人电脑上测试时,指令
MOV R2, #0xFFFFFFFF
表现不错。根据规范,数字0xFFFFFFFF是否超出范围?
希望有人能帮我一把。
问候。
我刚开始学习ARM汇编语言,并不清楚如何使用MOV将立即数传送到寄存器中。如何在ARM中使用MOV指令作为第二个操作数
从ARM参考手册和我的教科书都可以看出,MOV指令后的立即数范围是0-255。但是当我在ADS 1.2 IDE的个人电脑上测试时,指令
MOV R2, #0xFFFFFFFF
表现不错。根据规范,数字0xFFFFFFFF是否超出范围?
希望有人能帮我一把。
问候。
请记住,ARM可以对立即数值执行一些操作,作为集成到ARM操作码中的桶形移位器的一部分。
这个小文章有一些的ARM汇编程序可以使用,以适应大量直接进入次数ARM指令的小可用空间的招数最清晰的解释之一:
本文讨论了可能在您的具体生成MVN操作码示例中使用的技巧,以加载立即值的按位补码。
这些类型的操作不能用所有即时值完成,但ARM汇编器据说非常聪明(当然C编译器也是如此)。如果不能执行移位/补充技巧,该值通常会从PC相对位置加载,或者可能通过从几条指令中“建立”值来加载。
一种可能性是ARM汇编器丢弃了数字的有效位并仅使用最低的FF。
MOV指令是许多CPU指令集中的主要组件,通常汇编器会解析目标寄存器的大小和正在提供的立即数。
例如从x86组下述MOV指令是
MOV BL, 80h, ; 8bit
MOV BX, ACACh ;16bit
MOV EBX, 12123434h ; 32bit
您可以看到从原始值的符号扩展工件。如果用于查看反汇编的工具将0..255作为有符号字节进行处理,那么当它将其加载到更大的int类型(或寄存器)中时,它将用原始符号位填充所有高位值。换句话说,如果0xFF是一个有符号的字节,它的十进制值就是-1。把它放到一个32位寄存器中,十六进制看起来像0xFFFFFFFF,其十进制值仍然是-1。
尝试使用没有设置高位的值,例如0x7F。由于符号位没有设置,我猜测它将填充高位为零时,加载到一个更大的int类型的寄存器或字段。
编译器/汇编器也可能会截断您提供的任何值。我认为它是一个源代码错误,但汇编器是有趣的野兽。如果你给它0x7FF,它是否编译为0x7FF(不截断,大于0..255)或0xFFFFFFFF(截断为0..255,有符号字节)?
单条ARM指令只能编码一个立即数,它可以表示为一个8位立即数值,移位两个幂的任意一个甚至。
但是,还有一个MVN
指令,它与MOV
类似,但会反转所有位。所以,虽然MOV R2, #0xFFFFFFFF
不能编码为MOV
指令,但它可以编码为MVN R2, #0
。汇编器可能会为您执行此转换。
确定给定的常量是否在有效范围内有点困难。
像马修已经提到,汇编借给你的手用类似的替换作出批示,否定的,如MOV/MVN,CMP/CMN,TST/TNE等
MOV指令可以接受imm16值或算子2的值(由于相对于存储器对准指令长度),必须符合下列任一规则(从CortexM指令集手动复制,X和Y是任何十六进制值):
这就是接受0xFFFFFFFF的原因(符合第4条规则)。
如果你想组装你自己的32位常数,你可以使用指令MOVT,它写入寄存器的上半部分。
那为什么不允许0x45454545?其实也是0x00450045。 – JSmyth 2015-05-27 16:30:54
@Michael谢谢你的提示。这就是我想知道的! :-) – 2010-04-12 19:12:02
有谁知道**为什么**汇编程序会建立一些值,但会直接加载其他值?环视牛顿ROM代码(StrongArm 110)有很多“单指令加载”(比如“MOV r1,0x0c1b518”),但是我的所有代码都带有“构建加载” - 就像下面的代码一样: – 2012-01-16 16:00:47
..(哎呀,提前发布错误)..就像“MOV r1,0x0C000000/ADD r1,r1,0x100000”。我认为这可能与处理器如何编码32位值有关。处理器微码使用单个MOV然后ADD添加数字是否更高效? – 2012-01-16 17:21:52