一、汇编代码强制书写规范
- 所有标号(EQU 宏、向量表、函数入口、循环标记)必须顶格书写;
- 指令、伪指令(AREA/IMPORT/EXPORT/STMFD/LDMFD 等)统一缩进,禁止顶格;
- 工程命名规范:汇编自定义函数名前加双下划线
__,区分系统内置符号; - Cortex-M 满减栈标准:使用
STMFD SP!,{寄存器组,LR}入栈保护,LDMFD SP!,{寄存器组,PC}恢复现场并返回,替代简化版 PUSH/POP。
二、完整标准启动文件 startup.s(规范命名__SUM、__MUL)
; 所有的指令不能顶格写
; 所有的标号必须顶格写
; *********************1. 栈空间定义:可读可写、无初始化数据段***************************
Stack_size EQU 0x200 ; 宏定义堆栈大小,等价C语言#define Stack_size 0x200
AREA STACK, NOINIT,READWRITE, ALIGN=3
; AREA 定义STACK段
; NOINIT:上电不初始化栈内存
; READWRITE:栈内存可读可写
; ALIGN=3:8字节对齐,适配AAPCS规范与浮点运算
SPACE Stack_size ; 开辟Stack_size字节堆栈空间
__init_msp ; 主堆栈栈顶地址标号
;**********************2. 全局编译配置************************************************************
IMPORT main ; 导入C语言main函数
PRESERVE8 ; 堆栈8字节对齐
THUMB ; 使用THUMB指令集
;************************3. 复位中断向量表段*************************
AREA RESET,DATA, READONLY
__Vectors
DCD __init_msp ; 0号向量:主堆栈地址
DCD __start ; 1号向量:复位入口地址
SPACE 0x400 ; 预留其他中断向量空间
;***********************4. 程序代码段*******************************************************
AREA |.text|,CODE, READONLY
__start PROC
BL main ; 复位跳转C语言main函数
BL .
;==================== 规范1:加法函数__SUM(双下划线命名,供C调用)====================
__SUM ; 函数标号顶格,前缀双下划线
STMFD SP!,{R4-R12,LR} ; 满减栈标准现场保护
ADD R0,R0,R1 ; R0=a、R1=b,和存入R0作为返回值
LDMFD SP!,{R4-R12,PC} ; 恢复现场,PC赋值完成函数返回
ENDP
END
三、汇编调用 C 语言函数(核心知识点)
核心规则
IMPORT 函数名:任意定义在 C 文件的函数,汇编调用前必须导入,不局限 main 函数;- AAPCS 传参:前 4 个参数依次存入 R0~R3,超过 4 个参数压栈;
BL 函数名:跳转调用,自动保存返回地址至 LR。
示例代码
IMPORT main
IMPORT PrintNum
__start PROC
MOV R0,#20
BL PrintNum
BL main
ENDP
总结
汇编内部自定义函数统一加__,无需 IMPORT;所有 C 语言函数,汇编调用必须写IMPORT。
四、C 语言调用汇编函数标准流程
1. 汇编端要求
在全局配置区域书写 EXPORT __函数名,统一导出所有汇编函数符号;
IMPORT main ; 导入C语言main函数
EXPORT __SUM ;导出汇编函数__SUM
2. C 语言端 extern 声明
#include <stdio.h>
// 声明双下划线命名的汇编函数
extern int __SUM(int a,int b);
extern int __MUL(int a,int b);
int main(void)
{
int add_val = __SUM(4,6);
int mul_val = __MUL(4,6);
printf("4+6=%d,4*6=%d\r\n",add_val,mul_val);
return 0;
}
五、关键规范与指令对照表
| 条目 | 标准要求 |
|---|---|
| 汇编自定义函数命名 | 名称前加双下划线 __XXX,区分系统符号 |
| 现场保护 / 恢复 | 满减栈标准:STMFD SP!,{} / LDMFD SP!,{...,PC} |
| 标号格式 | 函数、循环、常量标号全部顶格 |
| 指令格式 | 所有运算 / 伪指令必须缩进 |
| 汇编调 C | 任意 C 函数均需 IMPORT 函数名 + BL 调用 |
| C 调汇编 | 汇编 EXPORT 导出__XXX,C 用 extern 声明 |