我刚开始研究ARM汇编语言,并不清楚如何使用MOV将立即数转移到寄存器中。
从ARM参考手册和我的教科书中可以看出,MOV指令后的立即数范围是0-255。但是,当我在ADS 1.2 IDE中使用我自己的PC进行测试时,指令
MOV R2, #0xFFFFFFFF
表现很好。根据规范,数字0xFFFFFFFF不在范围之外吗?
希望有人能帮助我。
问候。
答案 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是任何十六进制值):
这就是接受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