一.指令與僞指令
指令:CPU機器指令的助記符,經過編譯後會得到一串10組成的機器碼,可以由CPU讀取執行。
僞指令:本質上不是指令(只是和指令代碼一起寫在代碼中),它是編譯器環境提供的,目的是用來指導編譯過程,經過編譯後僞指令最終不會生成機器碼。
二:ARM彙編特點:
2.1:LDR/STR架構
ARM採用RISC架構,CPU本身不能直接讀取內存,而需要先將內存中內容加載入CPU中通用寄存器中才能被CPU處理。
ldr(load register)指令將內存內容加載入通用寄存器
str(store register)指令將寄存器內容存入內存空間中
ldr/str組合用來實現ARM CPU和內存數據交換
2.2:8種尋址方式
寄存器尋址: 寄存器r2的值賦給r1
mov r1, r2
立即尋址: 把0xFF00給r0寄存器
mov r0, #0xFF00
寄存器移位尋址: 把r1左移三位後賦值給r0
mov r0, r1, lsl #3
寄存器間接尋址: r2類似一個指針,r2指向一個內存地址,[]類似於C間接尋址,將r2指向內存的值賦給r1寄存器
ldr r1, [r2]
基址變址尋址: r2所指向的地址偏移4位後的內存地址賦給r1
ldr r1, [r2, #4]
多寄存器尋址: r1裏面放了內存地址,類似於數組,r1裏面7個元素,依次放到寄存器裏面
ldmia r1!, {r2-r7, r12}
堆棧尋址: sp棧指針,連續訪問數據放到寄存器
stmfd sp!, {r2-r7, lr}
相對尋址: 標號跳轉到標號執行
beq flag
flag:
2.3:條件後綴執行
mov r0,r1: 相當於C中的r0=r1
moveq r0,r1: 如果eq後綴成立,則直接執行mov r0,r1;如果eq本身不成立則本句代碼直接作廢,相當於沒有。類似與C語言中的if(eq)(r0 = r1;)
條件後綴執行注意2點:
1、條件後綴是否成立,不是取決於本句代碼,而是取決於這句代碼之前的代碼運行後的結果。
2、條件後綴決定了本句代碼是否被執行,而不會影響上一句和下一句代碼是否被執行
三:一些特殊指令
3.1 mvn:
mvn和mov用法一樣,mov是原封不動的傳遞,而mvn是按位取反後傳遞
譬如r1=0xff ,然後mov r0,r1後,r0 = 0xff 但是mvn r0,r1後,r0=0xff000000
and 邏輯與
orr 邏輯或
eor 邏輯異或
3.2 bic位清除指令
bic r0,r1,#0x1f @將r1中的數bit0到bit4清零後賦值給r0
3.3 比較指令cmp,cmn
比較指令:
cmp cmp r0,r1 等價於 sub r2,r0,r1(r2 = r0 - r1)
cmn cmn r0,r1 等價於 add r0,r1
比較指令用來比較2個寄存器中的數
注意:比較指令不用後加s後綴就可以影響cpsr中的標誌位
3.4 cpsr和spsr的區別和聯繫:
cpsr是程序狀態寄存器,整個SoC中只有1個;而spsr有5個,分別在5種異常模式下,作用是當從普通模式進入異常模式時,用來保存之前普通模式下的cpsr的,以在返回普通模式時恢復原來的cpsr.
cpsr訪問指令:
mrs & msr
mrs用來讀psr,msr用來寫
cpsr寄存器比較特殊,需要專門的指令訪問,這就是mrs和msr.
舉個例子:
@IRQ & FIQ disable
mrs r0,cpsr @cpsr讀到r0
bic r0,r0,#0x1f @bit0到bit5清除
orr r0,r0,#0xd3 @位或0xd3 11010011 (I & F disable and 10011模式) 查看cpsr程序狀態寄存器
msr cpsr,r0 @r0寫進cpsr
3.5 跳轉指令:
b直接跳轉
bl(跳轉前把返回地址放入lr中,以便返回,以便用於函數調用)跳轉後返回
四:協處理器
格式:
mrc p15 ,0 ,r0 ,c1 ,c0,0 @把cp15協處理器裏面 的c1值讀到cpu寄存器r0
bic r0,r0 #0x00002000
.
.
.
mcr p15,0,r0,c1,c0,0 @把cpu寄存器r0裏面的值寫到cp15協處理器c1裏面
如何看懂以上指令作用?
可百度查到相應寄存器的功能表,每一個bit位置爲不同數,表示不同的實現功能。會看懂即可,沒必要深究
五:多寄存器訪問指令
ldr/str每週期只能訪問4字節內存,如果需要批量讀取、寫入內存時太慢,解決方案是stm/ldm
ldm(load register mutiple)
stm(store register mutiple
舉例:
stmia sp, {r0 - r12}
@將r0存入sp指向的內存處(假設爲0x30001000);然後地址+4(即指向0x30001004),將r1存入該地址;然後地址再+4(指向0x30001008),將r2存入該地址······直到r12內容放入(0x3001030),指令完成。
一個訪存週期同時完成13個寄存器的讀寫
8種後綴:
ia(increase after)先傳輸,再地址+4
ib(increase before)先地址+4,再傳輸
da(decrease after)先傳輸,再地址-4
db(decrease before)先地址-4,再傳輸
fd(full decrease)滿遞減堆棧
ed(empty decrease)空遞減堆棧
fa(·······) 滿遞增堆棧
ea(·······)空遞增堆棧
ia對應空增棧
ib對應滿增棧
da對應空減棧
db對應滿減棧
最常見的是stmia和stmfd
四種棧
空棧:棧指針指向空位,每次存入時可以直接存入然後棧指針移動一格;而取出時需要先移動一格才能取出
滿棧:棧指針指向棧中最後一格數據,每次存入時需要先移動棧指針一格再存入;取出時可以直接取出,然後再移動棧指針
增棧:棧指針移動時向地址增加的方向移動的棧
減棧:棧指針移動時向地址減小的方向移動的棧
謹記:操作棧時使用相同的後綴就不會出錯,不管是滿棧還是空棧、增棧還是減棧