1. 因为对arm汇编有些指令还不能理解,特别是一些相似功能指令间的区别。偶然在网上搜到“faq ARM assembly”,其中描述的几个问题还是值得好好研究一下。

2. 慢慢的发现自己也不再害怕英文的文档了,耐心看至少也能懂个大概。大批经典的文章和书籍都是en文的,所以经常看英文文档是一个非常好的习惯。看看GNU的一些reference manual,哪个不是经典而又值得学习并研究的!

3. 学习别人写文档的风格,重点要注意条理性。能够把一个问题、一个知识点阐述清晰明白,这不仅需要对知识点的掌握,还需要良好的语言表达能力以及对文章细心、整洁的排版。我想,这些细节才能够体现一个人的水平和他所能到达的高度。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
本篇来看一下mov这个指令,相关指令 ldr

Question on MOV
Does the instruction “Mov” have indirect addressing?
Answer. No, e.g. you cannot use mov r1,[r2]
“MOV loads a value into the destination register, from another register, a shifted register, or an immediate 8-bit value.”
Examples:
MOV R0, R1 if R1 has 0x00001234, after this ,R1=R2=0x00001234
MOV R0, #0x12; after this R0 has #0x12
MOV R0, #300; is wrong the value should be less than 255
MOV R0, 200; is wrong, # is missing “mov R0,#200: is correct

Note: the immediate value must be prefixed by #

从上面的描述可以看出,mov的作用有两个:

1. 在寄存器之间传递值。

2. 给寄存器传递一个立即数,此时需要用“#”来修饰立即数,并且立即数为8位的,其值不能超过255.

但是在vivi中的head.S里,有许多类似 mov r1, #0x53000000 的语句:

简单的写几句汇编,测试一下:

.global _start
.align 0
_start:
mov r1, #0x12
mov r2, #300
mov r3, #0x53000000

.end

这样,编译并没有报错。

反汇编后如下

8000: e3a01012 mov r1, #18 ; 0x12
8004: e3a02f4b mov r2, #300 ; 0x12c
8008: e3a03453 mov r3, #1392508928 ; 0x53000000

这是为什么呢?为什么用mov也可以?看别的汇编里都是写ldr r1, =0x53000000

将程序改一下:

.global _start
.align 0
_start:
mov r1, #0x12
mov r2, #300
        ldr r3, =0x53000000
.end

汇编也没有报错,反汇编可看到如下三句话:

8000: e3a01012 mov r1, #18 ; 0x12
8004: e3a02f4b mov r2, #300 ; 0x12c
8008: e3a03453 mov r3, #1392508928 ; 0x53000000

发现,ldr r3, =0x53000000 被经过汇编之后,实际上变为了 mov r3, #0x53000000 。可见,此处ldr相当于一个伪指令。

关于ldr,下面这段说的很清楚。在分析汇编时,很重要一点就是分清“地址” 和“地址里的内容”,对这个能熟练把握了,相信能对C语言中的指针有更深的理解。

Question on the use of LDR,ADR
Are there any difference between statement 1,2,3 in the following program?
Data1p DCD 0, 0 ;just happen the address is at 0x40000000
;DCD (reserve a 32-bit word)is a pseudo instruction to
;allocate a memory location for this data.
align
align
:
:
Statment1 LDR R0, =Data1p ; Put the address Data1p into R0
Statment2 ADR R0, Data1p ; Put the address Data1p into R0
Statment3 LDR R0, =0x40000000 ; Put the value0x40000000 into R0,
;just happen it is the address of Data1p
Answer: They are all the same. Every statement will generate the same result. Such that the address, not the data content, will be saved into R0. For example, the value in R0 is 0x40000000.

到这里,相信一定对“mov”和“ldr”两个产生了一些疑惑。(注:此处的ldr指的是伪指令pseudo-instruction,而不是内存到寄存器传递值的instruction)

下面的这段对两者的区别作了很全面的分析。

Question on differences between LDR and MOV
What is the difference between MOV and LDR, they seem to have the same function of saving information into registers?
Answer part 1: How different are they?
Note: “#” for mov, “=” for ldr. To define an immediate value
MOV can only move an 8-bit value (0x00->0xff=255) into a register while LDR can move a 32-bit value into a register. The immediate value is prefixed by different characters in mov and ldr: “#” formov, “=” for ldr. E.g.


Mov r1,#255 ; ok, 255 is the biggest number you can mov
Mov r1,255 ; is wrong , missing #
Mov r1,#256 ; is wrong, the number is bigger than 255
Mov r1,#0x12340000 ; is wrong, the number is bigger than 255
Ldr r1,=255; you can do this,
Ldr r1,=256; you can do this,
Ldr r1,=0x12340000; you can do this,


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 0x55555555 ldr r0,=0x55555555; 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 at
http://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, #0x53000000”是可行的呢?

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位:0x0000 004b

