为什么这里需要C宏中的“##”以及预处理MIPS汇编中的分号是什么意思?

Why is "##" in C macro needed here and what does semicolon in preprocessed MIPS assembly means?

我最近正在阅读基于 MIPSfpga 的嵌入式系统上的 MIPS 程序集 OS 运行。

我有两个文件,boot.Sboot.h。我使用命令 mips-sde-elf-gcc -c -o boot.o boot.S 对其进行编译,以便它通过 C 预处理器 cpp.

在文件boot.h中,它定义了一个宏:

#define LEAF(name)\
    .##text;\
    .##globl    name;\
    .##ent  name;\
name:

##是什么意思?我在 info cpp 上找到它导航到 Macros 然后导航到 Concatenation,这叫做 "token pasting or token concatenation"。但是为什么我们需要在这种情况下连接令牌呢?你看,boot.S 将经过 cpp,然后是 as。但是 as 也有一个内置的标记解析器,所以我认为这里不需要粘贴标记,因为 as 会将它解析为单个符号,而不是两个单独的符号,来自cpp 的输出。 cpp 不用费心粘贴了。

然后,我用命令gcc -E boot.S > boot.i看看预处理后得到了什么。在 boot.S 中,宏 LEAF(__reset_vector) 扩展为以下内容:

.text; .globl __reset_vector; .ent __reset_vector;__reset_vector:

预处理指令在同一行。但是 ; 是什么意思呢? info as.

中没有记录

What does ## mean?

从前后一个标记中创建一个标记,将它们粘贴在一起。这里的目的可能是为了防止预处理器在 . 和后面的标识符之间插入一个额外的 space,因为 . 没有被 CPP 与标识符一起解析。

But what does ; mean?

在大多数架构的 GAS 语法中,它是一个语句分隔符。汇编语句通常由换行符分隔,但 cpp 的宏不能轻易地产生 multi-line 输出,因此需要另一个分隔符。

在其他一些汇编语法中(如 NASM 或 MASM),; 是注释字符。

(根据您的添加进行了更新。)

我仔细看了info as。事实证明,由 GNU as 定义的 "comments and statements" 是特定于目标的。不同的汇编语言可能有不同的注释和语句语法,以及行分隔符。所以我需要更深入地研究 MIPS 语法。

据我所知,## CPP 运算符 不是 必需的,并且没有任何效果,除非 textglobl , 或 ent #defined 作为宏。

#define LEAF(name)\
    .##text;\
    .##globl    name;\
    .##ent  name;\
name:

LEAF(myname)

CPP 输出:.text; .globl myname; .ent myname;myname:

#define LEAF2(name)\
    .text;\
    .globl    name;\
    .ent  name;\
name:

LEAF2(myname)

CPP 输出:.text; .globl myname; .ent myname;myname:

无论有无 ## token-pasting,输出都相同。


;在这个asm语法中是一个语句分隔符(像一个换行符),所以这个宏切换到.text部分,并声明一个以宏arg为名称的全局符号.里面还有一个.ent name指令,不知道是干什么用的