为什么这里需要C宏中的“##”以及预处理MIPS汇编中的分号是什么意思?
Why is "##" in C macro needed here and what does semicolon in preprocessed MIPS assembly means?
我最近正在阅读基于 MIPSfpga 的嵌入式系统上的 MIPS 程序集 OS 运行。
我有两个文件,boot.S
和 boot.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 运算符 不是 必需的,并且没有任何效果,除非 text
、globl
, 或 ent
#define
d 作为宏。
#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
指令,不知道是干什么用的
我最近正在阅读基于 MIPSfpga 的嵌入式系统上的 MIPS 程序集 OS 运行。
我有两个文件,boot.S
和 boot.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 运算符 不是 必需的,并且没有任何效果,除非 text
、globl
, 或 ent
#define
d 作为宏。
#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
指令,不知道是干什么用的