汇编指令-位置无关码(BL)与绝对位置码(LDR)(2)
位置无关码
即该段代码无论放在内存的哪个地址,都能正确运行。究其原因,是因为代码里没有使用绝对地址,都是相对地址。
位置相关码
即它的地址与代码处于的位置相关,是绝对地址
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中
例如:
- 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)的更多相关文章
- JZ2440开发笔记(9)——位置无关代码设计【转】
b MAIN 和 ldr pc,=MAIN 的区别(谈到代码位置无关性) 看bootloader的时候经常看到这两种写法,不太明白区别,网上查了查.其实看了之后还是一头雾水? 其中,2和3 似乎是一个 ...
- 韦东山yy公开课笔记(2)--汇编,段,栈,重定位/链接地址,位置无关吗
1. 要不要学习汇编 可以只懂一点,工作中基本不用,一旦用就是出了大问题 ldr : load 读内存 ldr r0, [r1] : r1里存放的是地址值, 去这个地址读取4字节的内容,存入r0 s ...
- s3c2440裸机-代码重定位、清bss的改进和位置无关码
1.代码重定位的改进 用ldr.str代替ldrb, strb加快代码重定位的速度. 前面重定位时,我们使用的是ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDR ...
- 代码重定位和位置无关码——运行于nor flash
通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简 ...
- 关于ARM指令中位置无关和位置相关代码的认识【转】
本文转载自:https://blog.csdn.net/talent_CYJ/article/details/50533153 今天在一个问题上折腾了又是半天.就是在学JZ2440串口通信的时候,在s ...
- 经常使用ARM汇编指令
一面学习,一面总结,一面记录. 以下是整理在网上找到的一些资料,简单整理记录一下,方便以后查阅. ARM处理器的指令集能够分为跳转指令.数据处理指令.程序状态寄存器(PSR)处理指令.载入/存储指令. ...
- 常用ARM汇编指令
常用ARM汇编指令 [日期:2012-07-14] 来源:Linux社区 作者:xuyuanfan77 [字体:大 中 小] 在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时初 ...
- ARM 汇编指令
ARM汇编程序特点: l 所有运算处理都是发生通用寄存器(一般是R0~R14)的之中.所有存储器空间(如C语言变量的本质就是一个存储器空间上的几个BYTE).的值的处理,都是要传送到通 ...
- arm汇编指令总结(不断更新)
/** ****************************************************************************** * @author Maox ...
随机推荐
- Dapper入门教程(三)——Dapper Query查询
介绍 查询方法(Query)是IDbConnection的扩展方法,它可以用来执行查询(select)并映射结果到C#实体(Model.Entity)类 查询结果可以映射成如下类型: Anonymou ...
- struts2增删改查---layer---iframe层
在这里写一下struts2中的简单的增删改查 struts.xml中的配置 <?xml version="1.0" encoding="UTF-8" ?& ...
- mysql flush操作
FLUSH语法 FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ... 如果您想要清除MySQL使用的部分内部缓存,您 ...
- Oracle B-tree、位图、全文索引三大索引性能比较及优缺点汇总
引言:大家都知道“效率”是数据库中非常重要的一个指标,如何提高效率大家可能都会想起索引,但索引又这么多种,什么场合应该使用什么索引呢?哪种索引可以提高我们的效率,哪种索引可以让我们的效率大大降低(有时 ...
- linux几个重要的按键
我们在用Windows系统时,有没有感觉快键键让我们工作更有效率,在Linux系统中仍有很好用的快捷键,这些快捷键可以辅助我们进行指令的编写与程序的中断呢,下面介绍几个经常用到的快捷键. 一.Tab- ...
- C/C++ 知识点---存储区
C/C++ 知识点---存储区 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储 ...
- Python 字典和集合
泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口(在Python 2.6 ...
- C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能
1.IEnumerator和IEnumerable的作用 其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环 ...
- 数字图像处理界标准图像 Lena 后面的故事
熟悉图像处理或者压缩的工程师.研究人员和学生,经常在他们的实验或者项目任务里使用"Lenna"或者"Lena"的图像.Lenna 图像已经成为被广泛使用的测试图 ...
- 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 ...