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