静下心来专门复习一下RTOS,拿mqx-lite下手,重新看一遍代码,记录点滴,以备总结。
(1)常用的预编译指令如#define和#include在汇编文件中也是可以使用的。
预编译指令是由预编译器实现的,#define执行是在编译器的符号表中建立新的符号(并赋值,对应于汇编语言的预编译指令EQU),而#include也仅仅是把包含文件的内容进行替换。虽然预编译器本身经常被集成到编译器中,但实际上它跟与语言相关的编译器的联系并没有我们想象的那么紧密。
在IAR汇编中可以使用的C风格预编译指令有:
#define,#elif,#else,#endif,#error,#if,#ifdef,#ifndef,#include,#line,#message,#pragma,#undef
它们的使用方式与在C语言中完全相同。
#pragma会被汇编的预编译器忽略。
#error在汇编的预编译器处理过程中将引发一个错误。
(2)兼容C语言的注释
在汇编源代码中使用传统的“;”注释也是可以的,但在IAR的汇编源文件中也支持C语言的“/* ... */”注释及“//”注释。需要注意的是,严格上说"//"是属于C++的注释风格,并不能归为纯C,并且在目前的MISRA-C标准中也是不推荐的。
事实上,在IAR中C风格的预编译器在汇编的预编译之前会先对汇编源文件进行一次预编译处理,因此在《IAR Assembler Reference Guide》(后简称为EWA_RM)描述的一种C风格和汇编语言的预编译指令不能混合嵌套,若是C风格的预编译指令因嵌套在汇编的预编译指令而躲过了C语言的预编译处理,那么在汇编的预编译处理过程中,它们的存在将被视为错误!同样,若是在C风格预编译器的工作范畴中,例如在#define命令中使用了汇编风格的注释";",这也将被C预编译器
虽然IAR ARM的汇编语言兼容了C语言的宏定义(#define),然而IAR汇编本身也有自己的宏定义方式。
在新版本的MQX-Lite中,并没有根据MQX的传统使用IAR汇编的宏(EWA_RM-P82),而是用#define和CFI。对于#define前面已经说过,现在关注一下CFI。
CFI是Call Frame Information的缩写,在EWA_RM(P105)中用这样的描述:
“当使用C-SPY调试应用程序时,用户可以看到调用调用栈的内容,即调用当前函数的其它函数链。为了在编译C源文件时实现这种特性,编译器提供了调试信息用以描述调用框架(Call Frame)的分布,尤其是存放返回地址的信息。”
“当希望在调试汇编语言写的函数时看到调用栈信息时,可以通过在汇编语言中使用CFI指令修饰函数,以实现等价的功能.”
也就是说,CFI命令完全是为了方便调试使用的。考虑到程序的兼容性,在分析代码的过程中直接忽略到CFI,在实际应用时,也跳过对汇编部分的调试。
这里贴上MQX-Lite中使用汇编定义的宏(asm_mac.h):
#define ASM_PREFIX(x) x
#define ASM_EXTERN(label) EXTERN label
#define ASM_PUBLIC(label) PUBLIC label
#define ASM_LABEL(label) label
#define ASM_EQUATE(label, value) label EQU value
#define ASM_SET(label, value) ASM_LABEL(label) SET value
#define ASM_ALIGN(value) ALIGNROM value/4
#define ASM_CONST16(value) DC16 value
#define ASM_CONST32(value) DC32 value
#define ASM_LABEL_CONST32(label, value) ASM_LABEL(label) DC32 value
#define ASM_CODE_SECTION(name) SECTION name : CODE (4)
#define ASM_CODE_SECTION_NOOPT(name) SECTION name : CODE (4) : ROOT
#define ASM_DATA_SECTION(name) SECTION name : DATA (4)
#define ASM_END END
#define ASM_COMP_SPECIFIC_DIRECTIVES
#define指令的右值是IAR汇编中可用的关键字和命令。最后一句宏定义说明还要用到更为特殊的指令,看来MQX-Lite的定位对可移植性考虑不多啊。
关于CFI的定义有:
/* CFI annotations for public symbols called from C code */
CFI Names CFINames0
CFI StackFrame CFA R13 DATA
CFI Resource R0:32, R1:32, R2:32, R3:32, R4:32, R5:32, R6:32, R7:32
CFI Resource R8:32, R9:32, R10:32, R11:32, R12:32, R13:32, R14:32
CFI EndNames CFINames0
CFI Common CFICommon0 Using CFINames0
CFI CodeAlign 2
CFI DataAlign 4
CFI ReturnAddress R14 CODE
CFI CFA R13+0
CFI R0 SameValue
CFI R1 SameValue
CFI R2 SameValue
CFI R3 SameValue
CFI R4 SameValue
CFI R5 SameValue
CFI R6 SameValue
CFI R7 SameValue
CFI R8 SameValue
CFI R9 SameValue
CFI R10 SameValue
CFI R11 SameValue
CFI R12 SameValue
CFI R14 SameValue
CFI EndCommon CFICommon0
/* Note that these macros should NOT be on the beggining of line when used
in assembler code. Prepend allways by at least one space.
(was not an issue in EWARM 6.40.x, space seems to be needed in 6.50.x) */
#define ASM_PUBLIC_BEGIN(name) CFI Block CFIBlock_##name Using CFICommon0
#define ASM_PUBLIC_FUNC(name) CFI Function name
#define ASM_PUBLIC_END(name) CFI EndBlock CFIBlock_##name
这部分代码先放在这里,虽然是要被忽略的,但要备忘。