搭档遇到这样一个问题:
在eVC编译出的汇编代码中我看到这样的句子:
mov r2, #0xFF, 28 和 orr r2, r2, #0xB
这样得到的成果时 r2=#0xffb ,
他企图更直接一点优化成一句:MOV r2,#0xffb
可是这样之后编译就出了问题:error A0092: no immediate rotate operand can be created: 4091
————————————我是无辜的分割线——————————–
在 mov r2,#0xffb 这句中,不是MOV的用法犯错,而是当即数用法犯错。
当即数的用法界说在Arm Architechture Reference Manual(简称ARMARM)的A5-4页开端
很重要的一段:
An immdediate operand value is formed by rotating an 8-bit constant (in a 32-bit word) by an even number of bits (0,2,4,8,26,28,30). Therefore, each instruction contains an 8-bit constant and a 4-bit rotate to be applied to that constant.
Some valid constants are:
0xFF, 0x104, 0xFF0, 0xFF00, 0xFF000, 0xFF000000, 0xF000000F
Some invalid constants are:
0x101, 0x102, 0xFF1, 0xFF04, 0xFF003, 0xFFFFFFFF, 0xF000001F
而在下面的A5-6页中说到
shifter_operand = immed_8 Rotate_Right (rotate_imm * 2)
以及
Some values of
所以,综上所述,首要解说清楚了 mov r2,#0xFF,28 一句。28并不是第三个操作数,而是和0xFF并在一同作为当即数运用,将0xFF循环右移28位。而这儿有必要着重右移XX位有必要是个偶数,由于它将等于 rotate_imm*2,那么在该指令的机器码中rotate_imm = 14, 也就是在32-BIT的机器码中第11到第8 bit = 1110B
然后再来看 mov r2,#0xFFB 的犯错状况
0xFFB = 111111111011B,很显然依照 shifter_operand = immed_8 Rotate_Right (rotate_imm * 2) 的公式, shifter_operand = 0xFFB时无法得到有用的 immed_8 和 rotate_imm, 所以编译呈现过错 error A0092: no immediate rotate operand can be created: 4091 也能够理解了,它应该是说无法生成rotate_imm,实际上immed_8也是无法生成的。
关于当即数怎么分解成immed_8和rotate_imm,能够参阅上面给出的valid constants和invalid constants,简而言之,假如该当即数能够分解成一个8-bit的二进制数循环右移偶数位,那么这个当即数是有用的,反之无效。
在上面的比如中,想要得到 r2 = 0xFFB 那么在汇编里就有必要走两步了,一步是无论怎么无法抵达的。