ARM中跳转指令BL/BLX偏移值计算规则

  1. 4字节对齐arm指令

????规则:偏移=( 跳转地址-(指令地址+8) )/4

原因:

指令地址 + 8:因为ARM的流水线使得指令执行到当前指令处时,PC实际的值是A+8。

跳转指令 - 上一步得到地址:得到跳转指令与当前PC处的差值。

÷4:因为ARM的指令是4对齐的,即最低两位为00,于是将这个值右移两位。

?

执行时:

取出偏移,左移两位,加入PC,这时PC的值刚好为目标处的地址值,即目标地址指令进入取值,流水线前两级被清空。

?

实例测试:


.text:0000126C
90
00
9F E5 LDR R0,
=0x4D44

.text:00001270
00
70
8F E0 ADD R7, PC, R0 ; _GLOBAL_OFFSET_TABLE_

.text:00001274
07
00
86 E0 ADD R0, R6, R7

.text:00001278
74
10
80 E2 ADD R1, R0, #0x74

.text:0000127C DC 20
80 E2 ADD R2, R0, #0xDC

.text:00001280
04
00 A0 E3 MOV R0, #4

.text:00001284
92 FF FF EB BL __android_log_print

.text:00001288
00
00
95 E5 LDR R0,
[R5]

?

?

.plt:000010D4 __android_log_print

.plt:000010D4
00 C6 8F E2 ADR R12,
0x10DC

(0010d4 - (001284 + 8))/4 = 00FFFF92。

对应机器码为 92 ff ff

2. thumb2指令

