新聞中心

Android ARM 指令學習

作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
6.1原生程序ARM匯編語言,逆向你的helloworld
6.2原生程序的生成過程
1:預(yù)處理
“如include頭文件"包含的頭文件全部編譯進來,還有#define預(yù)定義,#if預(yù)條件處理等也都在這里被編譯器處,詳細的輸出可以給gcc編譯器傳遞”-E“,選項查看。
2,編譯
編譯器首先要檢查代碼的規(guī)范性,以及是有語法錯誤等,以及代碼實際要做的工作,檢查無誤后,gcc編譯器把代碼翻譯成ARM匯編語言代碼,可以為gcc編譯器傳遞”-S“選項查看輸出,執(zhí)行”gcc-s hello.i“ -o hello.s 后生成hello.s匯編文件。
3,匯編
這個階段會調(diào)用連接器將匯編成二進制文件的目標文件,以上一小節(jié)的hello為例,執(zhí)行”gcc-c hello.s -o hello.o“ 后生成hello.o目標文件。
4,連接
這個階段編譯器會調(diào)用連接器將二進制的目標文件連接成Android平臺可執(zhí)行的ARM原生程序,以上一個小節(jié)為hello為例,執(zhí)行g(shù)cc hello.o -o hello 后會生成hello可執(zhí)行文件。
6.2.3必須要了解的ARM知識
總結(jié):
1:c語言編寫代碼在編譯時有一個過程,是將其轉(zhuǎn)換成ARM匯編代碼,所以可以這么理解,c語言實現(xiàn)的功能ARM
匯編語言都能實現(xiàn)。
2,ARM匯編語言中特有的寄存器。寄存器是處理特有的高速存儲部件,它們可以用來暫存指令,數(shù)據(jù)和位址,高級語言用到中用到的變量,常量,結(jié)構(gòu)體,類等數(shù)據(jù)用到了ARM匯編語言中,就是使用寄存器保存的值或內(nèi)存地址,寄存器的數(shù)據(jù)量有限,ARM微處理器共有37個32位寄存器,其中31個為通用寄存器,6個為狀態(tài)寄存器,ARM處理器器支持7中運行模式。
1;用戶模式(usr)ARM 處理器正常的程序執(zhí)行狀態(tài)。
2;快速中斷模式(fiq):用與高速數(shù)據(jù)傳輸或通道處理
3;外部中斷模式(irp)用于通用的中斷處理。
4;管理模式(svc)操作系統(tǒng)使用的保護模式
5;數(shù)據(jù)訪問終止模式(abt);當數(shù)據(jù)或指令預(yù)取終止進入該模式,可用于虛擬存儲及存儲數(shù)據(jù)。
6;系統(tǒng)模式(sys):運行具有特權(quán)的操作系統(tǒng)任務(wù)。
7;未定義指令終止模式(und):當未定義的指令執(zhí)行時進入該模式。
Thumb是ARM體系結(jié)構(gòu)中一種16位的指令集。
從ARMv4T之后的ARM處理器有一種16-bit指令模式,叫做Thumb,也許跟每個條件式執(zhí)行指令均耗用4位元的情形有關(guān)。Thumb指令集可以看作是ARM指令壓縮形式的子集,它是為減小代碼量而提出,具有16bit的代碼密度。Thumb指令體系并不完整,只支持通用功能,必要時仍需要使用ARM指令,如進入異常時。其指令的格式與使用方式與ARM指令集類似,而且使用并不頻繁,Thumb指令集作一般了解
ARM匯編語言程序結(jié)構(gòu)
1.一個完整的ARM匯編指令包括處理器架構(gòu)定義,數(shù)據(jù)段,代碼與main函數(shù)。
2.段定義.data的數(shù)據(jù)段中,
如果細分的話,
.rodata的只讀數(shù)據(jù)段中,這些數(shù)據(jù)段不可以執(zhí)行的。
.text的代碼段中ARM匯編使用,
".section"指令來定義段
.section name
3.注釋與標號
/*...*/
4.匯編器指令
程序中所有以“.”開頭的指令都是匯編指令,
.file:指定了源文件名,實例hello.s是從hello.c編譯得來的,手寫匯編代碼可以忽略。
.align:指定了代碼的對齊方式,后面跟的數(shù)值為2的次方,如:“.align4” 表示2^4=16個字節(jié)對齊
.ascii:聲明全局符號。全局符號是指在本程序外可以訪問的符號。
.global:聲明全局符號。全局符號是指在本程序外可以訪問的符號。
.type:指定符號的類型。“.type main,%function ” 表示main符號為函數(shù)。
.word:用來存儲地址址。"word. LCD-(LPIC0+8)"存放的是一個與地址無關(guān)的偏移量,
.size:設(shè)置指定符號的大小。“.size main ,-.main”中的點,“.表示當前地址”,減去main符號的地址即為整個
main符號的地址即為整個main函數(shù)的大小。
5.子線程與參數(shù)傳遞
.global 函數(shù)名
.type 函數(shù)名 ,%function 函數(shù)名
函數(shù)名
<....函數(shù)體...>
例如聲明一個實現(xiàn)兩個數(shù)相加的函數(shù)的代碼為:
.global MyAdd
.type MyAdd,%function
MyAdd:
ADD:r0, r0,r1 @ 兩個數(shù)相加
mov pc,lr@函數(shù)返回
ARM匯編中規(guī)定,R0-R3這4個寄存器用來傳遞函數(shù)調(diào)用的第1到第4個參數(shù),超出的參數(shù)通過堆棧來傳遞。R0同時用來存放函數(shù)調(diào)用的返回值,被調(diào)用的函數(shù)在返回前無需這些寄存器的內(nèi)容。
6.4寄存器
1,立即尋址
MOV R0 ,#1234 指令執(zhí)行后,R0=1234,立即數(shù)“#作為前綴",表示十六進制數(shù)值時以”0x“開頭
2,寄存器尋址
MOV R0 ,R1 寄存器尋址中,操作數(shù)的值在寄存器,指令執(zhí)行時直接從寄存器中取值進行操作
3,寄存器移位尋址
LSL :邏輯左移->移位后寄存器空出的低位補0
LSR:邏輯右移->移位后寄存器空出的高位補0
例如:
MOVR0 ,R1,LSL #2 表示:指令的功能是將R1寄存器左移2位,即“R1<<2” 后賦值給R0寄存器,指令執(zhí)行后R0=R1*4;
4,寄存器間接尋址
例如:寄存器間接尋址碼給出寄存器是操作數(shù)的地址指針,所需的操作數(shù)保存在寄存器指定地址的存儲單元
中,
例如:
LDRR0 ,[R1]
指令功能是將R1寄存器的數(shù)值作為地址,取出地址中的值賦值給R0寄存器。
5,基址尋址
基址尋址是將地址碼給出的寄存器與偏移量相加,形成操作數(shù)的有效地址,所需的操作數(shù)保存在有效地址所指向的存儲單元中,基址尋址多用于查表,數(shù)組訪問等操作,
例如:LDRR0 ,[R1,#-4]
指令的功能是 將R1寄存器的數(shù)值減4作為地址,取出此地址的值賦值給R0寄存器。
6,多寄存器尋址
多寄存器尋址一條指令最多可以完成16個通用寄存器值得傳遞
LDMIAR0,{R1,R2,R3,R4}
LDM是數(shù)據(jù)加載指令,指令的后綴IA表示每次執(zhí)行完加載操作后R0寄存器的值自增1個子,ARM中一個字表示的是一個字的32位數(shù)字(bit),這條指令執(zhí)行后,R1=[R0],R2=[R0+#4]
R3=[R0+#8],R4=[R0+#12]
7,堆棧尋址
堆棧尋址是ARM處理器特有的一種尋址方式,堆棧尋址需要使用特定的指令來完成
堆棧尋址的指令由LDMFA/STMFA,LDMEA/STMEA,LDMFD/STMFD
FA,EA,FD,ED 為指令前綴,表示多寄存器尋址,即一次可以傳遞多個寄存器值,F(xiàn)A,EA,FD,ED,為后綴
堆棧尋址舉例:
STMFD SP! {R1-R7,LR} @將R1~R7,LR入棧,多用于保持子線程“現(xiàn)場”
LDMFD SP! {R1-R7,LR} @將數(shù)據(jù)出棧,放入R1~R7,LR寄存器,恢復(fù)子程序“現(xiàn)場”
8,塊拷貝尋址
塊拷貝尋址可以實現(xiàn)連續(xù)地址數(shù)據(jù)從寄存器的莫某一位置拷貝到另一位置,
塊拷貝尋址的指令由
LDMIA/STMIA,LDMDA/STMDA/LDMIB/STMIB
LDM和STM為指令前綴,表示多寄存器尋址,即一次可以傳遞多個寄存器值,IA,DA,IB,DB為后綴,
塊拷貝舉例
LDMIA R0! ,{R1-R3} @從R0寄存器指向的存儲單元中讀取3個子到R1-R3寄存器
STMIA R0! ,{R1-R3} @存儲R1-R3寄存器的內(nèi)容到R0寄存器指向的存儲單元
9,相對尋址
相對尋址以程序計數(shù)器PC當前值為級地址,指令中的地址中的標號作為偏移量,將兩者相加后得到操作數(shù)的有效地址
BL NEXT
...
NEXT :
....
BL NEXT 是跳轉(zhuǎn)到NEXT標號處執(zhí)行,這里BL采用的就是相對尋址,標號NEXT 就是偏移量。
待續(xù)...


關(guān)鍵詞: AndroidARM指令學

評論


技術(shù)專區(qū)

關(guān)閉