一、ARM 指令集體系結構版本
ARM 公司定義了多個指令集版本:
ARMv1:原型機 ARM1,沒有用于商業產品。
ARMv2:擴展 V1,包含 32 位乘法指令和協處理器指令。
ARMv3:第一個微處理器 ARM6 核心,支持 Cache、MMU、寫緩沖。
ARMv4:應用最廣泛的 ARM 指令集版本。
ARM7TDMI、ARM720T、ARM9TDMI、ARM940T、ARM920T、StrongARM。
ARMv5:
ARM9E-S、ARM966E-S、ARM1020E、ARM1022E、XScale → 基于 ARMv5TE。
ARM9EJ-S、ARM926EJ-S、ARM7EJ-S、ARM1026EJ-S → 基于 ARMv5EJ。
ARM10 也采用。
后綴含義:
E:增強型 DSP 指令集,算法和 16 位乘法操作。
J:支持 Java。
ARMv6:
ARM11 系列。
ARM1136J(F)-S:SIMD、Thumb、Jazelle、DBX、VFP、MMU。
ARM1156T2(F)-S:SIMD、Thumb-2、VFP、MPU。
ARM1176JZ(F)-S:增加 MMU、TrustZone。
ARM11 MPCore:支持 1~4 核 SMP、MMU。
ARMv7-A:Cortex A7 等。
二、常用指令
1. MOV 指令
- 加載立即數到寄存器或寄存器值傳遞。
mov r0, #2 ; 加載立即數 2 到寄存器 r0
mov r1, r0 ; 將 r0 的值加載到 r1
2. ADD / SUB 指令
ADD Rd, Rn, #const
ADD Rd, Rn, Rm, <shift>SUB Rd, Rn, #const
SUB Rd, Rn, Rm, <shift>
3. 移位操作
LSL:邏輯左移
LSR:邏輯右移
ASR:算術右移(保持符號位)
ROR:循環右移
RRX:帶進位右移 1 位
移位可由立即數或寄存器指定,影響進位標志 C。
4. 立即數定義(imm12)
ARM 指令中的立即數并非任意 32 位數,而是 12 位立即數 (imm12),由以下規則決定:
條件 1:數值范圍在 0~0xFF 之間時一定是立即數。
條件 2:把數寫成二進制后,從最高位 1 到最低位 1 之間的位數 ≤ 8 位。
條件 3:補足 8 位后,右邊必須是偶數個連續的 0。
實際上 ARM 將 imm12 編碼為:
- 8 位常數 (0~255) + 4 位循環右移位數 (0~15)
- 旋轉步長是 2,即可表示 0~30 偶數位的右移。
示例:
0x234 =
0000 0010 0011 0100
→ 符合條件,是立即數。0x3F4 =
0000 0011 1111 0100
→ 符合條件,是立即數。0x132 =
0000 0001 0011 0010
→ 末尾只有 1 個 0,不符合條件。0x7F8 =
0000 0111 1111 1000
→ 末尾 3 個 0,不滿足條件。0xFAB4 =
1111 1010 1011 0100
→ 位寬超過 8 位,不是立即數。
5. LDR / STR 指令
- 加載和存儲數據:
ldr r0, =0x2FAB4 ; 常量加載
ldr r0, [r1, #4] ; 偏移尋址
ldr r0, [r1], #8 ; 讀后更新基址
ldr r0, [r1, #8]! ; 先更新基址再讀str r0, [r1, #4] ; 存儲數據
- 多寄存器操作:
ldmia r0!, {r1-r4} ; 從內存加載多個寄存器
stmfd sp!, {r0-r12, lr} ; 保存現場
6. BIC / ORR 指令
bic Rd, Rn, #const ; 清零
orr Rd, Rn, #const ; 置位
7. CMP 指令
- 比較兩個數,更新標志位。
mov r0, #100
cmp r0, #100 ; Z=1 → 相等
8. 條件執行與條件碼
指令可帶條件碼執行:
EQ:等于 (Z=1)
NE:不等于 (Z=0)
CS/HS:無符號大于等于 (C=1)
CC/LO:無符號小于 (C=0)
MI:負數 (N=1)
PL:正數 (N=0)
VS:溢出 (V=1)
VC:無溢出 (V=0)
HI:無符號大于 (C=1, Z=0)
LS:無符號小于等于 (C=0 或 Z=1)
GE:有符號大于等于 (N=V)
LT:有符號小于 (N≠V)
GT:有符號大于 (Z=0, N=V)
LE:有符號小于等于 (Z=1 或 N≠V)
AL:無條件執行
示例:
movcs r0, #100 ; 僅 C=1 時執行
9. B / BL / BX跳轉指令
指令 | 功能描述 | PC 的變化 | LR 的變化 | 跳轉目標 | 常見用途 |
---|---|---|---|---|---|
B | 無條件跳轉(類似 goto ) | PC ← PC + 偏移量(立即數) | 不變 | 立即數偏移(label 地址) | 循環、分支、跳轉到異常處理 |
BL | 跳轉并保存返回地址(函數調用) | PC ← PC + 偏移量(立即數) | LR ← 調用點下一條指令的地址 | 立即數偏移(label 地址) | 子程序調用(函數調用) |
BX | 跳轉到寄存器地址 | PC ← 指定寄存器的值 | 不變 | 任意寄存器(如 LR、R0) | 子程序返回(常見 bx lr ) |
三、棧操作
- ARM 采用 滿減棧 (Full Descending)。
入棧
stmfd sp!, {r0, r1, r2, r3-r12, lr}
出棧
ldmfd sp!, {r0, r1, r2, r3-r12, lr}
棧的實現方式
空增:先寫入數據,再自增
空減:先寫入數據,再自減
滿增:先自增,再寫入數據
滿減:先自減,再寫入數據(ARM 采用)
類型 | 含義 | 壓棧操作 | 出棧操作 | SP 指向 |
---|---|---|---|---|
滿減棧 (Full Descending, FD) | 棧向低地址增長,SP 指向已用單元 | 先遞減 SP → 寫數據 | 讀數據 → 遞增 SP | 已用單元 |
滿增棧 (Full Ascending, FA) | 棧向高地址增長,SP 指向已用單元 | 先遞增 SP → 寫數據 | 讀數據 → 遞減 SP | 已用單元 |
空減棧 (Empty Descending, ED) | 棧向低地址增長,SP 指向空單元 | 寫數據 → 遞減 SP | 遞增 SP → 讀數據 | 空單元 |
空增棧 (Empty Ascending, EA) | 棧向高地址增長,SP 指向空單元 | 寫數據 → 遞增 SP | 遞減 SP → 讀數據 | 空單元 |
四、函數與參數傳遞
匯編調用 C
import func_c
bl func_c
C 調用匯編
extern void func_asm(void);
func_asm();
參數傳遞規則
前 4 個參數 → r0 ~ r3
返回值 → r0
超過 4 個參數 → 棧傳遞
函數嵌套與現場保護
LR 會保存返回地址,但函數嵌套時 LR 會被覆蓋。
解決方法:調用前使用棧保存 LR 和相關寄存器,返回時恢復。
五、模式切換與 CPSR
CPSR(Current Program Status Register)低 5 位決定工作模式:
- User、FIQ、IRQ、Supervisor、Abort、Undefined、System
指令
mrs r0, cpsr ; 讀 CPSR
msr cpsr_c, r0 ; 寫 CPSR
常見操作:
切換工作模式:修改低 5 位
開關中斷:修改 I、F 位
六、ROM 類型分類
類型 | 是否可編程 | 是否可擦除 | 擦除方式 | 擦寫次數 | 應用場景 |
---|---|---|---|---|---|
Mask ROM | 否 | 否 | 制造時固化 | 不可擦寫 | 大批量固定程序 |
PROM | 一次 | 否 | 無 | 一次性 | 小批量定制程序 |
EPROM | 是 | 是 | 紫外線 | 少量(幾十次) | 開發測試 |
EEPROM | 是 | 是 | 電擦除(字節級) | 10^5 ~ 10^6 | BIOS、配置數據 |
Flash ROM | 是 | 是 | 電擦除(塊/扇區) | 10^4 ~ 10^5 | SSD、U盤、嵌入式系統 |
Flash ROM 分類總結表
類型 | 訪問方式 | 讀取速度 | 寫入/擦除速度 | 容量范圍 | 成本 | 常見應用 |
---|---|---|---|---|---|---|
NOR Flash | 隨機訪問(字節級/字尋址) | 快 | 慢 | MB ~ 數百 MB | 高 | 固件、Bootloader、系統代碼存儲 |
NAND Flash | 頁/塊訪問 | 較慢 | 快 | GB 級 | 低 | U 盤、SSD、SD 卡、大容量數據存儲 |
七、基本代碼實現
ARM匯編語言
area reset, readonly, codepreserve8code32entry;ldr r0, =0x40000000;ldr r1, =0x3456781A;str r1, [r0, #4] ;*(r0 + 1) = r1 ;str r1, [r0], #4 ;*r0++ = r1;str r1, [r0, #4]! ;*++r0 = r1;ldr r0, =0x40000000;ldr r3, [r0];ldr r0, = 0x40000004;ldr r4, [r0];add r5, r3, r4;ldr r0, =0x40000008;str r5, [r0];mov r0, #0;orr r0, r0, #(1 << 7) ;0000 0000 0000 0000 0000 0000 1000 0000;ldr r0, =0x7FFFFFFF ;adds r0, r0, #1;mov r0, #3;mov r1, #5;mov r2, #4;cmp r0, r1;movls r3, r1;movge r3, r0;cmp r3, r2;movls r3, r2;b lable ;branch;mov r0, #3;mov r1, #5
;lable
; mov r0, #5
; mov r1, #3
; mov r2, #4
; cmp r0, r1
; bls less
; bgt great
;great
; mov r3, r0
; b lable
;less
; mov r3, r1 ;lable
; cmp r3, r2
; bgt finished
; mov r3, r2
; mov r0, #1 ;i
; mov r1, #0 ;sum;loop
; cmp r0, #100
; bgt finished
; add r1, r1, r0
; add r0, r0, #1
; b loopldr pc, =_start_asm_maxstmfd sp!, {r0-r12, lr}bl _asm_minldmfd sp!, {r0-r12, lr} cmp r0, r1movge r2, r0movlt r2, r1bx lrexport _asm_min
_asm_mincmp r0, r1movle r2, r0movgt r2, r1mov r0, r2bx lr _startldr sp, =0x40001000mrs r0, cpsr;xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx0 0000bic r0, r0, #0x1Forr r0, r0, #0x10 ;0001 0000msr cpsr_c, r0ldr sp, =0x40001000sub sp, sp, #1024import mainb main;stmfd sp!, {r0-r12, lr};import c_max;mov r0, #2;mov r1, #3;bl c_max;ldmfd sp!, {r0-r12, lr};mov r0, #11;mov r1, #22finishedb finished end