ARM 架构的 STM32 系列微控制器广泛应用于嵌入式系统开发,理解其汇编语言指令对于优化性能、访问硬件底层非常重要。下面详细解释常见的 ARM 汇编指令及其使用实例。
数据处理指令
1. MOV
(移动)
- 功能:将立即数或寄存器值复制到目标寄存器。
- 语法:
MOV Rd, Rn
或MOV Rd, #immediate
- 实例:
MOV R0, #10 ; R0 = 10(立即数) MOV R1, R0 ; R1 = R0(寄存器到寄存器)
2. ADD
(加法)
- 功能:两个操作数相加,结果存入目标寄存器。
- 语法:
ADD Rd, Rn, Rm
或ADD Rd, Rn, #immediate
- 实例:
ADD R2, R0, R1 ; R2 = R0 + R1 ADD R3, R2, #5 ; R3 = R2 + 5
3. SUB
(减法)
- 功能:两个操作数相减,结果存入目标寄存器。
- 语法:
SUB Rd, Rn, Rm
或SUB Rd, Rn, #immediate
- 实例:
SUB R4, R3, R1 ; R4 = R3 - R1 SUB R5, R4, #2 ; R5 = R4 - 2
4. CMP
(比较)
- 功能:比较两个操作数,设置标志位(不存储结果)。
- 语法:
CMP Rn, Rm
或CMP Rn, #immediate
- 实例:
CMP R0, R1 ; 比较 R0 和 R1(R0 - R1) ; 根据比较结果设置标志位(Z=1 表示相等,N=1 表示 R0 < R1)
内存访问指令
1. LDR
(加载字)
- 功能:从内存加载 32 位数据到寄存器。
- 语法:
LDR Rd, [Rn, #offset]
- 实例:
LDR R0, [R1] ; R0 = 内存地址 R1 处的数据 LDR R2, [R1, #4] ; R2 = 内存地址 R1+4 处的数据
2. STR
(存储字)
- 功能:将寄存器数据存储到内存。
- 语法:
STR Rd, [Rn, #offset]
- 实例:
STR R0, [R1] ; 内存地址 R1 = R0 STR R2, [R1, #8] ; 内存地址 R1+8 = R2
分支指令
1. B
(无条件跳转)
- 功能:跳转到指定地址执行。
- 语法:
B label
- 实例:
B loop ; 跳转到 loop 标签处
2. BEQ
(相等时跳转)
- 功能:如果 Z 标志位为 1(上一次比较结果相等),则跳转。
- 语法:
BEQ label
- 实例:
CMP R0, R1 ; 比较 R0 和 R1 BEQ equal ; 如果 R0 == R1,跳转到 equal
3. BL
(带链接跳转)
- 功能:跳转到子程序并保存返回地址到 LR(R14)。
- 语法:
BL function
- 实例:
BL delay ; 调用 delay 子程序 ; 执行完 delay 后,通过 BX LR 返回
位操作指令
1. AND
(按位与)
- 功能:两个操作数按位与,结果存入目标寄存器。
- 语法:
AND Rd, Rn, Rm
- 实例:
AND R0, R0, #0x0F ; 保留 R0 的低4位,高28位清零
2. ORR
(按位或)
- 功能:两个操作数按位或,结果存入目标寄存器。
- 语法:
ORR Rd, Rn, Rm
- 实例:
ORR R0, R0, #0x01 ; 设置 R0 的最低位为1
3. EOR
(按位异或)
- 功能:两个操作数按位异或,结果存入目标寄存器。
- 语法:
EOR Rd, Rn, Rm
- 实例:
EOR R0, R0, #0xFF ; 翻转 R0 的低8位
实例:LED 闪烁程序
下面是一个使用 STM32 汇编控制 LED 闪烁的完整示例:
; STM32F103 LED闪烁程序
.syntax unified
.cpu cortex-m3
.thumb
; 寄存器地址定义
.equ RCC_APB2ENR, 0x40021018 ; 外设时钟使能寄存器
.equ GPIOC_CRH, 0x40011004 ; GPIOC配置寄存器高
.equ GPIOC_ODR, 0x4001100C ; GPIOC输出数据寄存器
.equ LED_PIN, 0x1000 ; PC13对应的位
; 代码段
.section .text
.global _start
_start:
; 初始化堆栈指针
LDR r0, =_estack
MOV sp, r0
; 使能GPIOC时钟
LDR r0, =RCC_APB2ENR
LDR r1, [r0]
ORR r1, r1, #0x00000010 ; 使能GPIOC时钟
STR r1, [r0]
; 配置PC13为推挽输出(模式11: 50MHz,CNF00: 通用推挽输出)
LDR r0, =GPIOC_CRH
LDR r1, [r0]
BIC r1, r1, #0x00F00000 ; 清除PC13的配置位
ORR r1, r1, #0x00300000 ; 设置PC13为50MHz推挽输出
STR r1, [r0]
loop:
; 点亮LED(PC13输出低电平)
LDR r0, =GPIOC_ODR
LDR r1, [r0]
BIC r1, r1, #LED_PIN ; 清除PC13位(输出低)
STR r1, [r0]
; 延时
BL delay
; 熄灭LED(PC13输出高电平)
LDR r0, =GPIOC_ODR
LDR r1, [r0]
ORR r1, r1, #LED_PIN ; 设置PC13位(输出高)
STR r1, [r0]
; 延时
BL delay
B loop ; 无限循环
; 简单延时函数
delay:
PUSH {r0, r1}
MOV r0, #0xFFFF ; 外层循环计数
delay_outer:
MOV r1, #0xFFFF ; 内层循环计数
delay_inner:
SUBS r1, r1, #1 ; 递减计数
BNE delay_inner ; 不为0则继续循环
SUBS r0, r0, #1 ; 外层计数递减
BNE delay_outer ; 不为0则继续循环
POP {r0, r1}
BX lr ; 返回
总结
ARM 汇编指令是开发 STM32 微控制器的基础,掌握数据处理、内存访问、分支跳转和位操作指令后,可以实现底层硬件控制和高性能代码优化。实际开发中,通常结合 C 语言和汇编以平衡效率和可维护性。