汇编指令-位置无关码(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中

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

实例:

 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条指令取值的地方。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏搜云库

使用 Phoenix-4.11.0连接 Hbase 集群 ,并使用 JDBC 查询测试

什么是 Phoenix ? Apache Phoenix 是运行在Hbase之上的高性能关系型数据库,通过Phoenix可以像使用jdbc访问关系型数据库一样访...

5135
来自专栏流柯技术学院

selenium启动firefox时加载扩展

    有些时候,我们测试需要用到插件或者已经导入的证书(比如金融和安全加密行业),而selenium启动firefox时会打开一个新的,不含有任何插件和个人证...

2401
来自专栏菩提树下的杨过

Flash/Flex学习笔记(53):利用FMS快速创建一个文本聊天室

先来看客户端fla的构成: 第一帧:登录界面 ? 第一帧的代码: import flash.events.MouseEvent; import com.adob...

2109
来自专栏开发与安全

linux系统编程之进程(四):wait/waitpid函数与僵尸进程、fork 2 times

一、僵尸进程 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将...

3477
来自专栏Java3y

从零开始写项目第二篇【登陆注册、聊天、收藏夹模块】

登陆模块目标 我要将其弄成类似的登陆,功能是要比较完善的。 ? 本来我是想做一步写一步的,但是发现这样文章就会太乱,因为要改的地方太多了。前面写过的,后边就被修...

1.2K8
来自专栏小白安全

Discuz网站通用修改注册会员数和显示在线人数

一.修改在线人数跟会员: 1.找到文件:sourcemoduleforumforum_index.php 2.查找代码: $onlinenum...

3678
来自专栏macOS 开发学习

macOS 应用开发小集锦

输出结果与当前app的语言环境有关(默认为English),如果需要修改工程的语言环境,需要设置Edit Scheme...

1062
来自专栏博客园

深入浅出话命令

WPF为我们准备了完善的命令系统,你可能会问:“有了路由事件为什么还需要命令系统呢?”。事件的作用是发布、传播一些消息,消息传达到了接收者,事件的指令也就算完成...

1024
来自专栏开源优测

RFC821 简单邮件传输协议(SMTP)

1483
来自专栏FreeBuf

AutoIt木马又一发:暗藏神秘照片

AutoIt是一个自动化的Windows界面交互的脚本语言,具有很高的灵活性和较低的学习曲线。由于AutoIt解释器本身属于合法程序,黑客可以把恶意代码藏在脚本...

3299

扫码关注云+社区

领取腾讯云代金券