android arm 寄存器,ARM汇编
8種機械鍵盤軸體對比
本人程序員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎么選?
Android Native 進程啟動流程
ARM傳參,R0-R3傳遞前四個參數
1. Thumb 指令集特點Thumb 指令集指令長度:16或32,16為為主
Thumb-16 大部分只能訪問前8個寄存器 R0-R7(少數可以訪問R8-R15)
Thumb-32 可以訪問所有的ARM core 寄存器 R0-R15
更小、更加靈活
2. ARM指令集特點指令長度32位,4字節對齊
功能更加完善
對比ThumbARM2字節對齊4字節對齊
占用空間少、密度高占用空間較多
功能不齊全功能齊全
ARM和Thumb指令集各有自己的優點,取長補短往往會得到最好的性能
3. Opcod 中判斷指令集Opcode[15:13]== 111 && Opcode[12:11]!= 00 滿足則為32bit 的ARM
bl #0x80000fbc
0xed 0xff 0xff 0xeb
4. IDA 中識別與切換指令集Edit->segments->change segment register value(快捷鍵ALT+G)
請看操作。
這有一段指令,判斷出目前是thumb指令集的
按下ALT+G,把0x1改成0x0,就是指定為ARM指令集
然后按下P鍵定義函數,函數參數就都分析出來了(
5. ARM切換指令集原理處理器無論在ARM還是Thumb狀態下都可以通過BX/BLX/LDR/LDM切換不同的指令集。
狀態切換是由寄存器Rn的最低位來指定的,如果操作數寄存器的狀態位Bit0=0,則進入ARM狀態,如果Bit0=1,則進入Thumb狀態。
ARM 中對于字節、字、雙字的定義
注意和intel匯編的區別,一個word(字)這里是4個字節
但是注意一下,在IDA中依然延續著老的傳統,一個DCW(word)代表兩個字節DCB 定義1字節數據
DCW 定義2字節數據
DCD 定義4字節數據
在IDA中,在上面這些數據定義上按下D鍵可以切換定義的類型
Array 定義數組,右鍵或*號鍵
數組最常見的就在數組,
IDA中的自定義數據類型
Structures 窗口中可以創建一個自定義結構體。按下I或者Ins鍵即可創建。
創建了一個名為test的結構體
因為沒有定義字段,所以現在都還是空的,結構體長度為0(相當于空結構體,沒有任何內容)
所以去定義字段。
為自定義數據類型添加字段
創建完結構體后,長這樣:
在ends處按下D鍵就可以定義一個字段了,在字段上按D可以改變長度1/2/4
其他按鍵:
這樣就可以給一個變量轉成自己的結構體類型
應用自定義數據類型
在起始數據處右鍵->Structure->自定義的數據類型
ARM匯編中的標志寄存器與條件代碼
跳轉指令b指令:跳轉
bl指令:跳轉且保存返回地址
blx/bx指令:帶x,可以切換指令集
分支指令例子:
beq=b+eq(equal)=b指令+條件助記符(參考下面的cond)
ben
條件執行
ARM中大部分的指令都支持帶條件執行。
cond:前四位保存條件碼
比較指令的大用處
Compare 指令:cmp r0,#1
完成操作:減法運算(不保存結果)
根據結果更新標志位
標志寄存器
APSR 寄存器
標志寄存器是條件執行的基礎。
N、Z、C、V用于條件標志位
N - 負數標志位
Z - 零標志位
C - 進位標志位
V - 溢出標志位
比如,若減法運算之后為負數,則N為1;為0,則Z=1;
一些會修改標志位的指令
1. 指令后綴帶S的指令,例如(MOVS)
2. TST(and)、TEQ(or)、CMN(add)、CMP(sub)
例如MOVS之后的到的值為0,那么Z就被置位(為1)
完整一點的例子
這里if有兩種可能,一種是a<=10,一種是a>10;
在匯編中先cmp a,#10
然后選擇if括號內相反的選項 bgt next1 (大于則跳轉出去)
然后在這中間填入if代碼塊中的內容
實例分析
打開程序
導出表
libcinit的第三個參數(R2)是main函數的地址
跳入main函數之后發現IDA未能把ARM指令集識別正確。需要手動(ALT+G)
隨便輸入一個不等于0x0的數
全部改好之后就識別出來了
程序源碼1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30int ()
{
int a = 0,b = 0;
printf("This is condition statements re test!nPlease input two number:");
scanf("%d%d",&a,&b);
if(a + b == 10)
{
printf("[if]a+b=10b");
}
if(a > b){
printf("[if-else-1]a > bn");
}else if(a == b){
printf("[if-else-if] a==bn");
}else{
printf("[if-else] a
}
if(a > 10)
{
if(a <= 20)
{
printf("[nest if]n");
}
printf("a > 10n");
}
return 0;
}
自己調試一下
生成thumb代碼
BL的下一條指令的地址被保存在LR寄存器中
調用gcc的內建函數,R0作為參數
R1=LR=57C(待調試) R1=R1+2=57E(待調試) 地址做移位是為了對齊(如這里的R1),而數移位是為了做乘除法(如這里的R0)
LSRS: R1=R1右移兩位
LSLS:R0=R0左移兩位=R0*4
LSLS:R1=R1左移兩位 //先右移再左移,清除R1原來的最低位,用于對齊,得到0x580(待調試)
LDR:R0=[R1+R0] =[580+原來的R04] //假設原來的R0=1,則R0=[580+原來R04]=[580+4]=[0x584]=loc_59C-0x580
ADDS: R0=R0+R1=loc_59C
MOV: LR=loc_59C
POP: 恢復寄存器R0,R1
MOV: PC=loc_59C;函數結束,跳轉到case:選中的代碼塊
這些不是代碼,是長為4字節的數據項,每一項都是偏移值,這個偏移值+0x580就能找到真正的代碼
生成ARM代碼
ADDLS:PC=PC+(R3*4)
PC的PC寄存器指向的不是下條指令,是下下條指令(也就是當前指令地址+8)CEMU測試bl funl //把LR設置為BL指令的下一條地址fun1:mov r0,pcmov r1,lr
差了8個字節
關于ARM中的寄存器PC
從圖中可以看出,一條匯編指令的運行有三個步驟,取指、譯碼、執行,當第一條匯編指令取指完成后,緊接著就是第二條指令的取指,然后第三條…如此嵌套
其實很容易看出,第一條指令:
add r0, r1,$5
取指完成后,PC就指向了第二條指令,此時PC=PC+4
當第一條指令譯碼完成以后,此時PC=PC+8
所以第一條指令開始執行時,PC值已經加了8
所以必須記住這個前提,在arm中,每次該指令執行時,其實這時的PC值是PC=PC+8
而且這個前提也同樣適合多級流水線,原因就不解釋了
總結
以上是生活随笔為你收集整理的android arm 寄存器,ARM汇编的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上百台linux的服务器互信,批量自动建
- 下一篇: linux 硬盘空间监控,Linux服务