只要遵循 Topic Link Label7.4 中定义的调用惯例,以及 Topic Link Label7.3 中定义的寄存器惯例,即可同时使用 C/C++ 与汇编语言函数。C/C++ 代码可访问变量并调用使用汇编语言定义的函数,汇编代码也可访问 C/C++ 变量并调用 C/C++ 函数。
结合使用汇编语言和 C 时,请遵循以下指南:
- 您必须保留由某函数修改的所有专用寄存器。专用寄存器包括:
- 入口保存寄存器 (R4-R10)
- 栈指针(SP 或 R1)
如果通常使用 SP,则无需显式保留。换而言之,汇编函数可自由使用栈,只要在函数返回前将压入栈的全部内容弹出即可(因此要保留 SP)。
非专用寄存器可自由使用,无需首先保存。
- 中断例程必须保存所使用的所有寄存器。如需更多信息,请参阅 Topic Link Label7.7。
- 如果通过汇编语言调用 C/C++ 函数,请加载指定的寄存器与参数,并将其余参数压入栈,如 Topic Link Label7.4.1 中所述。
请记住,函数可改变未保留的任何寄存器,而且不必恢复该寄存器。如果这些寄存器中有任何内容需要在不同调用间保留,则必须显式保存它们。
- 函数必须根据其 C/C++ 声明正确地返回值。双精度值会返回 R12 和 R13,结构也会返回,如 Topic Link Label7.4.1 的第 2 步所述。任何其他值都会返回 R12。
- 任何汇编模块均不应出于任何目的使用 .cinit 段,除非进行全局变量的自动初始化。C/C++ 启动例程假设 .cinit 段包含完整的 初始化表。将其他信息放入 .cinit 会将表打乱,导致无法预测的结果。
- 编译器会为所有外部对象指定链接名称。因此您在编写汇编语言代码时,使用的链接名称必须与编译器指定的相同。相关详细信息,请参阅Topic Link Label6.14。
- 在汇编语言中声明、并从 C/C++ 访问或调用的任何对象或函数,必须在汇编语言修饰符中使用 .def 或 .global 指令进行声明。这样可将符号声明为外部引用,并允许链接器解析对它的引用。
同理,若要从汇编语言中访问 C/C++ 函数或对象,应在汇编语言模块中使用 .ref 或 .global 指令来声明 C/C++ 对象。这样可创建未声明的外部引用,并由链接器解析。
- 任何与 MSP430x C 程序搭界的汇编例程都应符合大型代码模型:
- 使用 CALLA/RETA 而不使用 CALL/RET
- 使用 PUSHM.A/POPM.A 保存并恢复任何未使用的入口保存寄存器。必须保存/恢复整个 20 位寄存器。
- 操作函数指针需要 20 位运算 (OP.A)
- 如果与 C 代码(针对大型数据模型编译)搭界,则数据指针操作必须使用 20 位运算 (OP.A) 执行。