????(转自 http://bbs.pediy.com/showthread.php?t=199429 ))

1.向后跳转

0012 00F001F8 bl .Lhelo

.Lhelo:

0018 05F0D1F7 pld [r1, r5]

?

计算方式:

取高位 f000, 取后11位 => 000

取低位 f801, 取后11位 => 001

计算: (000 << 12) | (001 << 1) = 2

由于这个最高位符号位为0. 代表向后跳转, 只需要保留该值2即可

?

然后计算得到的目标地址为 : 0x0012 + 4 + 2 = 0x0018

向前跳转

00001164 FF F7 BE FF BL _Z4testv

_Z4testv

000010E4 07 B5 PUSH {R0-R2,LR}

?

计算方式:

取高位 f7ff, 取后11位 => 7ff

取低位 ffbe, 取后11位 => 7be

计算: (7ff << 12) | (7be << 1) = 7fff7c

由于这个最高位符号位为1 代表向前跳转, 需要-1然后取反 得到值为 ff800084。取84即可

?

然后计算得到的目标地址为 : 0x1164 + 4 - 0x84 = 0x10e4

?

逆向过程:

BL?<label>
由BL指令得到机器码算法:


offset
= dstAddr - srcAddr;

?

offset
=
(offset
-4)
&
0x007fffff;

?

high
=
offset
>>
12;

low
=
(offset
&
0x00000fff)
>>
1;

?

machineCode =
((0xFF00
|
low)
<<
16)
|
(0xF000
|
high);

BLX <label>

与BL类似。


offset
= dstAddr - srcAddr;

?

offset
=
(offset
-4)
&
0x007fffff;

?

high
=
offset
>>
12;

low
=
(offset
&
0x00000fff)
>>
1;

?

if(low%2 !=
0) {

low++;

}

?

machineCode =
((0xEF00
|
low)
<<
16)
|
(0xF000
|
high);

时间: 2024-12-30 19:10:49

ARM中跳转指令BL/BLX偏移值计算规则的相关文章

ARM指令集——跳转指令

ARM 汇编指令条件执行 在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位.在数据处理指令中使用S后缀来实现该功能. 不要在CMP,CMN,TST或者TEQ指令中使用S后缀.这些比较指令总是会更新标志位. 在Thumb模式下,所有数据处理指令都更新CPSR中的标志位.有一个例外就是:当一个或更多个高寄存器被用在MOV和ADD指令时,此时MOV和ADD不能更新状态标志. 几乎所有的ARM指令都可以根据CPSR中的ALU状态标志位来条件执行.参见

[zhuan]arm中的汇编指令

http://blog.csdn.net/qqliyunpeng/article/details/45116615 一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text".".data".".bss" 依次表示的是 “以下是代码段”, “以下是初始化数据段”, “以下是未初始化数据段”. 2.".global" 定义一个全局符号,通常是为ld使用.比如经常看到的 .global _start 3.".

ARM中的汇编指令

BIC:ARM指令,对某些位,清零.先取反再相与. asm("BIC  r2, r2, #0x1f");        ##对R2的低5位清零. ORR:ARM指令,逻辑或 asm("ORR r2, r2, #0x10");       ##R2逻辑与0x10. MRS:asm("MRS  r2, CPSR");          ##将CPSR的值加载到R2中. MSR:asm("MSR  CPSR, r2");      

汇编跳转指令B、BL、BX、BLX 和 BXJ的区别

跳转指令用于实现程序流程的跳转,在 ARM 程序中有两种方法可以实现程序流程的跳转: (1) 使用专门的跳转指令. (2) 直接向程序计数器 PC 写入跳转地址值. 通过向程序计数器 PC 写入跳转地址值,可以实现在 4GB 的地址空间中的任意跳转,在跳转之前结合使用 MOV LR , PC 等类似指令,可以保存下一条指令地址作为将来的返回地址值,从而实现在 4GB 连续的线性地址空间的子程序调用. 专门的跳转指令 B.BL.BX.BLX 和 BXJ: 跳转.带链接跳转(带返回的跳转).跳转并切

关于ARM的B,BL跳转指令

.text:00001260 A3 04 00 EB                             BL      sub_24F4 当前地址+ (偏移 << 2 + 8) = 目标地址 0x1260 + 0x4A3 * 4 + 8 = 24F4 偏移 = (目标地址 - 当前地址 - 8) >> 2 偏移 = (0x24F4 - 0x1260 - 8) / 4 = 0x4A3 假设跳转指令处的地址是A,跳转目标处的地址是B.B,BL指令保存的是偏移地址,这个地址的计算方

arm跳转指令对应的机器码

ARM: 常见跳转指令机器码: B:0xEA BL:0xEB 偏移地址计算过程: (目标地址 - 指令地址 - 8)/ 4 = 偏移 // 减8,指令流水造成. // 除4,因为指令定长,存储指令个数差,而不是地址差. 完整指令: 假设上一步得到的偏移为0x00000C 跳转指令为:B 则完整指令为:0C 00 00 EA THUMB: Thumb指令都是2字节.BL看起来像4字节指令,其实是一个误解,因为长跳转是由两条跳转指令组成的. 0~11位表示11位地址,具体含义如下: 第11位为0,偏

汇编中的跳转指令

能修改CS以及IP的指令都是转移指令.它分为段内转移,段间转移. 段内转移:只修改IP的值 段间转移:同时修改CS以及IP的值 段内转移根据转移的距离远近分为:短转移,近转移 短转移:转移范围为-128 – 127 近转移:转移范围为-32768 –32767 根据转移情况又分为: 无条件转移指令 条件转移指令 循环指令 过程 中断 <1> jmp short xxx(行号) 这个是短转移指令,实现段内的转移,在翻译成机器码的时候,码内并没有目标地址,有的只是转移位移,这样做的好处就是防止目标

arm学习之汇编跳转指令总结

目前所知道的跳转指令有 b,bl,bep,bne.他们共同点是都是以b开头,首先从字面上分析:b:是Branch,表示分支.bl:是Branch Link表示带连接的分支.bep:Branch ,Equalbne:Branch ,Not Equal. B或BL指令引起处理器转移到"子程序名"处开始执行.两者的不同之处在于BL指令在转移到子程序执行之前将其下一条指令的地址拷贝到R14(LR,链接寄存器).由于BL指令保存了下条指令的地址因此使用指令"MOV PC,LR&qu

关于ARM中的tst、cmp、bne、beq指令

一.关于cmp的详细用法 假设现在AX寄存器中的数是0002H,BX寄存器中的数是0003H. 执行的指令是:CMP AX, BX 执行这条指令时,先做用AX中的数减去BX中的数的减法运算. 列出二进制运算式子: 0000 0000 0000 0010 -   0000 0000 0000 0011 _________________________________ (借位1) 1111 1111 1111 1111 所以,运算结果是 0FFFFH 根据这个结果,各标志位将会被分别设置成以下值: