1 前言
ARM既是一種處理器架構,也是一家公司,它不生產芯片,只靠芯片IP授權賺錢。
ARM處理器是英國Acorn有限公司設計的低功耗成本的第一款RISC微處理器。全稱為Advanced RISC Machine。ARM處理器本身是32位設計,但也配備16位指令集,一般來講比等價32位代碼節省達35%,卻能保留32位系統的所有優勢。
更多詳細介紹,請參考百度百科.
2 ARM知識圖譜
本文先列個大綱,后續有時間再補充。
3 ARM匯編基礎三大塊
這里整理了ARM匯編中非常基礎的三大塊知識,了解了這三大塊內容基本可以看懂甚至編譯一些簡單的匯編程序。
3.1 尋址方式
ARM的尋址方式總共有9種,包括:
3.1.1 立即尋址
操作數是立即數,以“#”為前綴,表示 16 進制數值時以“0x”表示。
例:
MOV R0,#0xFF00 ;0xFF00 -> R0
SUBS R0,R0,#1 ;R0 – 1 -> R0
3.1.2 寄存器尋址
操作數的值在寄存器中,指令執行時直接取出寄存器值操作。
例:
MOV R1,R2 ;R2 -> R1
SUB R0,R1,R2 ;R1 - R2 -> R0
3.1.3 寄存器偏移尋址
當第二操作數是寄存器偏移方式時,第二個寄存器操作數在與第一個操作數結合之前,選擇進行移位操作。
例:
MOV R0,R2,LSL #3 ;R2 的值左移 3 位,結果放入 R0,即 R0 = R2 * 8
ANDS R1,R1,R2,LSL #3 ;R2 的值左移 3 位,然后和 R1 相與操作,結果放入 R1
可采用的移位操作:
LSL:邏輯左移(Logical Shift Left),低端空出位補 0
LSR:邏輯右移(Logical Shift Right),高端空出位補 0
ASR:算術右移(Arithmetic Shift Right),移位過程中符號位不變,即源操作數為正數,則高端空出位補 0,否則補 1
ROR:循環右移(Rotate Right),由低端移出位填入高端空出位
RRX:帶擴展的循環右移(Rotate Right eXtended by 1 place),操作數右移一位,高端空出位用原 C 標志值填充。
3.1.4 寄存器間接尋址
操作數保存在寄存器指定地址的存儲單元中,即寄存器為操作數的地址指針。
例:
LDR R1,[R2] ;將 R2 中的數值作為地址,取出此地址中的數據保存在 R1 中
SWP R1,R1,[R2] ;將R2中的數值作為地址,取出此地址中的數值與 R1 中的值**
3.1.5 基址尋址
將基址寄存器的值與偏移量相加,形成操作數的有效地址,基址尋址用于訪問基址附近的存儲單元,常用于查表、數組操作、功能寄存器訪問等。
例:
LDR R2,[R3,#0x0F] ;將R3中的數值加 0x0F 作為地址,取此地址的值保存在 R2 中
STR R1,[R0,#-2] ;將R0中的數值減 2 作為地址,把 R1的值保存到此地址中
3.1.6 多寄存器尋址
一次傳送多個寄存器值,允許一條指令傳送 16 個寄存器的任何子集或所有寄存器。多寄存器尋址時,寄存器子集按由小到大的順序排列,連續的寄存器可用“-”連接,否則,用“,”分隔書寫。
例:
LDMIA R1!,{R2-R7,R12} ;將 R1的值讀出到 R2-R7,R12,過程中R1 自動加 1
STMIA R0!,{R3-R6,R10};將 R3-R6,R10的值保存到 R0 指向的地址,過程中R0 自動加 1
3.1.7 堆棧尋址
堆棧尋址使用堆棧指針SP,即R13,指向堆棧的棧頂。堆棧可分為兩種:
向上生長:向高地址方向生長,稱為遞增堆棧,
向下生長:向低地址方向生長,稱為遞減堆棧,
堆棧指針指向最后壓入的有效數據項,稱為滿堆棧,
堆棧指針指向下一個要放入的空位置,稱為空堆棧,這樣就有 4 種類型的堆棧。
A)滿遞增:堆棧地址向上增長,堆棧指針指向有效數據的最高地址。如 LDMFA,STMFA。
B)空遞增:堆棧地址向上增長,堆棧指針指向堆棧上的第一個空位置。如 LDMEA,STMEA 。
C)滿遞減:堆棧地址向下增長,堆棧指針指向有效數據項的最低地址。如 LDMFD,STMFD。
D)空遞減:堆棧地址向下增長,堆棧指針指向堆棧下的第一個空位置。如 LDMED,STMED 。
例:
STMFD SP!,{R1-R7,LR} ; 將 R1~R7,LR 入棧。滿遞減堆棧。
LDMFD SP!,{R1-R7,LR} ;數據出棧,放入 R1~R7,LR 寄存器。滿遞減堆棧。
3.1.8 塊拷貝尋址
用于將一塊數據從存儲器的某一位置拷貝到另一位置。
例:
STMIA R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中,存儲器指針在保存第一個值之后增加,增長方向為向上增長。
STMIB R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中,存儲器指針在保存第一個值之前增加,增長方向為向上增長。
STMDA R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中,存儲器指針在保存第一個值之后增加,增長方向為向下增長。
STMDB R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中,存儲器指針在保存第一個值之前增加,增長方向為向下增長。
3.1.9 相對尋址
相對尋址是基址尋址的一種變通,由程序計數器 PC 提供基準地址,指令中的地址
碼字段作為偏移量,兩者相加后得到有效地址。
例:
BL ROUTE1 ;調用ROUTE1 子程序
BEQ LOOP ;條件跳轉到 LOOP 標號處
…
LOOP MOV R2,#2
…
ROUTE1
…
3.2 寄存器的用途
3.2.1 ARM寄存器列表
ARM共有37個32位物理寄存器,7種工作模式下可訪問的寄存器見下表,User和System使用完全相同的物理寄存器。
3.2.2 ARM寄存器的用途
其中 r0~r3 主要用于子程序間傳遞參數, r4~r11 主要用于保存局部變量,但在 Thumb 程序中,通常只能使用 r4~r7 來保存局部變量; r12 用作子程序間scratch 寄存器,即 ip 寄存器; r13 通常用做棧指針,即 sp; r14 寄存器又被稱為連接寄存器(lr),用于保存子程序以及中斷的返回地址; r15 用作程序計數器(pc),由于 ARM 采用了流水線機制,當正確讀取了 PC 的值后,該值為當前指令地址加 8 個字節,即 PC 指向當前指令的下兩條指令地址。
CPSR和SPSR都是程序狀態寄存器,其中SPSR是用來保存中斷前的CPSR中的值,以便在中斷返回之后恢復處理器程序狀態。
3.2.2.1 R0~R7
所有工作模式下,R0-R7都分別指向同一個物理寄存器(共8個物理寄存器),它們未被系統用作特殊的用途。在中斷或異常處理進行工作模式轉換時,由于不同工作模式均使用相同的物理寄存器,可能造成寄存器中數據的破壞。
3.2.2.2 R8~R12
在User&System、IRQ、Svc、Abt和Und模式下訪問的R8~R12都是同一個物理寄存器(共5個物理寄存器);在FIQ模式下,訪問的R8fiq~R12fiq是另外獨立的物理寄存器(共5個物理寄存器)。
3.2.2.3 R13(SP)和R14(LR)
? 在User&System、IRQ、FIQ、Svc、Abt和Und訪問的R13_~R14都是各自模式下獨立的物理寄存器(共12個物理寄存器)。
? R13在ARM指令中常用作堆棧指針(SP),但這只是一種習慣用法,用戶也可使用其他的寄存器作為堆棧指針。而在Thumb指令集中,某些指令強制性的要求使用R13作為堆棧指針。
? 由于處理器的每種工作模式均有自己獨立的物理寄存器R13,在用戶應用程序的初始化部分,一般都要初始化每種模式下的R13,使其指向該工作模式的棧空間。這樣,當程序進入異常模式時,可以將需要保護的寄存器放入R13所指向的堆棧,而當程序從異常模式返回時,則從對應的堆棧中恢復,采用這種方式可以保證異常發生后程序的正常執行。 R14稱為鏈接寄存器(Link Register),當執行子程序調用指令(BL)時,R14可得到R15(程序計數器PC)的備份。在每一種工作模式下,都可用R14保存子程序的返回地址,當用BL或BLX指令調用子程序時,將PC的當前值復制給R14,執行完子程序后,又將R14的值復制回PC,即可完成子程序的調用返回。以上的描述可用指令完成。
執行以下任意一條指令: MOV PC, LR BX LR 在子程序入口處使用以下指令將R14存入堆棧: STMFD SP!,{,LR} 對應的,使用以下指令可以完成子程序返回: LDMFD SP!,{,PC} R14也可作為通用寄存器。
3.2.2.4 程序計數器PC(R15)
所有工作模式下訪問的R15都是同一個物理寄存器,由于ARM體系結構采用了多級流水線技術,對于ARM指令集而言,PC總是指向當前指令的下兩條指令的地址,即PC的值為當前指令的地址值加8個字節。
在ARM狀態下,R15[1:0]為0,R15[31:2]用于保存PC;在Thumb狀態下,R15[0]為0,R15[31:1]用于保存PC。
3.2.2.5 CPSR和SPSR
R16用作CPSR(Current Program Status Register,當前程序狀態寄存器),CPSR可在任何工作模式下被訪問,它包括條件標志位、中斷禁止位、當前處理器模式標志位,以及其他一些相關的控制和狀態位。
每一種工作模式下又都有一個專用的物理狀態寄存器,稱為SPSR(Specified Program Status Register,備份的程序狀態寄存器),當異常發生時,SPSR用于保存CPSR的當前值,從異常退出時則可由SPSR來恢復CPSR。 User模式和System模式不屬于異常模式,它們沒有SPSR,當在這兩種模式下訪問SPSR,結果是未知的。
2.6 CPSR各標志位含義
31 | 30 | 29 | 28 | 27 | 26 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
N | Z | C | V | Q | DNM(RAZ) | I | F | T | M4 | M3 | M2 | M1 | M0 |
N(Negative)---設置成當前指令運算結果的bit[31]的值。當兩個有符號整數運算時,N=1運算結果為負數,N=0運算結果為正。
Z(Zero)---Z=1運算結果為零;Z=0表示運算的結果不為零。對于CMP指令,Z=1表示進行比較的兩個數大小相等。
C(Carried out)---分四種情況討論 1)在加法指令中(包括比較指令CMP),當結果產生進位,則C=1,表示無符號運算發生上溢出;其他情況C=0。 2)在減法指令中(包括減法指令CMP),當運算發生借位,則C=0,表示無符號運算發生下溢出;其他情況下C=1。 3)對于包含移位操作的非加減運算指令,C中包含最后一次溢出的位的數值 4)對于其他非加減運算指令,C位的值通常不受影響 V(oVerflow)---對于加減運算指令,當操作數和運算結果為二進制的補碼表示的帶符號數時,V=1符號為溢出;通常其他指令不影響V位。
Q---在ARM V5的E系列處理器中,CPSR的bit[27]稱為Q標識位,主要用于指示增強的DSP指令是否發生了溢出。同樣的spsr的bit[27]位也稱為Q標識位,用于在異常中斷發生時保存和恢復CPSR中的Q標識位。在ARM V5以前的版本及ARM V5的非E系列的處理器中,Q標識位沒有被定義。
I和F---當I=1時禁止IRQ中斷,當F=1時禁止FIQ中斷
T---對于ARM V4以更高版本的T系列ARM處理器,T=0表示執行ARM指令;T=1表示執行Thumb指令 對于ARM V5以及更高版本的非T系列處理器,T=0表示執行ARM指令;T=1表示強制下一條執行的指令產生未定指令中斷
M[4:0]---定義了的ARM工作模式,具體見1中表CSPR[4:0]定義的ARM工作模式
3.3 匯編指令
由于ARM的指令非常多,本文僅列舉常見的一些匯編指令,更多的指令格式,請參考其他資料。
3.3.1 數據處理指令
數據傳輸指令 mov mvn 算術指令 add sub rsb adc sbc rsc 邏輯指令 and orr eor bic 比較指令 cmp cmn tst teq 乘法指令 mvl mla umull umlal smull smlal 前導零計數 clz
3.3.2 cpsr訪問指令
mrs & msr mrs用來讀psr,msr用來寫psr CPSR寄存器比較特殊,需要專門的指令訪問,這就是mrs和msr。
3.3.3 跳轉(分支)指令
b & bl & bx b 直接跳轉(就沒打開算返回) bl branch and link,跳轉前把返回地址放入lr中,以便返回,以便用于函數調用 bx跳轉同時切換到ARM模式,一般用于異常處理的跳轉。
3.3.4 訪存指令
ldr/str & ldm/stm & swp 單個字/半字/字節訪問 ldr/str 多字批量訪問 ldm/stm swp r1, r2, [r0] swp r1, r1, [r0]
3.3.5 軟中斷指令
swi(software interrupt) 軟中斷指令用來實現OS中系統調用
4 更多分享
歡迎關注我的github倉庫01workstation,日常分享一些開發筆記和項目實戰,歡迎指正問題。
同時也非常歡迎關注我的CSDN主頁和專欄:
【CSDN主頁:架構師李肯】
【RT-Thread主頁:架構師李肯】
【GCC專欄】
【信息安全專欄】
【RT-Thread開發筆記】
【freeRTOS開發筆記】
【BLE藍牙開發筆記】
【ARM開發筆記】
【RISC-V開發筆記】
有問題的話,可以跟我討論,知無不答,謝謝大家。
5 參考鏈接
- ARM尋址方式
- ARM寄存器
- ARM指令
-
ARM
+關注
關注
134文章
9169瀏覽量
369239 -
嵌入式
+關注
關注
5093文章
19178瀏覽量
307713 -
RT-Thread
+關注
關注
31文章
1305瀏覽量
40388
發布評論請先 登錄
相關推薦
評論