ARM匯編概述:Cortex-M3/M4實(shí)戰(zhàn)指南
Cortex-M3/M4是嵌入式開發(fā)中最主流的ARM內(nèi)核,廣泛應(yīng)用于STM32等微控制器。其匯編語言遵循RISC架構(gòu)"精簡高效"的設(shè)計(jì)理念。本文從核心寄存器到常用指令,再到實(shí)戰(zhàn)示例,層層遞進(jìn)講解ARM匯編的核心邏輯。
一、核心寄存器(匯編的"操作對(duì)象")
Cortex-M3/M4的寄存器是匯編指令的直接操作對(duì)象,無需記憶所有寄存器,僅需掌握以下高頻核心寄存器,即可覆蓋絕大多數(shù)嵌入式開發(fā)場(chǎng)景。
1. 通用寄存器
| 寄存器 | 別名 / 功能 | 核心用途 |
|---|---|---|
| R0-R7 | 低寄存器 | 暫存運(yùn)算數(shù)據(jù)、傳遞函數(shù)前4個(gè)參數(shù)、存儲(chǔ)內(nèi)存地址(配合LDR/STR訪問RAM/ROM) |
| R13 | SP(棧指針) | 指向棧頂,管理函數(shù)調(diào)用時(shí)的上下文保存與恢復(fù)。Cortex-M默認(rèn)采用滿遞減棧模型 |
| R14 | LR(鏈接寄存器) | 保存函數(shù)調(diào)用后的返回地址(BL指令自動(dòng)存入)。 |
| R15 | PC(程序計(jì)數(shù)器) | 指向當(dāng)前執(zhí)行的指令地址,修改PC可實(shí)現(xiàn)跳轉(zhuǎn)。Cortex-M始終處于Thumb狀態(tài),故PC的BIT0必須為1。 |
2. 程序狀態(tài)寄存器
程序狀態(tài)寄存器(xPSR)由APSR(應(yīng)用狀態(tài)寄存器)、IPSR(中斷程序狀態(tài)寄存器)和EPSR(執(zhí)行程序狀態(tài)寄存器)三個(gè)部分組合而成,其中APSR需重點(diǎn)關(guān)注,其4個(gè)標(biāo)志位是"條件指令"的核心判斷依據(jù):
- N(負(fù)標(biāo)志):運(yùn)算結(jié)果為負(fù)(最高位為1)時(shí)N=1,否則為0;用于判斷有符號(hào)數(shù)的正負(fù)。
- Z(零標(biāo)志):運(yùn)算結(jié)果為0時(shí)Z=1,否則為0;常用于循環(huán)結(jié)束判斷(如計(jì)數(shù)到0)、相等比較(如
CMP R0, R1后用BEQ跳轉(zhuǎn))。 - C(進(jìn)位/借位標(biāo)志):加法有進(jìn)位或減法無借位時(shí)C=1,否則為0;用于多字節(jié)運(yùn)算(如64位數(shù)據(jù)加法)。
- V(溢出標(biāo)志):有符號(hào)數(shù)運(yùn)算超出32位范圍時(shí)V=1,否則為0;用于檢測(cè)有符號(hào)數(shù)運(yùn)算錯(cuò)誤(如
0x7FFFFFFF + 1會(huì)溢出)。
二、ARM常用匯編指令
Cortex-M3/M4架構(gòu)遵循Load-Store原則,即數(shù)據(jù)處理指令只操作寄存器,與內(nèi)存的數(shù)據(jù)交換必須通過LDR(從內(nèi)存加載數(shù)據(jù)到寄存器)和STR(將寄存器數(shù)據(jù)存儲(chǔ)到內(nèi)存)指令完成。
1. 數(shù)據(jù)處理指令(CPU內(nèi)部寄存器運(yùn)算)
僅操作通用寄存器,不直接訪問內(nèi)存,是實(shí)現(xiàn)"加減、比較、位操作"等邏輯的核心。
(1)MOV:數(shù)據(jù)傳送指令
核心作用:實(shí)現(xiàn)數(shù)據(jù)在寄存器間的傳遞,或立即數(shù)到寄存器的加載。
語法:MOV{S}{cond} Rd, Op2
{S}:可選,指令執(zhí)行后更新APSR標(biāo)志(如MOVS R0, #0會(huì)設(shè)置Z=1)。{cond}:可選,條件執(zhí)行后綴(如MOVNE R0, #0xFF表示"若Z=0(前序運(yùn)算結(jié)果非0),則執(zhí)行")。Op2:可以是立即數(shù)或另一個(gè)寄存器,并可包含移位操作(如R3, LSL #2)。
示例:
MOV R0, #0x20000000 ; R0 = 0x20000000(加載RAM基地址)
MOVS R1, #0 ; R1 = 0,同時(shí)更新APSR的Z標(biāo)志(Z=1)
MOV R2, R3, LSL #2 ; R2 = R3 << 2(將R3的值左移2位后存入R2)
(2)ADD/SUB:加減指令
核心作用:實(shí)現(xiàn)寄存器或立即數(shù)的加減運(yùn)算。
語法:
- ADD(加法):
ADD{S}{cond} Rd, Rn, Op2(Rd = Rn + Op2) - SUB(減法):
SUB{S}{cond} Rd, Rn, Op2(Rd = Rn - Op2)
示例:
; ADD示例
ADD R0, R1, #5 ; R0 = R1 + 5
ADDS R2, R3, R4 ; R2 = R3 + R4,同時(shí)更新APSR
; SUB示例
SUB R0, R1, #10 ; R0 = R1 - 10
SUBS R5, R5, #1 ; R5自減1(循環(huán)計(jì)數(shù)器),并更新標(biāo)志位
(3)CMP:比較指令
核心作用:隱性計(jì)算"Rn - Op2",不保存結(jié)果,僅更新APSR標(biāo)志,為后續(xù)"條件跳轉(zhuǎn)"做準(zhǔn)備。
語法:CMP{cond} Rn, Op2
示例:
CMP R0, #100 ; 比較R0與100
BEQ LoopEnd ; 若Z=1(R0=100),跳轉(zhuǎn)到LoopEnd
BNE LoopContinue ; 若Z=0(R0≠100),跳轉(zhuǎn)到LoopContinue
2. 內(nèi)存訪問指令
(1)LDR:讀內(nèi)存指令
核心作用:將內(nèi)存中的數(shù)據(jù)讀取到寄存器。
語法:LDR{type}{cond} Rd, [Rn {, #offset}]
{type}:可選,指定數(shù)據(jù)類型(B=無符號(hào)字節(jié)、H=無符號(hào)半字、默認(rèn)=字)。- 尋址方式:偏移尋址(
[Rn, #4]):地址 = Rn + 4,Rn不變。前索引([Rn, #4]!):地址 = Rn + 4,然后更新Rn = Rn + 4。后索引([Rn], #4):地址 = Rn,然后更新Rn = Rn + 4。
示例:
LDR R0, [R1] ; 讀R1指向的4字節(jié)數(shù)據(jù)到R0
LDRB R2, [R1, #1] ; 讀R1+1地址的1字節(jié)到R2
LDRH R3, [R1], #2 ; 讀R1指向的2字節(jié)到R3,然后R1 = R1 + 2
(2)STR:寫內(nèi)存指令
核心作用:將寄存器中的數(shù)據(jù)寫入內(nèi)存。
語法:與LDR一致(Rd為源寄存器)。
示例:
STR R0, [R1] ; 將R0的4字節(jié)數(shù)據(jù)寫入R1指向的地址
STRH R2, [R1, #4]! ; 將R2的2字節(jié)數(shù)據(jù)寫入R1+4,然后R1 = R1 + 4
(3)PUSH/POP:棧操作指令
核心作用:批量保存/恢復(fù)寄存器到棧,是函數(shù)調(diào)用時(shí)保護(hù)上下文的標(biāo)準(zhǔn)且推薦的方式。它們是STMFD SP!和LDMFD SP!的別名,專用于棧操作,更簡潔直觀。
語法:
- 入棧(保存寄存器):
PUSH {reglist} - 出棧(恢復(fù)寄存器):
POP {reglist}
示例:
; 函數(shù)入口:保存R4-R6(需保護(hù)的寄存器)和LR(返回地址)
PUSH {R4-R6, LR} ; 入棧,SP相應(yīng)遞減
; 函數(shù)體 ... (可安全使用R4-R6)
; 函數(shù)出口:恢復(fù)寄存器并返回
POP {R4-R6, PC} ; 出棧,恢復(fù)R4-R6,并將LR的值直接彈出到PC(實(shí)現(xiàn)返回)
3. 跳轉(zhuǎn)與函數(shù)調(diào)用指令(程序流控制)
(1)B:無條件/條件跳轉(zhuǎn)
核心作用:直接修改PC值,跳轉(zhuǎn)到指定標(biāo)號(hào),適用于"循環(huán)、分支判斷"。
語法:B{cond} Label
示例:
B MainLoop ; 無條件跳轉(zhuǎn)到MainLoop
CMP R0, #0
BNE ErrorHandler ; 若R0≠0,跳轉(zhuǎn)到ErrorHandler
(2)BL:函數(shù)調(diào)用指令
核心作用:跳轉(zhuǎn)前自動(dòng)將返回地址(下一條指令地址)存入LR,用于函數(shù)調(diào)用。
語法:BL{cond} Label
示例:
BL Delay ; 調(diào)用Delay函數(shù),LR = 返回地址
MOV R1, #1 ; Delay返回后,從此處繼續(xù)執(zhí)行
Delay:
MOV R0, #100000
DelayLoop:
SUBS R0, R0, #1
BNE DelayLoop
BX LR ; 使用 BX LR 返回調(diào)用處
(3)偽指令
LDR =val:加載任意32位數(shù)值到寄存器。
LDR R0, =0x12345678 ; 加載非立即數(shù)
LDR R1, =0x10 ; 編譯器可能優(yōu)化為 MOV R1, #0x10
ADR:獲取標(biāo)號(hào)的相對(duì)地址(短距離)。
ADR R0, DataBuf ; 將DataBuf的地址加載到R0
DataBuf DCD 0x00, 0x01, 0x02
三、完整示例程序
以下示例覆蓋"棧操作、函數(shù)調(diào)用、內(nèi)存讀寫、數(shù)據(jù)校驗(yàn)"四大核心場(chǎng)景,并使用推薦的PUSH/POP指令。
; 程序說明:Cortex-M3/M4匯編實(shí)戰(zhàn)示例
; 核心功能:1.棧保存寄存器 2.調(diào)用延時(shí)函數(shù) 3.讀寫RAM數(shù)據(jù) 4.校驗(yàn)數(shù)據(jù)一致性 5.循環(huán)執(zhí)行
AREA ARM_Demo, CODE, READONLY
ENTRY
THUMB ; 明確指定使用Thumb指令集
ALIGN 4
; --------------------------
; 主函數(shù):程序核心邏輯入口
; --------------------------
Main
; 1.棧操作:在函數(shù)入口保存可能被使用的寄存器及返回地址,遵守調(diào)用規(guī)范
PUSH {R0-R2, LR} ; 使用PUSH保存寄存器
; 2.內(nèi)存讀寫:向RAM地址(0x20000000)寫入數(shù)據(jù),再讀取校驗(yàn)
MOV R0, #0x20000000 ; R0 = RAM基地址
LDR R1, =0x12345678 ; R1 = 待寫入數(shù)據(jù)
STR R1, [R0] ; 寫操作:將數(shù)據(jù)寫入內(nèi)存
LDR R2, [R0] ; 讀操作:從內(nèi)存讀取數(shù)據(jù)
; 3.數(shù)據(jù)校驗(yàn):比較"寫入值(R1)"與"讀取值(R2)"
CMP R1, R2
BEQ Data_OK ; 若數(shù)據(jù)一致,跳轉(zhuǎn)
MOV R3, #0x00 ; 數(shù)據(jù)不一致:R3 = 0x00(錯(cuò)誤標(biāo)志)
B Call_Delay
Data_OK
MOV R3, #0xFF ; 數(shù)據(jù)一致:R3 = 0xFF(成功標(biāo)志)
; 4.調(diào)用延時(shí)函數(shù)
Call_Delay
BL Delay_Func ; 調(diào)用延時(shí)函數(shù)
; 5.恢復(fù)寄存器并返回:從棧中恢復(fù)R0-R2,并通過將LR彈出至PC來返回到調(diào)用者,實(shí)現(xiàn)循環(huán)
POP {R0-R2, PC} ; 使用POP恢復(fù)寄存器并返回
; --------------------------
; 延時(shí)函數(shù):簡單遞減延時(shí)
; --------------------------
Delay_Func
PUSH {R0, LR} ; 延時(shí)函數(shù)也保護(hù)它用到的寄存器和LR
LDR R0, =500000
Delay_Loop
SUBS R0, R0, #1
BNE Delay_Loop
POP {R0, PC} ; 恢復(fù)R0,并通過彈出LR到PC來返回
ALIGN 4
END
執(zhí)行效果:
- 入棧后:SP相應(yīng)遞減。
- 寫內(nèi)存后:查看
0x20000000地址,值為0x12345678。 - 校驗(yàn)后:APSR的Z標(biāo)志為1,R3被設(shè)為
0xFF。 - 全速運(yùn)行:程序在
Main和Delay_Func間循環(huán),R3始終保持0xFF。
四、總結(jié)
Cortex-M3/M4匯編的核心邏輯可提煉為三句話:
- 操作對(duì)象是寄存器:核心寄存器僅需掌握R0-R7(數(shù)據(jù))、SP/LR/PC(控制)和APSR(條件標(biāo)志)。
- 內(nèi)存訪問靠Load/Store:遵循RISC原則,僅
LDR/STR指令與內(nèi)存交互。函數(shù)上下文保護(hù)使用推薦的PUSH/POP指令。 - 程序流靠PC控制:跳轉(zhuǎn)用
B,函數(shù)調(diào)用用BL(依賴LR),返回推薦用BX LR或POP {PC}。
掌握以上內(nèi)容,即可為理解和應(yīng)對(duì)嵌入式開發(fā)中啟動(dòng)代碼/硬件初始化、中斷服務(wù)例程(ISR)編寫、性能關(guān)鍵代碼段優(yōu)化等場(chǎng)景打下堅(jiān)實(shí)基礎(chǔ)。

浙公網(wǎng)安備 33010602011771號(hào)