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

adr :相对寻址,与当前位置有关

ldr  :绝对寻址,与当前位置无关

在初始化SDRAM时就会用到adr,代码如下:

    /*   初始化SDRAM       */
       ldr r0,=BWSCON                    //r0=SDRAM寄存器基地址,获取绝对地址
       adr r1,SDRAM_CONFIG           //使用adr相对跳转, r1=SDRAM_CONFIG地址
       add r2,r0,#(13*4)               

0:
       ldr r3,[r1],#4                       
       str r3,[r0],#4                       
       cmp r0,r2
       bne 0b                         

SDRAM_CONFIG:
	.long 0x22011110;	  //BWSCON
	.long 0x00000700;	  //BANKCON0
	.long 0x00000700;	  //BANKCON1
	.long 0x00000700;	  //BANKCON2
	.long 0x00000700;	  //BANKCON3  
	.long 0x00000700;	  //BANKCON4
	.long 0x00000700;	  //BANKCON5
	.long 0x00018005;	  //BANKCON6
	.long 0x00018005;	  //BANKCON7
	.long 0x008C04F4;	  //REFRESH
	.long 0x000000B1;	  //BANKSIZE 
	.long 0x00000030;	  //MRSRB6
	.long 0x00000030;	  //MRSRB7

 上面代码中第3行之所以用到了 “ adr r1,SDRAM_CONFIG ”,是因为SDRAM未初始化之前,不能使用绝对寻址,所以使用adr相对寻址.

adr r1,SDRAM_CONFIG就相当于 ldr r1,=SDRAM_CONFIG 

通过以下实例:

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

_start:
        nop

得出以下汇编(r0设为0C008000):

0c008000 <_start-0x14>: c008000: e59f000c ldr r0, [pc, #12] ; c008014 <_start>           //ldr指令(不带=)  :  r0= c008014里面内容= e1a00000  c008004: e28f0008 add r0, pc, #8 ; 0x8 //adr指令:             r0=(当前PC值+8)+0x8=c008014 c008008: e59f0008 ldr r0, [pc, #8] ; c008018 <_start+0x4>     //ldr指令(带=)  :   r0=c008018 里面内容=0c008014  c00800c: e1a00000 nop (mov r0,r0) c008010: e1a0f00e mov pc, lr 0c008014 <_start>: c008014: e1a00000 nop (mov r0,r0) c008018: 0c008014 stceq 0, cr8, [r0], -#80

分析出:

ldr r0, _start 

将内存地址 _start (c008014)里的数据放入r0中。执行这个后,r0 = 0xe1a00000

adr r0, _start

将 _start 的地址值(c008014)放入 r0中,但是请看反编译的结果,它是与位置无关的。其实取得的时相对的位置。例如这段代码在 0x0c008000 运行,那么 adr r0, _start 得到 r0 = 0x0c008014;如果在地址 0 运行,就是 0x00000014 了。

ldr r0, =_start

这个取得标号 _start 的绝对地址值(c008014)。这个绝对地址是在 link 的时候确定的。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 _start 的数据(因为在编译的时候不能确定 _start 的值,而且也不能用 mov 指令来给 r0 赋一个 32bit 的常量,所以需要多出一个空间存放 _start 的真正数据,在这里就是 0x0c008014)。 因此可以看出,这个是绝对的寻址,不管这段代码在什么地方运行,它的结果都是 r0 = 0x0c008014

结论:

对于adr r0,XXX      就相当于         ldr r0,=XXX ,通常用于SDRAM 未初始化之前用

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

C#:异步编程和线程的使用(.NET 4.5 )

异步编程和线程处理是并发或并行编程非常重要的功能特征。为了实现异步编程,可使用线程也可以不用。将异步与线程同时讲,将有助于我们更好的理解它们的特征。 本文中涉及...

1935
来自专栏犀利豆的技术空间

Redis 数据库、键过期的实现

之前的文章讲解了 Redis 的数据结构,这回就可以看看作为内存数据库,Redis 是怎么存储数据的以及键是怎么过期的。

682
来自专栏Hongten

python开发_function annotations

在看python的API的时候,发现了一个有趣的东东,即:python的方法(函数)注解(Function Annotation)

772
来自专栏阿杜的世界

Java Web技术经验总结(六)

这个函数中的关键是几个If...else...语句,通过判断指定的类是否存在,来决定是否添加对应的messageConverter(在4.0之后应该可以使用@C...

532
来自专栏技术分享

Redis 数据结构与内存管理策略(下)

Redis 数据结构与内存管理策略(下) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 作者:王清培...

2838
来自专栏程序员互动联盟

【专业技术】arm中的7种执行模式

嵌入式设备已经越来越与我们的日常生活密切相关了,由此带来了ARM的高速发展。就拿我们的手机来说吧,几乎所有的手机都是ARM体系的。这里大致介绍下ARM 的7种执...

3539
来自专栏IT杂记

Hadoop SequnceFile.Writer 压缩模式及压缩库浅析

先说明SequnceFile的压缩类型(Compression Type)分为三种NONE,RECORD,BLOCK,通过配置项io.seqfile.compr...

18810
来自专栏Linux驱动

第1阶段——uboot分析之启动函数bootm命令 (9)

本节主要学习: 详细分析UBOOT中"bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0" 中...

1869
来自专栏逆向技术

远程线程注入

一丶远程线程注入的讲解 远程线程注入的原理,我会写一个远程线程开发的例子 我们总共需要几步 /*1.查找窗口,获取窗口句柄*/ /*2.根据...

19210
来自专栏贾老师の博客

makecontext 理解与使用

1133

扫码关注云+社区