5. 汇编文件输出
本章介绍如何使用 clang汇编源代码。
5.1 汇编示例
KF32工具链兼容GNU语法的汇编伪指令。关于更多的伪指令,可参考GNU Binutils文档。
以下示例展示了汇编代码,用于计算两个变量的和。
.text
.file "add.c"
.globl add
.p2align 3
.type add,@function
add:
ADD r0, r1, r0
JMP lr
使用kf32clang来汇编语言源代码。通常,调用kf32clang的步骤如下:
kf32clang --target=kf32r -o file.o file.s
5.2 汇编流程
默认情况下,clang 使用汇编代码源文件后缀来决定是否运行 C 预处理器:
.s(小写)后缀表示不需要预处理的汇编代码。.S(大写)后缀表示需要预处理的汇编代码。-x 选项允许显式指定后续输入文件的编程语言来覆盖默认配置,而不是通过文件后缀进行推断。具体来说,-x assembler-with-cpp表示汇编代码包含 C 预处理器指令,clang 必须运行 C 预处理器。-x 选项只适用于命令行中在该选项之后的输入文件,一旦使用了 -x 选项,它就会为其后的所有输入文件设置编程语言,直到遇到下一个 -x 选项或文件列表结束。
注意:不要将 .ifdef 汇编器指令与预处理器 #ifdef 指令混淆:
- 预处理器
#ifdef指令检查是否存在预处理器宏。这些宏通过#define预处理器指令或 clang命令行选项-D定义。 - clang 汇编
.ifdef指令检查代码符号。这些符号通过标签或.set指令定义。
汇编.S文件时,预处理器先运行,对源代码进行文本替换,对 #ifdef 指令的处理阶段。之后源代码会传递给汇编器,对 .ifdef 指令进行处理。
汇编源文件中的注释应使用 // 或 /* */。# 是立即数的前缀(如 MOV r0, #16),不能用作注释:写在语句之后会报 Unexpected Immediate;写在行首时,.S 文件由预处理器先行处理,若该行恰好以 #error、#define、#include、#if 等指令名开头,预处理器会把它当作真正的预处理指令执行,而 .s 文件不经过预处理,整行只被汇编器当作注释忽略。因此 .s 与 .S 对以 # 开头的行处理结果不同,编写注释请勿依赖这一差别。
要预处理汇编代码源文件,请执行以下其中之一:
-
确保汇编代码文件名为 .S后缀,然后使用:
kf32clang --target=kf32r -march=kf32r test.S -c -o test.o -
使用
-x assembler-with-cpp选项来告诉 clang 汇编源文件需要预处理。当你已有带有小写后缀的源文件时,这个选项非常有用。例如:kf32clang --target=kf32r -march=kf32r -x assembler-with-cpp test.s -c -o test.o