Chinaunix首页 | 论坛 | 博客
  • 博客访问: 267116
  • 博文数量: 33
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1917
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-22 16:27
文章分类

全部博文(33)

文章存档

2015年(33)

分类: 嵌入式

2015-05-30 18:13:32

ldr既可以做汇编指令使用,也可以做伪指令使用。当作为汇编指令使用的时候:

ldr 指令的格式为:
ldr{条件}  目的寄存器,<存储器地址>
ldr 指令用于从存储器中将一个 32 位的字数据传送到目的寄存器中。该指令通常用于从存
储器中读取 32 位的字数据到通用寄存器,然后对数据进行处理。当程序计数器 PC 作为  目
的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。

指令示例:
ldr r0,[r1]                 ;将存储器地址为 r1 的字数据读入寄存器 r0。
ldr r0,[r1,r2]        ;将存储器地址为 r1+r2 的字数据读入寄存器 r0。
ldr r0,[r1,r2]!     ;将存储器地址为r1+r2的字数据读入寄存器 r0,并将新地址r1+r2写 r1。


str和ldr可认为是一对指令,str用法如下:


str{条件}  源寄存器,<存储器地址>
str 指令用于从源寄存器中将一个 32 位的字数据传送到存储器中。
指令示例:
str r0,[r1],#8            ;将 r0 中的字数据写入以 r1 为地址的存储器中,并  将新地址
r1+8 写入 r1。
str r0,[r1,#8]           ;将 r0 中的字数据写入以 r1+8 为地址的存储器中。


当ldr作为伪指令使用时,用法如下:
ldr     r0, =_start


从下面这个例子可以了解区别

0c008014 <_start>:
c008014:       e1a00000        nop                     (mov r0,r0)

ldr     r0, _start
这里是当做汇编指令使用,把内存地址 _start 的地方的值读入(_start代表一个地址标号)。执行这个后,r0 = 0xe1a00000

ldr     r0, =_start  得到的是绝对的地址,链接时决定;
当做伪指令来使用。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 _start 的数据
(因为在编译的时候不能确定 _start 的值,而且也不能用 mov 指令来给 r0 赋一个 32bit 的常量,
所以需要多出一个空间存放 _start 的真正数据,在这里就是 0x0c008014)。执行的结果 r0 = 0c008014


ldr和adr区别
adr     r0, _start  得到的是_start的当前执行位置,由 pc+offset 决定的
取 _start 的地址到 r0,但是请看反编译的结果,它是与位置无关的。其实取得的是相对的位置。
例如这段代码在 0x0c008000 运行,那么 adr r0, _start 得到 r0 = 0x0c008014;如果在地址
0 运行,就是 0x00000014 了。




阅读(2739) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~