ARM-彙編指令集(總結)
https://www.cnblogs.com/wxb20/p/6249580.html
ARM彙編指令集
指令、偽指令
(彙編)指令: 是機器碼的助記符,經過彙編器編譯後,由CPU執行。
(彙編)偽指令:用來指導指令執行,是彙編器的產物,最終不會生成機器碼。
有兩種不同風格的ARM指令
1).ARM官方的ARM彙編風格:指令一般用大寫,Windows中的IDE開發環境。
2).GNU風格的ARM彙編:指令一般用小寫。
ARM彙編的特點
- LDR/STR架構
1).ARM採用RISC架構,CPU本身不能直接讀取記憶體,而需要先將記憶體中內容載入入CPU中通用暫存器中才能被CPU處理。
2).ldr(load register)指令將記憶體內容載入入通用暫存器。
3).str(store register)指令將暫存器內容存入記憶體空間中。
4).ldr/str組合用來實現 ARM CPU和記憶體資料交換。
- 至此8種定址方式
1).暫存器定址mov r1, r2。
2).立即(立即數)定址 mov r0, #0xFF00。
3).暫存器移位定址 mov r0, r1, lsl #3。
4).暫存器間接定址 ldr r1, [r2] 表示記憶體,記憶體地址存在r2這個暫存器中,把記憶體地址裡的值給r1。
5).基址變址定址ldr r1, [r2, #4]記憶體地址在r2+4裡面。
6).多暫存器定址 ldmia r1!, {r2-r7, r12}一次訪問多個暫存器。
7).堆疊定址 stmfd sp!, {r2-r7, lr}。
8).相對定址 beq flag。
- 指令字尾
同一指令經常附帶不同字尾,變成不同的指令。經常使用的字尾有:
B(byte)功能不變,操作長度變為8位
H(half word)功能不變,長度變為16位
S(signed)功能不變,運算元變為有符號
如 ldr ldrb ldrh ldrsb ldrsh
S(S標誌)功能不變,影響CPSR標誌位
如 mov和movs movs r0, #0
- 條件執行字尾
條件字尾是否成立取決於當前程式碼的前面的程式碼。
條件字尾隻影響當前程式碼的執行。
- 多級指令流水線
為增加處理器指令流的速度,ARM使用多級流水線.,下圖為3級流水線工作原理示意圖。(S5PV210使用13級流水線,ARM11為8級)
允許多個操作同時處理,而非順序執行。
1).PC指向正被取指的指令,而非正在執行的指令
資料傳輸與跳轉指令詳解
-
資料處理指令
資料傳輸指令 mov mvn
算術指令 add sub rsb adc sbc rsc
邏輯指令 and orr eor bic
比較指令 cmp cmn tst teq
乘法指令 mvl mla umull umlal smull smlal
前導零計數 clz -
cpsr訪問指令
mrs & msr
mrs用來讀psr,msr用來寫psr
CPSR暫存器比較特殊,需要專門的指令訪問,這就是mrs和msr。 -
跳轉(分支)指令
b & bl & bx
b 直接跳轉(就沒開啟算返回)
bl branch and link,跳轉前把返回地址放入lr中,以便返回,以便用於函式呼叫
bx跳轉同時切換到ARM模式,一般用於異常處理的跳轉。 -
訪存指令
ldr/str & ldm/stm & swp
單個字/半字/位元組訪問 ldr/str
多字批量訪問 ldm/stm
swp r1, r2, [r0]
swp r1, r1, [r0]
- 軟中斷指令
swi(software interrupt)
軟中斷指令用來實現OS中系統呼叫
ARM彙編中的立即數
合法立即數與非法立即數
ARM指令都是32位,除了指令標記和操作標記外,本身只能附帶很少位數的立即數。因此立即數有合法和非法之分。
合法立即數:經過任意位數的移位後非零部分可以用8位表示的即為合法立即數。
協處理器與協處理器指令集
6.協處理器cp15操作指令
mcr & mrc
mrc用於讀取CP15中的暫存器
mcr用於寫入CP15中的暫存器
7.arm定址方式
1). 暫存器: MOV R1,R2 ; R2->R1
2). 立即數: SUBS R0,R1,#1; R0=R1-1
3). 暫存器移位:MOV R0,R2,LSL #3 ;R2左移三位->R0
4). 間接定址: LDR R1,[R2] ; 裝載R2指向的記憶體數值至R1
5). 基址定址: LDR R2,[R3,#0x0F] ;R3+0x0F作為地址,將所指向的置裝入R2.R3的值不改變
6). 多暫存器定址: LDMIA R1!,{R2-R7,R12} ; 將R1所指向的記憶體塊依次裝入{}中的暫存器。
STMIA R0!,{R3-R6,R10} ;將{}列出的暫存器裡的值依次填入R0所指向的記憶體塊。
7). 相對定址: BL XXX ;跳轉
BEQ XXX ;條件跳轉
協處理器解析:
SoC內部另一處理核心,協助主CPU實現某些功能,被主CPU呼叫執行一定任務。
ARM設計上支援多達16個協處理器,但是一般SoC只實現其中的CP15.(cp:coprocessor)
協處理器和MMU、cache、TLB等處理有關,功能上和作業系統的虛擬地址對映、cache管理等有關。
MRC & MCR的使用方法
mcr{} p15, <opcode_1>, , , , {<opcode_2>}
opcode_1:對於cp15永遠為0
Rd:ARM的普通暫存器
Crn:cp15的暫存器,合法值是c0~c15
Crm:cp15的暫存器,一般均設為c0
opcode_2:一般省略或為。
ldm/stm與棧的處理
為什麼需要多暫存器訪問指令
ldr/str每週期只能訪問4位元組記憶體,如果需要批量讀取、寫入記憶體時太慢,解決方案是stm/ldm
ldm(load register mutiple)
stm(store register mutiple)
舉例(uboot start.S 537行)
stmia sp, {r0 - r12}
將r0存入sp指向的記憶體處(假設為0x30001000);然後地址+4(即指向0x30001004),將r1存入該地址;然後地址再+4(指向0x30001008),將r2存入該地址······直到r12內容放入(0x3001030),指令完成。
一個訪存週期同時完成13個暫存器的讀寫
字尾的種類:
ia(increase after)先傳輸,再地址+4
ib(increase before)先地址+4,再傳輸
da(decrease after)先傳輸,再地址-4
db(decrease before)先地址-4,再傳輸
fd(full decrease)滿遞減堆疊
ed(empty decrease)空遞減堆疊
fa(·······) 滿遞增堆疊
ea(·······)空遞增堆疊
四種棧解析:
空棧:棧指標指向空位,每次存入時可以直接存入然後棧指標移動一格;而取出時需要先移動一格才能取出。
滿棧:棧指標指向棧中最後一格資料,每次存入時需要先移動棧指標一格再存入;取出時可以直接取出,然後再移動棧指標。
增棧:棧指標移動時向地址增加的方向移動的棧。
減棧:棧指標移動時向地址減小的方向移動的棧。
!的作用:
ldmia r0, {r2 - r3}
ldmia r0!, {r2 - r3}
感嘆號的作用就是r0的值在ldm過程中發生的增加或者減少最後寫回到r0去,也就是說ldm時會改變r0的值。
^的作用:
ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^
^的作用:在目標暫存器中有pc時,會同時將spsr寫入到cpsr,一般用於從異常模式返回。
總結:批量讀取或寫入記憶體時要用ldm/stm指令。
各種字尾以理解為主,不需記憶,最常見的是stmia和stmfd。
謹記:操作棧時使用相同的字尾就不會出錯,不管是滿棧還是空棧、增棧還是減棧。
常用gun偽指令:
global _start @ 給_start外部連結屬性
.section .text @ 指定當前段為程式碼段
.ascii .byte .short .long .word .quad .float .string @ 定義資料
.align 4 @ 以2*4位元組對齊
.balignl 16 0xabcdefgh @ 16位元組對齊填充
.equ @ 類似於C中巨集定義
偶爾會用到的gun偽指令
.end @標識檔案結束
.include @ 標頭檔案包含
.arm / .code32 @宣告以下為arm指令
.thumb / .code16 @宣告以下為thubm指令
重要的幾個偽指令
ldr 大範圍的地址載入指令
adr 小範圍的地址載入指令
adrl 中等範圍的地址載入指令
nop 空操作
ARM中有一個ldr指令,還有一個ldr偽指令
一般都使用ldr偽指令而不用ldr指令
adr與ldr
adr編譯時會被1條sub或add指令替代,而ldr編譯時會被一條mov指令替代或者文字池方式處理;
adr總是以PC為基準來表示地址,因此指令本身和執行地址有關,可以用來檢測程式當前的執行地址在哪裡
ldr載入的地址和連結時給定的地址有關,由連結指令碼決定。
@筆記記得有點不清晰,希望在學習ARM在座的各位指出哪有錯,大家一起進步,共同學習。@
/******************************** Stay hungry, Stay foolish. @Rocky ********************************/