ARM-指令集全解析:从基础到高阶应用

一、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汇编语言

cs 复制代码
	area reset, readonly, code
	preserve8
	code32
	entry
	
	;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 loop

	ldr pc, =_start

_asm_max
	stmfd sp!, {r0-r12, lr}
	bl _asm_min
	ldmfd sp!, {r0-r12, lr} 
	cmp r0, r1
	movge r2, r0
	movlt r2, r1
	bx lr

	export _asm_min
_asm_min
	cmp r0, r1
	movle r2, r0
	movgt r2, r1
	mov r0, r2
	bx lr		

_start
	ldr sp, =0x40001000

	mrs r0, cpsr
   	;xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx0 0000
	bic r0, r0, #0x1F
	orr r0, r0, #0x10 ;0001 0000
	msr	cpsr_c, r0

	ldr sp, =0x40001000
	sub sp, sp, #1024

	import main
	b 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, #22


finished
	b finished	
	end
相关推荐
17(无规则自律)6 小时前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞18 小时前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠1 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember2 天前
Linux网络基础
linux·网络·arm开发
代码游侠2 天前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
程序猿阿伟2 天前
《Apple Silicon与Windows on ARM:引擎原生构建与模拟层底层运作深度解析》
arm开发·windows
wkm9562 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt
unicrom_深圳市由你创科技2 天前
基于ARM+DSP+FPGA异构计算架构的高速ADC采集卡定制方案
arm开发·fpga开发
松涛和鸣2 天前
DAY69 Practical Guide to Linux Character Device Drivers
linux·服务器·arm开发·数据库·单片机·嵌入式硬件
松涛和鸣2 天前
69、Linux字符设备驱动实战
linux·服务器·网络·arm开发·数据库·驱动开发