分类: LINUX
2008-11-07 15:29:06
------------------------------------我是无辜的分割线--------------------------------
在 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 那么在汇编里就必须走两步了,一步是无论如何无法到达的。