位置无关码

即该段代码无论放在内存的哪个地址,都能正确运行。究其原因,是因为代码里没有使用绝对地址,都是相对地址。

位置相关码

即它的地址与代码处于的位置相关,是绝对地址


BL :带链接分支跳转指令,也是位置无关码(相对位置),用于调用函数用的。

B:分支跳转指令,指目标不能太远,一般用于同一个文件下的目标地址跳转。

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


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

例如:

1. LDR r0,=label    //用于加载立即数或一个地址值到指定寄存器中

//如果label是立即数: LDR r0,=0X123 ;将0X123存入r0中

//如果name是个标识符: LDR r0,=label_1 ;将label_1所指向的地址值存入r0中

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

例如:

  • LDR r0,[r1]        //将R1中的值存到r0中
  • LDR r1,[r2,#16]     //将(r2+16)地址中的内容存到r1中
  • LDR r1,[r2],#4      //将r2地址中的内容存到r1中,同时r2=r2+4

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

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

 SECTIONS {
. = 0x30000000;
.text : { *(.text) }
.rodata ALIGN() : {*(.rodata)}
.data ALIGN() : { *(.data) }
.bss ALIGN() : { *(.bss) *(COMMON) }
}

反汇编如下:

  <_start>:
: e3a0da01 mov sp, # ; 0x1000
: eb00000a bl <disable_watch_dog>
: eb00000d bl <clock_init>
3000000c: eb000026 bl 300000ac <memsetup>
: eb000040 bl <copy_steppingstone_to_sdram>
: e59ff00c ldr pc, [pc, #] ; <.text+0x28> <on_sdram>:
: e3a0d30d mov sp, # ; 0x34000000
3000001c: e59fe008 ldr lr, [pc, #] ; 3000002c <.text+0x2c>
: e59ff008 ldr pc, [pc, #] ; <.text+0x30> <halt_loop>:
: eafffffe b <halt_loop>
: andcc r0, r0, r8, lsl r0
3000002c: andcc r0, r0, r4, lsr #
: andcc r0, r0, r0, lsl # <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补码左移两位,得到 =0X28

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

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

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

汇编指令-位置无关码(BL)与绝对位置码(LDR)(2)的更多相关文章

  1. JZ2440开发笔记(9)——位置无关代码设计【转】

    b MAIN 和 ldr pc,=MAIN 的区别(谈到代码位置无关性) 看bootloader的时候经常看到这两种写法,不太明白区别,网上查了查.其实看了之后还是一头雾水? 其中,2和3 似乎是一个 ...

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

    1. 要不要学习汇编 可以只懂一点,工作中基本不用,一旦用就是出了大问题 ldr : load 读内存 ldr r0, [r1]  : r1里存放的是地址值, 去这个地址读取4字节的内容,存入r0 s ...

  3. s3c2440裸机-代码重定位、清bss的改进和位置无关码

    1.代码重定位的改进 用ldr.str代替ldrb, strb加快代码重定位的速度. 前面重定位时,我们使用的是ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDR ...

  4. 代码重定位和位置无关码——运行于nor flash

    通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简 ...

  5. 关于ARM指令中位置无关和位置相关代码的认识【转】

    本文转载自:https://blog.csdn.net/talent_CYJ/article/details/50533153 今天在一个问题上折腾了又是半天.就是在学JZ2440串口通信的时候,在s ...

  6. 经常使用ARM汇编指令

    一面学习,一面总结,一面记录. 以下是整理在网上找到的一些资料,简单整理记录一下,方便以后查阅. ARM处理器的指令集能够分为跳转指令.数据处理指令.程序状态寄存器(PSR)处理指令.载入/存储指令. ...

  7. 常用ARM汇编指令

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

  8. ARM 汇编指令

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

  9. arm汇编指令总结(不断更新)

    /** ****************************************************************************** * @author    Maox ...

随机推荐

  1. Dapper入门教程(三)——Dapper Query查询

    介绍 查询方法(Query)是IDbConnection的扩展方法,它可以用来执行查询(select)并映射结果到C#实体(Model.Entity)类 查询结果可以映射成如下类型: Anonymou ...

  2. struts2增删改查---layer---iframe层

    在这里写一下struts2中的简单的增删改查 struts.xml中的配置 <?xml version="1.0" encoding="UTF-8" ?& ...

  3. mysql flush操作

    FLUSH语法 FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ... 如果您想要清除MySQL使用的部分内部缓存,您 ...

  4. Oracle B-tree、位图、全文索引三大索引性能比较及优缺点汇总

    引言:大家都知道“效率”是数据库中非常重要的一个指标,如何提高效率大家可能都会想起索引,但索引又这么多种,什么场合应该使用什么索引呢?哪种索引可以提高我们的效率,哪种索引可以让我们的效率大大降低(有时 ...

  5. linux几个重要的按键

    我们在用Windows系统时,有没有感觉快键键让我们工作更有效率,在Linux系统中仍有很好用的快捷键,这些快捷键可以辅助我们进行指令的编写与程序的中断呢,下面介绍几个经常用到的快捷键. 一.Tab- ...

  6. C/C++ 知识点---存储区

    C/C++ 知识点---存储区 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.    栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储 ...

  7. Python 字典和集合

    泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口(在Python 2.6 ...

  8. C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能

    1.IEnumerator和IEnumerable的作用 其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环 ...

  9. 数字图像处理界标准图像 Lena 后面的故事

    熟悉图像处理或者压缩的工程师.研究人员和学生,经常在他们的实验或者项目任务里使用"Lenna"或者"Lena"的图像.Lenna 图像已经成为被广泛使用的测试图 ...

  10. vue-cli脚手架npm相关文件解读(6)build.js

    系列文章传送门: 1.build/webpack.base.conf.js 2.build/webpack.prod.conf.js 3.build/webpack.dev.conf.js 4.bui ...