微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM 汇编的mov操作立即数的疑问

ARM 汇编的mov操作立即数的疑问

时间:11-09 来源:互联网 点击:

1. MOV can run faster than LDR.
2. LDR can move a data from a memory address to a register, MOV can only i) move data between two registers or ii) save a 8-bit immediate value to a register. e.g.
value1 DCD 0; this define an integer variable “value1” with address “=value1”

:

;A standard pair of statements for moving a data into a register
Ldr r0,=value1 ; 1) save the address of the variable value1 in r0
Ldr r1,[r0] ;2)use r0 as the address (pointer) to get value1 to r1
r1 Note: Mov cannot be used to achieve the same result, because mov,[r0] is not allowed
Answer part 2 : How similar are they?.
MOV is a real instruction, LDR is a pseudo instruction. If the immediate value is small, the assembler will use “mov” to implement it , otherwise it uses a literal pool to achieve the result.
e.g.
ldr r0,=14; the immediate value 14 <255, so it will be implemented using mov r0,#14, (see the use of # and = ) but if the immediate value is large than 255, e.g.
The assembler will generate code to place the constant 0x55 ldr r0,=0x55; for a large immediate value “mov” does work.in a nearby table in the code area. Then it uses an instruction to load a data from that table pointed by the program counter and an offset to fill up r0. The reason is because there is no way to fit a 2-bit data into a 32-instruction, and ARM design always want to make sure instructions are 32-bit. Details can be found athttp://www.keil.com/support/man/docs/armasm/armasm_chdcegci.htm
see also the directive “LTORG” for how to setup the table. Usually it is placed at the near by code area. You don’t need to worry too much because everything is automatic; you only need to place “LTORG” at the end of the code area as shown in the example at Keil.

但是我在看完上面这段话之后还是存在疑问:为什么”mov r3, #0x53”是可行的呢?

http://www.keil.com/support/man/docs/armasm/armasm_cihcdbca.htm

这个网页上对mov做了一些说明,截取有关立即数的部分如下:

Syntax
MOV{cond} Rd, #imm16
where:
imm16
is any value in the range 0-65535.

可以看到,这里说 立即数是16位的。

看到这里,确实把自己弄糊涂了。理清一下:

第一个说imm为8位是在网络上搜的一分资料,没有什么权威性,其可信程度也值得怀疑。

第二个是keil官司方网站里关于arm汇编的说明。

另外,在《arm体系结构与编程》这本书里,并没有说立即数的具体范围,在26页有一句:

mov r0, #0xfc0

明显立即数大于255了。

在144页有提到,“ldr伪指令读取的数据超过mov操作范围”。这说明mov可操作的立即数是有一定范围的,且比ldr小。

再来分析一下立即数的产生,其寻址方式是这样的:

11 8 7 0
+-+-+
Rotate Imm
+-+-+
[7:0] Unsigned 8 bit immediate value
[11:8] Shift applied to Imm
The immediate operand rotate field is a 4 bit unsigned integer which specifies a shift operation on the 8 bit immediate value. This value is zero extended to 32 bits, and then subject to a rotate right by twice the value in the rotate field.This enables many common constants to be generated, for example all powers of 2

1. 取低8位,先用0扩展为32位数
2. 将所得32位数循环右移 2*Rotate位,Rotate为[11:8]

来分析一句:mov r2, #300。反汇编如下:

8004: e3a02f4b mov r2, #300 ; 0x12c

立即数是直接放在指令内部的。

1. 取其低8位:0x4b

2. 扩展为32位:0x0 004b

3. 2*Rotate = 2*15 = 30

4. 循环右移30位(相当于左移2位)。即0100 1011 左移2位,得到1 0010 1100 ,即0x12c,十进制等于300

对于0x53的计算方法也是相同的。 mov r1, #0x53 这样写确实是可行的。

-

总结:对于mov 操作立即数时的操作范围,现在还是不确定。但经过这么多的分析以及实际写的几句测试代码,至少可以说明在Linux里,用arm-linux-as来编译,mov是可以操作32位的立即数的,不然vivi如何编译成功。(怀疑是否这跟实际汇编器相关。)

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top