標籤:
- 4位元組對齊arm指令
????規則:位移=( 跳轉地址-(指令地址+8) )/4
原因:
指令地址 + 8:因為ARM的流水線使得指令執行到當前指令處時,PC實際的值是A+8。
跳轉指令 - 上一步得到地址:得到跳轉指令與當前PC處的差值。
÷4:因為ARM的指令是4對齊的,即最低兩位為00,於是將這個值右移兩位。
?
執行時:
取出位移,左移兩位,加入PC,這時PC的值剛好為目標處的地址值,即目標地址指令進入取值,流水線前兩級被清空。
?
執行個體測試:
|
.text:0000126C90009F E5 LDR R0,=0x4D44
.text:0000127000708F E0 ADD R7, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001274070086 E0 ADD R0, R6, R7
.text:00001278741080 E2 ADD R1, R0, #0x74
.text:0000127C DC 2080 E2 ADD R2, R0, #0xDC
.text:000012800400 A0 E3 MOV R0, #4
.text:0000128492 FF FF EB BL __android_log_print
.text:00001288000095 E5 LDR R0,[R5]
?
?
.plt:000010D4 __android_log_print
.plt:000010D400 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); |
ARM中跳轉指令BL/BLX位移值計算規則