先奉上別人的一篇帖子
ARM的工作狀態(tài)
從編程的角度看漆枚,ARM微處理器的工作狀態(tài)一般有兩種赤套,并可在兩種狀態(tài)之間切換:
1)第一種為ARM狀態(tài)茴她,此時(shí)處理器執(zhí)行32的字對齊ARM指令档叔,絕大部分工作在此狀態(tài);
2)第二種為Thumb狀態(tài)连舍,此時(shí)處理器執(zhí)行16位的没陡、半字對齊的Thumb指令。
ARM微處理器有32位的ARM指令集和16位的Thumb指令集索赏,微處理器可以隨時(shí)在兩種工作狀態(tài)之間切換,并且贴彼,處理器工作狀態(tài)的轉(zhuǎn)變并不影響處理器的工作模式和相應(yīng)寄存器中的內(nèi)容潜腻。
ARM語法不是很復(fù)雜,知道一些大體的語法和指令就可以了
ARM指令分為尋址方式、寄存器器仗、常用指令,了解這三個(gè)知識點(diǎn),就會(huì)對ARM指令有一個(gè)大體的了解融涣。
1. ARM指令中的尋址方式
尋址方式就是確定本條指令的操作數(shù)地址或者是下一條要執(zhí)行指令的指令地址
換句話來說尋址方式就是如何找到指令或者是數(shù)據(jù)的地址
從指令或者數(shù)據(jù)的角度來說童番,可以把尋址方式劃分成兩類指令尋址和數(shù)據(jù)尋址
'''
1. 立即數(shù)尋址
立即數(shù)尋址也叫立即尋址,是一種特殊的尋址方式.
操作數(shù)本身包含在指令中,只要取出指令也就取到了操作數(shù).
這個(gè)操作數(shù)叫做立即數(shù),對應(yīng)的尋址方式叫作立即尋址.
例如:
MOV R0, #64; R0 ← 64
-----------------------------------------------------------------------
2. 寄存器尋址
寄存器尋址是利用寄存器中的數(shù)值作為操作數(shù),也稱為寄存器直接尋址.
例如:
ADD R0, R1, R2 ; R0 ← R1+R2
-----------------------------------------------------------------------
3. 寄存器間接尋址
寄存器間接尋址就是把寄存器中的值作為地址,
再通過這個(gè)地址去取得操作數(shù),操作數(shù)本身存放在存儲(chǔ)器中.
例如:
LDR R0, [R1] ; R0 ← [R1]
-----------------------------------------------------------------------
4. 寄存器偏移尋址
這是ARM指令集特有的尋址方式,
它是在寄存器尋址得到操作數(shù)后再進(jìn)行移位操作,得到最終的操作數(shù).
例如:
MOV R0, R2, LSL #3 ; R0 ← R2*8
(注釋:R2的值左移3位,結(jié)果賦給R0.)
-----------------------------------------------------------------------
5. 寄存器基址變址尋址
又稱為基址變址尋址,是在寄存器間接尋址的基礎(chǔ)上擴(kuò)展來的.
它將寄存器(該寄存器一般稱作基址寄存器)中的值與指令中給出的地址偏移量相加,
從而得到一個(gè)地址,通過這個(gè)地址取得操作數(shù).
例如:
LDR R0, [R1, #4]; R0 ← [R1+4]
(注釋:將R1的內(nèi)容加上4形成操作數(shù)地址,取得的操作數(shù)存入寄存器R0中.)
-----------------------------------------------------------------------
6. 多寄存器尋址
這種尋址方式可以一次完成多個(gè)寄存器值的傳送.
例如:
LDMIA R0, (R1, R2, R3, R4) ; R1←[R0], R2←[R0+4], R3←[R0+8], R4←[R0+12]
-----------------------------------------------------------------------
7. 堆棧尋址
堆棧是一種數(shù)據(jù)結(jié)構(gòu),按先進(jìn)后出(First In Last Out, FILO)的方式工作,
使用堆棧指針(Stack Pointer, SP)指示當(dāng)前的操作位置,堆棧指針總是指向棧頂.
例如:
STMFD SP! , | R1-R7, LR | (將R1~R7, LR壓入堆棧,滿遞減堆棧)
LDMED SP! , | R1-R7, LR | (將堆棧中的數(shù)據(jù)取回到R1~R7, LR寄存器⊥梗空遞減堆棧)
'''
2. ARM中的寄存器
我這里插播一條知識
寄存器的意思是CPU里面會(huì)有少量的內(nèi)存這個(gè)叫寄存器剃斧,差不多像RAM的意思,
它們可用來暫存指令忽你、數(shù)據(jù)和地址
因?yàn)镃PU計(jì)算出來的數(shù)據(jù)會(huì)太快幼东,所以來不及轉(zhuǎn)換到RAM
更不會(huì)與硬盤(磁盤)頻繁的進(jìn)行數(shù)據(jù)交換
所以數(shù)據(jù)會(huì)暫時(shí)放在寄存器的這個(gè)地方,然后再通過某些命令科雳,進(jìn)行數(shù)據(jù)的交換
比如:
指令MOV: 在寄存器和RAM之間移動(dòng)數(shù)據(jù)
+---------------------------------------------------------------------------------------------------------+
| R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | R11 | R12 (IP) | R13 (SP) | R14 (LR) | R15 (PC) |
+---------------------------------------------------------------------------------------------------------+
| | |
R13:(stack pointer),是棧頂指針____/ | |
| |
R14:(link register),存放函數(shù)的返回地址____/ |
|
R15:(program counter),指向當(dāng)前指令地址____/
'''
R0-R3:用于函數(shù)參數(shù)及返回值的傳遞.
R4-R6, R8, R10-R11:沒有特殊規(guī)定,就是普通的通用寄存器.
R7:棧幀指針(Frame Pointer),指向前一個(gè)保存的棧幀(stack frame)和鏈接寄存器 (link register, Ir)在棧上的地址.
R9:操作系統(tǒng)保留.
R12:又叫IP (intra-procedure scratch).
R13:又叫SP (stack pointer),是棧頂指針.
R14:又叫LR (link register),存放函數(shù)的返回地址.
R15: 又叫PC (program counter),指向當(dāng)前指令地址.
'''
LDR和STR指令圖像化解釋
3. ARM中的常用指令含義
MOV: "在寄存器和RAM之間移動(dòng)數(shù)據(jù),使用方法MOV [目標(biāo)地址][源地址] mov r1, r2"
ADD: "加指令"
SUB: "減指令"
LDR: "把棧(內(nèi)存)上內(nèi)容載入一寄存器(CPU里面的內(nèi)存)中"
STR: "把寄存器(CPU里面的內(nèi)存)內(nèi)容存到棧(內(nèi)存)上去"
.w: "是一個(gè)可選的指令寬度說明符.它不會(huì)影響為此指令的行為,它只是確保生成32位指令."
BL: "執(zhí)行函數(shù)調(diào)用,并把使lr指向調(diào)用者(caller)的下一條指令,即函數(shù)的返回地址"
BLX: "同上,但是在ARM和thumb指令集間切換"
CMP: "比較兩個(gè)值"
拓展閱讀. 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;
}
"""
對應(yīng)的ARM指令:
add r0, r1; 將參數(shù)a和參數(shù)b相加再把結(jié)果賦值給r0
ldr.w r12, [sp]; 把最后的一個(gè)參數(shù)f從棧上裝載到r12寄存器
add r0, r2; 把參數(shù)c累加到r0上
ldr.w r9, [sp, #4]; 把參數(shù)e從棧上裝載到r9寄存器
add r0, r3; 累加d累加到r0
add r0, r12; 累加參數(shù)f到r0
add r0, r9 ; 累加參數(shù)e到r0
func(int, int, int, int, int, int):
push {r11, lr}
mov r11, sp
sub sp, sp, #20
ldr r12, [r11, #12]
ldr lr, [r11, #8]
str r0, [r11, #-4]
str r1, [r11, #-8]
str r2, [sp, #8]
str r3, [sp, #4]
ldr r0, [r11, #-4]
ldr r1, [r11, #-8]
add r0, r0, r1
ldr r1, [sp, #8]
add r0, r0, r1
ldr r1, [sp, #4]
add r0, r0, r1
ldr r1, [r11, #8]
add r0, r0, r1
ldr r1, [r11, #12]
add r0, r0, r1
str r0, [sp]
ldr r0, [sp]
mov sp, r11
pop {r11, lr}
bx lr
"""
在IDA中的偏移地址說明
IDA中打開so文件
"""
[SP,#0x538+jstr2]
這條尋址結(jié)果就是
SP+0x538+jstr2
意思就是寄存器SP的值加上0x538根蟹,再加上jstr2的一個(gè)偏移
已知jstr2=-0x51C
所以最后棧中的內(nèi)存是
SP+0x538-0x51C
"""