ARM指令在Thumb模式和arm模式之间跳转
2016-04-20 15:13
323 查看
根据arm spec, 跳转地址最低位( lsb ) 为0表示 arm 指令;最低位为1表示thumb指令。
一、绝对地址跳转进入 thumb模式
如下指令可以切换到thumb模式。
[cpp] view
plain copy
print?
LDR R6, =0x24000
ADD R6, #1 @ (set lsb to 1)
BX R6
如果已经知道 0x24000 地址存放的是 thumb 指令, 可以直接使用如下方式切换到arm 模式
[java] view
plain copy
print?
LDR R6, =0x24001
BX R6
因此, 无论当前处理器模式是thumb或者arm, 只要0x24000 地址处存放的是 thumb 指令, 就可以通过 BX 指令跳转到 thumb 模式。
二、标号跳转进入thumb 模式
如果不知道链接地址,只知道标号,可以用如下指令跳转。
上述指令的问题在于,如果linker 知道 label 对应的是一条 arm 指令或者 thumb 指令,该指令能正常工作。
如果linker不能正确区别 label 的指令类型,将会导致错误。
指令示例
[java] view
plain copy
print?
.thumb
ping:
ldr r0,=pong
bx r0
.code 32
pong:
ldr r0,=ping
bx r0
编译链接后如下
[java] view
plain copy
print?
d6008148 <ping>:
d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
d600814a: 4700 bx r0
d600814c <pong>:
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
d6008150: e12fff10 bx r0
d6008158: d600814c strle r8, [r0], -ip, asr #2
d600815c: d6008148 strle r8, [r0], -r8, asr #2
ping 可以正确 bx r0 跳转到 0xd6008158。
但是pong 不能。 因为 pong 通过 bx r0 跳转到 0xd600815c 地址后得到的是一条 arm 地址 0xd6008148 ( lsb=0 )。
GNU linker 帮助开发者解决了这些麻烦。GNU 汇编器 as 定义了 .thumb_func 符号。
如果正确的使用了该符号, GNU assembler/linker 将会正确的生成对应的指令序列。
改写后的指令示例
[java] view
plain copy
print?
.thumb
.thumb_func
ping:
ldr r0,=pong
bx r0
.code 32
pong:
ldr r0,=ping
bx r0
编译链接后的指令
[java] view
plain copy
print?
d6008148 <ping>:
d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
d600814a: 4700 bx r0
d600814c <pong>:
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
d6008150: e12fff10 bx r0
d6008158: d600814c strle r8, [r0], -ip, asr #2
d600815c: d6008149 strle r8, [r0], -r9, asr #2
这样生成的代码正是我们所期待的。 0xd600815c 地址对应的指令 ( lsb=1 ) 已经被正确设置成 thumb 指令。
对于 C 函数, GNU Compiler 将会正确处理类似关系。
但是对于 arm assmebly 函数, 必须要通过 使用.thumb_func 符号或者其他被 as 工具定义的符号, 使得 as 工具知道这是一个thumb label.
参考
1. http://stackoverflow.com/questions/9368360/arm-thumb-using-bx-in-thumb-code-to-call-a-thumb-function-or-to-jump-to-a-thu
2. http://stuff.mit.edu/afs/sipb/project/egcs/src/egcs/gcc/config/arm/README-interworking
原帖:http://blog.csdn.net/cfy_phonex/article/details/18667299
一、绝对地址跳转进入 thumb模式
如下指令可以切换到thumb模式。
[cpp] view
plain copy
print?
LDR R6, =0x24000
ADD R6, #1 @ (set lsb to 1)
BX R6
如果已经知道 0x24000 地址存放的是 thumb 指令, 可以直接使用如下方式切换到arm 模式
[java] view
plain copy
print?
LDR R6, =0x24001
BX R6
因此, 无论当前处理器模式是thumb或者arm, 只要0x24000 地址处存放的是 thumb 指令, 就可以通过 BX 指令跳转到 thumb 模式。
二、标号跳转进入thumb 模式
如果不知道链接地址,只知道标号,可以用如下指令跳转。
ldr r6,=label bx r6
上述指令的问题在于,如果linker 知道 label 对应的是一条 arm 指令或者 thumb 指令,该指令能正常工作。
如果linker不能正确区别 label 的指令类型,将会导致错误。
指令示例
[java] view
plain copy
print?
.thumb
ping:
ldr r0,=pong
bx r0
.code 32
pong:
ldr r0,=ping
bx r0
编译链接后如下
[java] view
plain copy
print?
d6008148 <ping>:
d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
d600814a: 4700 bx r0
d600814c <pong>:
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
d6008150: e12fff10 bx r0
d6008158: d600814c strle r8, [r0], -ip, asr #2
d600815c: d6008148 strle r8, [r0], -r8, asr #2
ping 可以正确 bx r0 跳转到 0xd6008158。
但是pong 不能。 因为 pong 通过 bx r0 跳转到 0xd600815c 地址后得到的是一条 arm 地址 0xd6008148 ( lsb=0 )。
GNU linker 帮助开发者解决了这些麻烦。GNU 汇编器 as 定义了 .thumb_func 符号。
如果正确的使用了该符号, GNU assembler/linker 将会正确的生成对应的指令序列。
改写后的指令示例
[java] view
plain copy
print?
.thumb
.thumb_func
ping:
ldr r0,=pong
bx r0
.code 32
pong:
ldr r0,=ping
bx r0
编译链接后的指令
[java] view
plain copy
print?
d6008148 <ping>:
d6008148: 4803 ldr r0, [pc, #12] ; (d6008158 <pong+0xc>)
d600814a: 4700 bx r0
d600814c <pong>:
d600814c: e59f0008 ldr r0, [pc, #8] ; d600815c <pong+0x10>
d6008150: e12fff10 bx r0
d6008158: d600814c strle r8, [r0], -ip, asr #2
d600815c: d6008149 strle r8, [r0], -r9, asr #2
这样生成的代码正是我们所期待的。 0xd600815c 地址对应的指令 ( lsb=1 ) 已经被正确设置成 thumb 指令。
对于 C 函数, GNU Compiler 将会正确处理类似关系。
但是对于 arm assmebly 函数, 必须要通过 使用.thumb_func 符号或者其他被 as 工具定义的符号, 使得 as 工具知道这是一个thumb label.
参考
1. http://stackoverflow.com/questions/9368360/arm-thumb-using-bx-in-thumb-code-to-call-a-thumb-function-or-to-jump-to-a-thu
2. http://stuff.mit.edu/afs/sipb/project/egcs/src/egcs/gcc/config/arm/README-interworking
原帖:http://blog.csdn.net/cfy_phonex/article/details/18667299
相关文章推荐
- NSNotification 与 KVO 的区别?
- 机器学习资源大全
- nfs挂载文件系统
- PHP安全设置
- 双飞翼布局
- 每日一题:替换空格
- linux下tcp状态是从哪查出来的
- python中os模块中文帮助文档
- unity发布Android默认启动类
- MyBatis知识系列之四:解决属性名和字段名不一致的问题
- ARM CPSR/SPSR 的示意图
- My first blog on csdn
- Express安装教程
- 第一阶段冲刺个人博客03
- java error和exception的区别,RuntimeException和非RuntimeException的区别
- 软件测试分类
- Python 三目运算符(三分支)
- block的学习(block和timer的循环引用问题)
- Kvm、Xen虚拟机集中管理平台--convirt
- Objective-C中#define的常见用法