位置无关码(BL)与绝对位置码(LDR)

BL :带连接分支跳转指令,也是位置无关码(相对位置),一般用于带返回的子程序跳转,B指令是用于无返回的跳转。

LDR:通常都是作加载指令的,但是它也可以作伪指令,通常有两种不同的表示: 

1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ地址放入pc寄存器中,相当于PC=MyHandleIRQ 。

2)LDR PC,MyHandleIRQ 表示将 MyHandleIRQ地址中的值放入pc寄存器中,类似于C语言中的指针形式,相当于PC=*(MyHandleIRQ )。

实例:

 1 Reset:
 2     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
 3     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
 4     // bl是位置无关码,相当于:PCnew = PC + 偏移
 5     //                         PCnew = (4+8) + 0x28 = 0x34
 6
 7     //ldr pc, =disable_watch_dog  /* 这样写将出错 */
 8
 9     bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK
10     bl  memsetup            @ 设置存储控制器以使用SDRAM
11     bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
12     ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
13 on_sdram:
14     ldr sp, =0x34000000     @ 设置栈指针
15     ldr lr, =halt_loop      @ 设置返回地址
16     ldr pc, =main           @ 调用main函数
17 halt_loop:
18     b   halt_loop

链接脚本如下,链接地址在0X30000000:

1 SECTIONS {
2     . = 0x30000000;
3     .text          :   { *(.text) }
4     .rodata ALIGN(4) : {*(.rodata)}
5     .data ALIGN(4) : { *(.data) }
6     .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
7 }

