汇编与 C 语言 互调用

一、汇编代码强制书写规范

  1. 所有标号(EQU 宏、向量表、函数入口、循环标记)必须顶格书写;
  2. 指令、伪指令(AREA/IMPORT/EXPORT/STMFD/LDMFD 等)统一缩进,禁止顶格;
  3. 工程命名规范:汇编自定义函数名前加双下划线 __,区分系统内置符号;
  4. 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 语言函数(核心知识点)

核心规则

  1. IMPORT 函数名:任意定义在 C 文件的函数,汇编调用前必须导入,不局限 main 函数;
  2. AAPCS 传参:前 4 个参数依次存入 R0~R3,超过 4 个参数压栈;
  3. 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 声明
相关推荐
水饺编程6 天前
第2章:Linux 基础,解压缩【.tar.bz2】压缩包文件
linux·c语言·汇编
Zevalin爱灰灰6 天前
Linux入门第二部分(ARM裸机篇) 第二章 Cortex-A7 MPCore架构与ARM汇编基础
linux·汇编·arm开发·嵌入式
Zevalin爱灰灰6 天前
Linux入门第二部分(ARM裸机篇) 第三章 汇编LED驱动实验
linux·汇编·arm开发
水饺编程7 天前
第2章:Linux 基础,制作【.tar.xz】压缩包文件
linux·c语言·汇编
小向是个Der9 天前
嵌入式进阶——编译与链接
汇编·单片机·学习·编译原理·交叉编译
二十七日秋9 天前
算法刷题笔记「Day 1|四道 OJ 入门题里的深坑」
c语言·汇编·数据结构·c++·笔记·python·算法
银河麒麟操作系统9 天前
两案例入选全球计算联盟年度产业应用案例汇编
大数据·汇编·人工智能
abc light9 天前
ARM 裸机开发(2)——ARM 汇编与启动代码
汇编·arm开发
soso196810 天前
Modbus协议开发实战指南
汇编
水饺编程11 天前
第2章:Linux 基础,解压缩【.tar.gz】压缩包
linux·c语言·汇编