ARM汇编调用C函数头文件报错的问题咨询
问题描述
在ARM汇编文件CelsiusFahrenheit.s中调用Q15.s实现的汇编函数时,编译test_CelsiusFahrenheit出现错误:汇编器将C头文件Q15.h中的语法识别为无效指令,报错信息如下:
./includes/Q15.h: Assembler messages: ./includes/Q15.h:19: Error: bad instruction `typedef int Q15' ./includes/Q15.h:46: Error: bad instruction `extern Q15 add_Q15(Q15 num1,Q15 num2,unsigned char*overflow)' ./includes/Q15.h:56: Error: bad instruction `extern Q15 sub_Q15(Q15 num1,Q15 num2,unsigned char*overflow)' ./includes/Q15.h:66: Error: bad instruction `extern Q15 mul_Q15(Q15 num1,Q15 num2,unsigned char*overflow)' ./includes/Q15.h:76: Error: bad instruction `extern Q15 div_Q15(Q15 num1,Q15 num2,unsigned char*overflow)' make: *** [build/CelsiusFahrenheit.o] Error 1
错误根源
汇编器(arm-none-eabi-as)仅能解析ARM汇编语法,无法识别C语言的头文件结构(如typedef、C风格函数声明)。直接在汇编文件中用.include "Q15.h"会让汇编器把C代码当作汇编指令处理,必然触发语法错误。
解决步骤
1. 移除汇编文件中对C头文件的包含
修改CelsiusFahrenheit.s,删除.include "Q15.h"行,仅保留汇编兼容的宏定义文件Q15.i:
.include "Q15.i" ; 移除 .include "Q15.h" .text .align 2 .arm .global Celsius2Fahrenheit Celsius2Fahrenheit: push {r1-r3, lr} ldr r1, =58982 @; 9/5 * 2^15 = 58982 bl mul_Q15 @; r0 = r0 * r1 ldr r1, =1048576 @; 32 * 2^15 = 1048576 bl add_Q15 @; 修正函数名:原代码误写为sum_Q15 pop {r1-r3, pc} .global Fahrenheit2Celsius Fahrenheit2Celsius: push {r1-r3, lr} ldr r1, =1048576 @; 32 * 2^15 = 1048576 bl sub_Q15 @; r0 = r0 - r1 ldr r1, =18204 @; 5/9 * 2^15 = 18204 bl mul_Q15 @; r0 = r0 * 5/9 pop {r1-r3, pc}
注:代码中存在拼写错误,
sum_Q15需修正为实际函数名add_Q15,否则链接阶段会找不到符号。
2. 遵循ARM调用规范传递参数
ARM ATPCS调用规范中,前3个参数依次放入r0、r1、r2寄存器,返回值存入r0。当前代码调用mul_Q15、add_Q15时未传递第三个参数(unsigned char* overflow),会导致运行时错误,需补充参数处理:
Celsius2Fahrenheit: push {r1-r3, lr} sub sp, sp, #4 @; 栈上分配4字节存储overflow状态 mov r2, sp @; r2指向overflow变量 ldr r1, =58982 bl mul_Q15 ldr r1, =1048576 bl add_Q15 add sp, sp, #4 @; 释放栈空间 pop {r1-r3, pc}
3. 调整Makefile依赖(可选但规范)
由于汇编文件不再依赖Q15.h,修改build/CelsiusFahrenheit.o的依赖规则:
build/CelsiusFahrenheit.o: sources/CelsiusFahrenheit.s includes/Q15.i arm-none-eabi-as $(ASFLAGS) -c sources/CelsiusFahrenheit.s -o build/CelsiusFahrenheit.o
核心总结
汇编文件不能直接包含C头文件,正确做法是:
- 仅引入汇编兼容的宏定义文件(如
.i格式) - 直接调用已用
.global声明的汇编函数,无需C风格声明 - 严格遵循ARM调用规范传递参数、处理返回值和栈帧
内容的提问来源于stack exchange,提问作者Jan Torres Rodríguez
相关产品推荐
相关产品推荐