3.   2*Rotate = 2*15 = 30

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

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

----------------------------------------------------------------------------------------------------------------------------------------------------

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

ARM 汇编的mov操作立即数的疑问的更多相关文章

  1. ARM汇编之MOV指令

    http://blog.csdn.net/lsywk/article/details/8799837 一.指令格式 MOV{条件}{S}  目的寄存器,源操作数 二.指令详解 MOV指令可完成从另一个 ...

  2. ARM汇编(2)(指令)

    一,ARM汇编语言立即数的表示方法 十六进制:前缀:0x 十进制:无前缀 二制:前缀:0b 二,常用的ARM指令(标准的ARM语法,GNU的ARM语法) 1.@M开头系列 MOV R0, #12 @R ...

  3. ARM汇编

    ARM汇编 ISA ISA即指指令集架构(Instruction Set Architecture)是与程序设计有关的计算机架构的一部分,包括本地数据类型.指令.寄存器.地址模式.内存架构.中断和意外 ...

  4. GNU风格 ARM汇编语法指南

    汇编源程序一般用于系统最基本的初始化:初始化堆栈指针.设置页表.操作 ARM的协处理器等.这些初始化工作完成后就可以跳转到C代码main函数中执行. 1.  GNU汇编语言语句格式 任何Linux汇编 ...

  5. 常用ARM汇编指令

    常用ARM汇编指令 [日期:2012-07-14] 来源:Linux社区  作者:xuyuanfan77 [字体:大 中 小]     在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时初 ...

  6. ARM 汇编的一些规范

    A.5.1  文件格式        ARM 源程序文件(即源文件)为文件格式,可以使用任一文本编辑器编写程序代码.         在一个项目中,至少要有一个汇编源文件或C 程序文件,可以有多个汇编 ...

  7. ARM 汇编指令

    ARM汇编程序特点: l         所有运算处理都是发生通用寄存器(一般是R0~R14)的之中.所有存储器空间(如C语言变量的本质就是一个存储器空间上的几个BYTE).的值的处理,都是要传送到通 ...

  8. linux驱动系列之arm汇编

    在arm平台学习linux时,会遇到arm汇编指令,arm汇编指令与8086汇编指令很多地方都不同,在此记下来以免后面忘了,同时在学习了汇编指令之后分析一些汇编指令编写的代码. 一.相对跳转指令b.b ...

  9. ARM学习笔记9——ARM汇编汇编语言中的伪指令

    ARN汇编器支持ARM伪指令,这些伪指令在汇编阶段被翻译成ARM或Thumb指令.ARM伪指令包含ADR.ADRL.MOV32和LDR.一.ADR伪指令 1.作用 ADR是小范围地址读取伪指令,基于P ...

随机推荐

  1. HDU 4770 Lights Against Dudely (2013杭州赛区1001题,暴力枚举)

    Lights Against Dudely Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  2. how convert large HEX string to binary array ?

    how convert large HEX string to binary I have a string with 14 characters . This is a hex represanta ...

  3. 在 C# 中,如何发现死锁并防止死锁

    在解释死锁如何发生以及如何阻止死锁的过程中,你似乎遇到了问题. 当两个( 最小二) 线程试图获取已经被另一个锁锁定的资源的锁时,就会发生死锁. 线程 1锁定资源 1尝试获取对资源 2的锁定. 同时,线 ...

  4. CentOS 6.8 搭建 Git 代码托管系统 Gitea

    [荐] Gitea:Git with a cup of tea,在 Gogs 基础上,发展起来的 自助 Git 服务系统.Gogs是一个个人维护的版本,而Gitea是一个社区组织维护的,版本迭代更新快 ...

  5. socket recv阻塞与非阻塞error总结

    recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结. 首先阻塞接收的re ...

  6. [置顶] 九度笔记之 1494:Dota

    题目1494:Dota 1 秒 内存限制:128 兆 特殊判题:否 提交:559 解决:122 题目描述: 大家都知道在dota游戏中,装备是对于英雄来说十分重要的要素. 英雄们不仅可以购买单个的装备 ...

  7. Revit API修改链接文件房间边界

    start [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] );//设置房间边界     ...

  8. 集群服务器下使用SpringBoot @Scheduled注解定时任务

    原文:https://blog.csdn.net/huyang1990/article/details/78551578 SpringBoot提供了 Schedule模块完美支持定时任务的执行 在实际 ...

  9. cocos2d-x系列笔记技巧篇(2)---关于CREATE_FUNC宏的用法

    FROM://http://blog.csdn.net/jinciyulang/article/details/8631889 阅读cocos2d-x demo的代码,我们会看到有些头文件中使用CRE ...

  10. 基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码

    在ipad.iphone网页开发中,我们很可能需要判断是横屏或者竖屏.下面就来介绍如何用 jQuery 判断iPad.iPhone.Android是横屏还是竖屏的方法 其实主要是通过window.or ...