1. 程式人生 > 其它 >常用的ARM指令集知識

常用的ARM指令集知識

我們在上面看到IDA開啟so之後,看到的是純種的彙編指令程式碼,所以這就要求我們必須會看懂彙編程式碼,就類似於我們在除錯Java層程式碼的時候一樣,必須會smali語法,慶幸的是,這兩種語法都不是很複雜,所以我們知道一些大體的語法和指令就可以了,下面我們來看看arm指令中的定址方式,暫存器,常用指令,看完這三個知識點,我們就會對arm指令有一個大體的瞭解,對於看arm指令程式碼也是有一個大體的認知了。

1、arm指令中的定址方式

1>. 立即數定址
也叫立即定址,是一種特殊的定址方式,運算元本身包含在指令中,只要取出指令也就取到了運算元。這個運算元叫做立即數,對應的定址方式叫做立即定址。例如:
MOV R0,#64 ;R0 ← 64
2>. 暫存器定址
暫存器定址就是利用暫存器中的數值作為運算元,也稱為暫存器直接定址。例如:

ADD R0,R1, R2 ;R0 ← R1 + R2
3>. 暫存器間接定址
暫存器間接定址就是把暫存器中的值作為地址,再通過這個地址去取得運算元,運算元本身存放在儲存器中。例如:
LDR R0,[R1] ;R0 ←[R1]
4>. 暫存器偏移定址
這是ARM指令集特有的定址方式,它是在暫存器定址得到運算元後再進行移位操作,得到最終的運算元。例如:
MOV R0,R2,LSL #3 ;R0 ← R2 * 8 ,R2的值左移3位,結果賦給R0。
5>. 暫存器基址變址定址
暫存器基址變址定址又稱為基址變址定址,它是在暫存器間接定址的基礎上擴充套件來的。它將暫存器(該暫存器一般稱作基址暫存器)中的值與指令中給出的地址偏移量相加,從而得到一個地址,通過這個地址取得運算元。例如:
LDR R0,[R1,#4] ;R0 ←[R1 + 4],將R1的內容加上4形成運算元的地址,取得的運算元存入暫存器R0中。
6>. 多暫存器定址
這種定址方式可以一次完成多個暫存器值的傳送。例如:
LDMIA R0,{R1,R2,R3,R4} ;R1←[R0],R2←[R0+4],R3←[R0+8],R4←[R0+12]
7>. 堆疊定址
堆疊是一種資料結構,按先進後出(First In Last Out,FILO)的方式工作,使用堆疊指標(Stack Pointer, SP)指示當前的操作位置,堆疊指標總是指向棧頂。
堆疊定址舉例如下:
STMFD SP!,{R1-R7, LR} ;將R1-R7, LR壓入堆疊。滿遞減堆疊。
LDMED SP!,{R1-R7, LR} ;將堆疊中的資料取回到R1-R7, LR暫存器。空遞減堆疊。

2、ARM中的暫存器

R0-R3:用於函式引數及返回值的傳遞
R4-R6, R8, R10-R11:沒有特殊規定,就是普通的通用暫存器
R7:棧幀指標(Frame Pointer).指向前一個儲存的棧幀(stack frame)和連結暫存器(link register, lr)在棧上的地址。
R9:作業系統保留
R12:又叫IP(intra-procedure scratch )
R13:又叫SP(stack pointer),是棧頂指標
R14:又叫LR(link register),存放函式的返回地址。
R15:又叫PC(program counter),指向當前指令地址。

3、ARM中的常用指令含義

ADD 加指令
SUB 減指令
STR 把暫存器內容存到棧上去
LDR 把棧上內容載入一暫存器中
.W 是一個可選的指令寬度說明符。它不會影響為此指令的行為,它只是確保生成 32 位指令。Infocenter.arm.com的詳細資訊
BL 執行函式呼叫,並把使lr指向呼叫者(caller)的下一條指令,即函式的返回地址
BLX 同上,但是在ARM和thumb指令集間切換。
CMP 指令進行比較兩個運算元的大小

4、ARM指令簡單程式碼段分析

C程式碼:

include <stdio.h>

int func(int a, int b, int c, int d, int e, int f)
{
int g = a + b + c + d + e + f;
return g;
}

對應的ARM指令:

add r0, r1 將引數a和引數b相加再把結果賦值給r0
ldr.w r12, [sp] 把最的一個引數f從棧上裝載到r12暫存器
add r0, r2 把引數c累加到r0上
ldr.w r9, [sp, #4] 把引數e從棧上裝載到r9暫存器
add r0, r3 累加d累加到r0
add r0, r12 累加引數f到r0
add r0, r9 累加引數e到r0

原文:http://www.520monkey.com/archives/622