反汇编如下:

 1 30000000 <_start>:
 2 30000000:    e3a0da01     mov    sp, #4096    ; 0x1000
 3 30000004:    eb00000a     bl    30000034 <disable_watch_dog>
 4 30000008:    eb00000d     bl    30000044 <clock_init>
 5 3000000c:    eb000026     bl    300000ac <memsetup>
 6 30000010:    eb000040     bl    30000118 <copy_steppingstone_to_sdram>
 7 30000014:    e59ff00c     ldr    pc, [pc, #12]    ; 30000028 <.text+0x28>
 8
 9 30000018 <on_sdram>:
10 30000018:    e3a0d30d     mov    sp, #872415232    ; 0x34000000
11 3000001c:    e59fe008     ldr    lr, [pc, #8]    ; 3000002c <.text+0x2c>
12 30000020:    e59ff008     ldr    pc, [pc, #8]    ; 30000030 <.text+0x30>
13
14 30000024 <halt_loop>:
15 30000024:    eafffffe     b    30000024 <halt_loop>
16 30000028:    30000018     andcc    r0, r0, r8, lsl r0
17 3000002c:    30000024     andcc    r0, r0, r4, lsr #32
18 30000030:    30000200     andcc    r0, r0, r0, lsl #4
19
20 30000034 <disable_watch_dog>:   ...  ...

反汇编中可以看出当执行ldr pc, =on_sdram 时的反汇编是 ldr pc, [pc, #12] ; 相当于pc=*(pc+12)=30000018,此时的*(pc+12)是指的pc+12地址所指的地址,所以无论pc怎么变都是指的30000018这个常量来执行on_sdram,属于绝对转移

执行  bl  disable_watch_dog  时,地址0X30000004跳转到0X30000034.这里的0X30000034是通过机器码算出来的,机器码格式如下图所示:

其中[31:28]位是条件码[27:24]位为“1010”0xeaffffff,表示B跳转指令,为“1011”时,表示BL跳转指令;[23:0]表示偏移地址。

从反汇编中可以看到 bl  disable_watch_dog  的机器码是eb00000a ,二进制为1110 1011 000000000000000000001010

其中1110表示无条件执行,接下的1011就是BL指令,如L==0则就表示B指令,剩下的Offset就是链接位。

BL指令的跳转地址计算:

1.如上图所示,先将24位Offset补码左移两位,得到000000000000000000001010 00 =0X28

2.由于ARM流水线,当前PC永远等于PC+8,所以PC=PC+0X28+8=0X30000004+0X28+8=0X30000034。

若这里的PC值为其它值,算出来的转移地址也会随之改变,所以BL指令为地址无关码,跳转地址与位置无关。

 注:ARM9是3级流水线,也就是PC处理时正在执行第1条指令的同时对第2条指令进行译码,并将第3条指令从存储器中取出,如下图所示,PC总是指向第3条指令取值的地方。

时间: 2024-10-18 05:40:33

位置无关码(BL)与绝对位置码(LDR)的相关文章

位置无关码 位置相关码

在汇编中  使用位置无关码 b,bl 在c语言中 使用位置无关码 不用全局变量  不用静态变量 位置无关码:CPU取指时,总是相对于本条执行指令的相对地址去取指.比如指行一个ADD指令时,PC要取下一指令的地址,就在原来的基础上+4.这就不管你代码放在存储器的任何位置,只要他们的相对地址没有改变,就能正常执行程序.一般上电复位那几条语句就必须是位置无关码指令. 位置相关码:可以这样来说,就是CPU每次取指都从绝对位置去取,而不是上面的相对位置.这个绝对地址就是相对起始地址0来说的.这样,就要求你

位置无关码

ARM下的位置无关和相关码 为什么需要位置无关码? 见 : U-BOOT详解(什么是<编译地址>?什么是<运行地址>?)  http://bbs.21ic.com/forum.php?mod=viewthread&tid=857037&typeid=114       ARM位置无关代码设计规范  http://wenku.baidu.com/view/5ef25b890b4c2e3f562763a8.html 位置无关可执行文件PIE包括位置无关代码PIC和位置无

代码重定位和位置无关码

通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简单地内存访问,通常我们使用sdram这个介质作为程序运行的载体.但是只重定位data段这种方式存在弊端.第一,我们的调试工具通常不支持这种分体形式(比如我们的之前的代码在0地址开始存放text和rodata段,而在间隔很远处sdram 0x30000000存放data段,这就是分体的形式)的代码:第

韦东山yy公开课笔记(2)--汇编,段,栈,重定位/链接地址,位置无关吗

1. 要不要学习汇编 可以只懂一点,工作中基本不用,一旦用就是出了大问题 ldr : load 读内存 ldr r0, [r1]  : r1里存放的是地址值, 去这个地址读取4字节的内容,存入r0 str : stroe 写内存 str r0, [r1]  : r1里存放的是地址值, 把r0里的4字节数据存入这个地址 所有的汇编.C程序也好,终极目标就是:读写某个地址 2. 程序为何要分为代码段.数据段.BSS段 程序的指令等是只读的,可以把它们归为一类,以便运行时可以放在ROM等设备上, 当然

计算机科学基础知识(四)动态库和位置无关代码

一.前言 本文主要描述了动态库以及和动态库有紧密联系的位置无关代码的相关资讯.首先介绍了动态库和位置无关代码的源由,了解这些背景知识有助于理解和学习动态库.随后,我们通过加-fPIC和不加这个编译选项分别编译出两个relocatable object file,看看编译器是如何生成位置无关代码的.最后,我们自己动手编写一个简单的动态库,并解析了一些symbol Visibility.动态符号表等一些相关基本概念. 本文中的描述是基于ARM MCU,GNU/linux平台而言的,本文是个人对动态库

uboot之位置无关代码解析

在之前的话 新年过去了,那么久没有好好学习,感觉好颓废,现在就uboot的一些基础问题做一些笔记,顺便分享给大家,不过由于见识有限,如果有不足之处请多多指教. 位置无关?什么意思?我们先了解一些基础知识..... 我们都知道我们写的代码最后是运行在内存(SDRAM或者SRAM,通常是SDRAM)中的,但是在运行之前他们是保存在诸如nand.flash等非易失存储设备中的,而这些存储设备的地址要映射到CPU能够寻找的地址上(一般映射在0X0地址上,这个后面详细解释),这样才能得到要运行的代码.而代

对位置无关代码的理解

今天在看uboot编译流程的时候,突然发现对程序的地址相关性的记忆又有点模糊了.搞嵌入式软件就是这个不好,需要学习和掌握很多知识点,才能够对开发中的所有细节都有全面的掌握.可是往往这种掌握又不是很有必要的,因为很多细节性的问题在实际开发过程中,又不一定需要去关注,或者说关注的很少.这就直接导致了学习和掌握了很多细节的知识,往往久了不用,就淡忘了. 比如这里提到的代码地址相关性,以前在搞VxWorks,尤其是bootrom存放位置的时候就有过分析.bootrom编译的时候是不用考虑代码运行位置的,

共享库中的位置无关代码(PIC)

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ 在之前的文章里我已经描述过在将共享库载入程序地址空间时需要特殊的处理.简而言之,在链接器创建共享库时,它不能预先知道这个库将在哪里载入.这给在库里访问数据与代码带来了麻烦,应该使得这些访问指向正确的内存位置. 在Linux ELF共享库里解决这个问题有两个主要途径: 1.     

【Java集合源码剖析】HashMap源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap. HashMap 实现了Serializable接口,因此它支持序列化,