指令简介:

adr r0, _start   得到的是 _start 的当前执行位置,由 pc+offset 决定
ldr r0, =_start 得到的是绝对的地址,链接时决定

程序示例:

ldr r0, _start
adr r0, _start
ldr r0, =_start
nop
mov pc, lr _start:
nop

下面是反汇编的结果:

0c008000 <_start-0x14>:
c008000: e59f000c ldr r0, [pc, #12] ; c008014 <_start>
c008004: e28f0008 adr r0, pc, #8 ; 0x8
c008008: e59f0008 ldr r0, [pc, #8] ; c008018 <_start+0x4>
c00800c: e1a00000 nop (mov r0,r0)
c008010: e1a0f00e mov pc, lr 0c008014 <_start>:
c008014: e1a00000 nop (mov r0,r0)

分析:

ldr r0, _start
从内存地址 _start 的地方把值读入。执行这个后,r0 = 0xe1a00000。 adr r0, _start
取得 _start 的地址到 r0,但是请看反编译的结果,它是与位置无关的。其实取得的是相对的位置。例如这段代码在 0x0c008000 运行,
那么 adr r0, _start 得到 r0 = 0x0c008014;如果在地址 0 运行,就是 0x00000014 了。即当前 PC 值加上 _start 的偏移量。 ldr r0, =_start
这个取得标号 _start 的绝对地址。这个绝对地址是在 link 的时候确定的。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 _start 的数据(因为在编译的时候不能确定 _start 的值,所以不能直接用 mov 指令来给 r0 赋一个 32bit 的常量,所以需要多出一个空间存放 _start 的真正数据,这个数据是在 link 的时候确定的,在这里就是 0x0c008014)。
因此可以看出,这个是绝对的寻址,不管这段代码在什么地方运行,它的结果都是 r0 = 0x0c008014。

ADR 的应用实例

在 GNU_uC/OS-II 中:

/* we do sys-critical inits only at reboot not when booting from ram */
adr r0, _start /*r0 <- current position of code*/
cmp r0, #0x0
blne cpu_init_crit

在 Uboot 中:

/* r0 <- current position of code(此处 r0 取决于运行实际所处的 _start 地址)*/
adr r0, _start /* test if we run from flash or RAM(此处 r1 为 _TEXT_BASE 宏定义的值)*/
ldr r1, _TEXT_BASE /* 如果相等,说明 uboot 已经被搬运到期望的 _TEXT_BASE 定义的地址 */
cmp r0, r1
beq stack_setup

参考自:blog.csdn.net/u010886535/article/details/52800184

伪指令 ADR 与 LDR 的区别的更多相关文章

  1. ARM 汇编指令 ADR 与 LDR 使用

    简介 这两个都是伪指令:ADR 是小范围的地址读取伪指令,LDR 是大范围的读取地址伪指令.可实际使用的区别是: ADR 是将基于 PC 相对偏移的地址值或基于寄存器相对地址值读取的伪指令,而 LDR ...

  2. 8.adr与ldr伪指令的区别

    ldr和adr都是伪指令,区别是ldr是长加载.adr是短加载. 重点:adr指令加载符号地址,加载的是运行时地址: ldr指令加载符号地址时,加载的是链接地址.

  3. 汇编指令-adr与ldr伪汇编区别(8)

    adr :相对寻址,与当前位置有关 ldr  :绝对寻址,与当前位置无关 在初始化SDRAM时就会用到adr,代码如下: /* 初始化SDRAM */ ldr r0,=BWSCON //r0=SDRA ...

  4. ARM指令adr adrl ldr mov

    ADR是一条小范围的地址读取伪指令,它将基于PC的相对偏移的地址值读到目标寄存器中.格式:ADR register,exper. 编译源程序时,汇编器首先计算当前PC值(当前指令位置)到exper的距 ...

  5. adr adrl ldr mov总结整理

    ADR这是一条小范围的地址读取伪指令,它将基于PC的相对偏移的地址值读到目标寄存器中.     使用的格式:ADR register,exper.     在编译源程序时,汇编器首先计算出当前PC值( ...

  6. ARM体系结构和汇编指令

    第一节 可编程器件的编程原理 1. 可编程器件的特点 1 . CPU在固定频率的时钟控制下节奏运行 2 . CPU可以通过总线读取外部存储设备中的二进制指令集,然后解码执行 3 . 这些可以被CPU解 ...

  7. mov和ldr/str的区别

    ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令.比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如:ldr r0, 0x12345678就 ...

  8. LDR 和MOV 指令区别

    ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令.比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如:ldr r0, 0x12345678就 ...

  9. ARM汇编中ldr伪指令和ldr指令(转载)

    转自:http://blog.csdn.net/ce123_zhouwei/article/details/7182756 ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成, ...

随机推荐

  1. 欣赏<沉默的大多数>——王小波

    君特·格拉斯在<铁皮鼓>里,写了一个不肯长大的人.小奥斯卡发现周围的世界太过荒诞,就暗下决心要永远做小孩子.在冥冥之中,有一种力量成全了他的决心,所以他就成了个侏儒.这个故事太过神奇,但很 ...

  2. eclipse中设置python的版本

    (mac系统)由于系统的python是内置的,无法直接查找到安装文件,则可在eclipse偏好设置-PyDev - Interpreters-Python Interpreter其右边选择Quick ...

  3. 我的C#跨平台之旅(一):从 Hello World 开始

    创建一个“控制台应用程序”,目标框架为“.NET Framework 4.5”,并移除无关的文件及引用,仅保留对 “system.dll”的引用:其中工程文件中核心内容如下: 使用NuGet添加如下引 ...

  4. javaWeb中MVC的编程思想示例

    没有学习MVC之前我只写了一个Servlet类(Note_List.java),分层之后,我将这个类分成了5个类(NoteDao.java,,NoteDaoImpl.java,,NoteService ...

  5. eclipse 导入包含子maven项目的maven项目时的正确方式(父子项目)

    eclipse 导入包含子maven项目的maven项目时的正确方式(父子项目) NO1 导入时依次选择 import > Maven > Existing Maven Projects ...

  6. 28.实现 strStr() 函数

    28.实现 strStr() 函数 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在, ...

  7. ubuntu下file_get_contents返回空字符串

    ubuntu下file_get_contents返回空字符串 | 浏览:302 | 更新:2014-03-30 10:11 本文起初面临的问题是PHP中SoapClient不好使,最后file_get ...

  8. JVM运行时数据区(一)

    1.名词解释: 栈帧:栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素. 2.程序计数器: 程序计数器是一块比较小的内存空间,可以将它看作是当前线程所执 ...

  9. react-native 项目初始化

    react-native 项目初始化 搭建java,android,node环境 http://www.cnblogs.com/morang/p/react-native-java-build.htm ...

  10. 【渗透攻防WEB篇】SQL注入攻击初级

    前言不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动.在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一,这里我想问 ...