ZHCU947E June 2015 – January 2023
在 C 和汇编代码之间共享 C 头文件
单行:
.cdecls [options ,] " filename "[, " filename2 "[,...]]
多行:
.cdecls [options]
%{
/*---------------------------------------------------------------------------------*/
/* C/C++ code - Typically a list of #includes and a few defines */
/*---------------------------------------------------------------------------------*/
%}
.cdecls 指令允许使用混合汇编和 C/C++ 环境的编程器共享 C 头文件,此头文件包含使用 C 和 汇编代码的声明和原型。任何合法的 C/C++ 都可以在 .cdecls 块中使用,并且 C/C++ 声明会使系统自动生成合适的汇编语言,使用户可以在汇编代码中引用 C/C++ 结构,比如调用函数、分配空间、访问结构成员和使用等效的汇编机制。虽然函数和变量定义会被忽略,但常见的 C/C++ 元素被转换为汇编语言,例如:枚举、(非函数类)宏、函数和变量原型、结构体和联合体。
.cdecls 选项会控制将代码视为 C 代码还是 C++ 代码;以及如何呈现 .cdecls 块和转换后的代码。选项必须用英文逗号分隔;它们可以按任何顺序出现:
C | 将 .cdecls 块中的代码视为 C 源代码(默认)。 | |
CPP | 将 .cdecls 块中的代码视为 C++ 源代码。这和 C 选项相反。 | |
NOLIST | 不要在为包含汇编文件生成的任何列表文件中包含转换后的汇编代码(默认)。 | |
LIST | 在为包含汇编文件生成的任何列表文件中包含转换后的汇编代码。这和 NOLIST 选项相反。 | |
NOWARN | 不要在 STDERR 上发出有关在解析 .cdecls 源块时无法转换 C/C++ 构造的警告(默认)。 | |
WARN | 在 STDERR 上发出有关在解析 .cdecls 源块时无法转换 C/C++ 构造的警告(默认)。这和 NOWARN 选项相反。 |
在单行格式中,选项后跟一个或多个要包含的文件名。文件名和选项用英文逗号分隔。列出的每个文件犹如 #include "filename" 是以多行格式指定。
在多行格式中,.cdecls 后面的行必须包含开始的 .cdecls 块指示符 %{。%{ 之后的所有内容,直到结束块指示符 %},都被视为 C/C++ 源代码并进行处理。普通汇编器进行处理,然后在结束 %} 后面的行上恢复。
%{ 和 %} 中的文本被传递给 C/C++ 编译器以转换为汇编语言。许多 C 语言语法(包括函数和变量定义以及类函数宏)不受支持,在转换过程中会被忽略。但是,传统上出现在 C 头文件中的所有内容都受支持,包括函数和变量原型、结构体和联合体声明、非类函数宏、枚举和 #defines。
生成的汇编语言包含在汇编文件中的 .cdecls 指令处。如果使用 LIST 选项,则转换后的汇编语句将列印在列表文件中。
由 .cdecls 指令生成的汇编语言的处理方式与 .include 文件类似。因此, .cdecls 指令可以嵌套在被复制或包含的文件中。汇编器将嵌套限制为十级;主机操作系统可能会设置额外的限制。汇编器在复制文件的行号之前加上一个字母代码来标识复制级别。A 表示第一个复制的文件,B 表示第二个复制的文件,以此类推。
.cdecls 指令可以出现在汇编源文件中的任何位置,并且可以在一个文件中多次出现。但是,一个 .cdecls 创建的 C/C++ 环境不会被后面的 .cdecls 继承;每个 .cdecls 的 C/C++ 环境在开始时都是全新的。
有关在 C 头文件中设置和使用 .cdecls 指令的更多信息,请参阅GUID-413E9C31-DDE9-4735-87A6-20C56CBC9D51.html#GUID-413E9C31-DDE9-4735-87A6-20C56CBC9D51。
在此示例中,使用 .cdecls 指令调用 C header.h 文件。
C 头文件:
#define WANT_ID 10
#define NAME "John\n"
extern int a_variable;
extern float cvt_integer(int src);
struct myCstruct { int member_a; float member_b; };
enum status_enum { OK = 1, FAILED = 256, RUNNING = 0 };
源文件:
.cdecls C,LIST,"myheader.h"
size: .int $sizeof(myCstruct)
aoffset: .int myCstruct.member_a
boffset: .int myCstruct.member_b
okvalue: .int status_enum.OK
failval: .int status_enum.FAILED
.if $defined(WANT_ID)
id .cstring NAME
.endif
列表文件:
1 .cdecls C,LIST,"myheader.h"
A 1 ; ------------------------------------------
A 2 ; Assembly Generated from C/C++ Source Code
A 3 ; ------------------------------------------
A 4
A 5 ; =========== MACRO DEFINITIONS ===========
A 6 .define "10",WANT_ID
A 7 .define """John\n""",NAME
A 8
A 9 ; =========== TYPE DEFINITIONS ===========
A 10 status_enum .enum
A 11 00000001 OK .emember 1
A 12 00000100 FAILED .emember 256
A 13 00000000 RUNNING .emember 0
A 14 .endenum
A 15
A 16 myCstruct .struct 0,4
17 ; struct size=(8 bytes|64 bits), alignment=4
A 18 00000000 member_a .field 32
19 ; int member_a - offset 0 bytes, size (4 bytes|32 bits)
A 20 00000004 member_b .field 32
21 ; float member_b - offset 4 bytes, size (4 bytes|32 bits)
A 22 00000008 .endstruct
23 ; final size=(8 bytes|64 bits)
A 24
A 25 ; =========== EXTERNAL FUNCTIONS ===========
A 26 .global _cvt_integer
A 27
A 28 ; =========== EXTERNAL VARIABLES ===========
A 29 .global _a_variable
2 00000000 00000008 size: .int $sizeof(myCstruct)
3 00000004 00000000 aoffset: .int myCstruct.member_a
4 00000008 00000004 boffset: .int myCstruct.member_b
5 0000000c 00000001 okvalue: .int status_enum.OK
6 00000010 00000100 failval: .int status_enum.FAILED
7 .if $defined(WANT_ID)
8 00000014 0000004A id .cstring NAME
00000015 0000006F
00000016 00000068
00000017 0000006E
00000018 0000000A
00000019 00000000
9 .endif