Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么是##&引用;在这里需要C宏,预处理MIPS程序集中的分号是什么意思?_Assembly_Mips_Preprocessor - Fatal编程技术网

Assembly 为什么是##&引用;在这里需要C宏,预处理MIPS程序集中的分号是什么意思?

Assembly 为什么是##&引用;在这里需要C宏,预处理MIPS程序集中的分号是什么意思?,assembly,mips,preprocessor,Assembly,Mips,Preprocessor,我最近正在阅读基于MIPSfpga的嵌入式系统上运行的小操作系统的MIPS汇编 我有两个文件,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导航到Macr

我最近正在阅读基于MIPSfpga的嵌入式系统上运行的小操作系统的MIPS汇编

我有两个文件,
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
,这称为“令牌粘贴或令牌连接”。但在这种情况下,我们为什么需要连接令牌呢?你看,
boot.S
将通过
cpp
,然后作为
。但是
as
也有一个内置的令牌解析器,所以我认为这里不需要粘贴令牌,因为
as
将从
cpp
的输出中将其解析为单个符号,而不是两个单独的符号
cpp
无需费心粘贴它

然后,我使用命令
gcc-eboot.S>boot.I
查看预处理后得到的结果。在
boot.S
中,宏
叶(\uu重置\u向量)
展开为以下内容:

.text; .globl __reset_vector; .ent __reset_vector;__reset_vector:
预处理的指令位于同一行。但是什么是
平均值?它没有作为
记录在
信息中

##
是什么意思

从上一个和下一个标记中创建一个标记,并将它们粘贴在一起。此处的目的可能是防止预处理器在
和以下标识符之间插入额外的空间,因为CPP不会使用标识符解析

但是什么是
平均值

在大多数架构的GAS语法中,它是一个语句分隔符。汇编语句通常用换行符分隔,但是
cpp
的宏无法轻松生成多行输出,因此需要另一个分隔符

在其他一些程序集语法(如NASM或MASM)中,
是注释字符


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

我仔细阅读了
信息作为
。事实证明,
GNU定义为
的“注释和语句”是特定于目标的。不同的汇编语言可能有不同的注释和语句语法,以及行分隔符。因此,我需要深入研究MIPS语法。

据我所知,
CPP操作符不是必需的,也没有任何效果,除非
text
globl
ent
都是
,将
d定义为宏

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

LEAF(myname)
CPP输出:
.text。globl myname。我的名字;myname:

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

LEAF2(myname)
CPP输出:
.text。globl myname。我的名字;myname:

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

LEAF2(myname)
输出与
##
标记粘贴相同或不相同。



是此asm语法中的语句分隔符(如换行符),因此此宏将切换到
.text
部分,并以宏arg作为名称声明一个全局符号。那里还有一个
.ent name
指令,我不知道它是做什么的。

可能是@LưuVĩnhPhúc的重复,谢谢。我读了那篇文章,它没有被复制。我在想为什么这里需要
##
,而不是
##
的语法含义。至于“###”,我想这只是一个双重保险箱。嗯。。。不确定。我可以想到一个挑剔的预处理器,它将
从其输出中的以下标识符中分离出来,这将破坏构造。另一方面,
.text
作为
##
操作符的结果也不是严格符合的(C标准要求它是一个C令牌,但事实并非如此),因此它也不能完全安全地避免额外挑剔的预处理器。@Han
##
是令牌粘贴操作符。它将前后出现的内容连接成一个标记。这里不起作用,例如
。text
在C编程语言中不是有效的标记。@AntoineL@fuz是的,我还假设
cpp
会检查符号是否是有效的C样式标识符。然而,我做了一个小测试,
#define foo.var=1;printf(“%d\n”,.var)
,当我使用命令
gcc-efoo.c>foo.I
对其进行预处理(展开宏
foo
)时,
cpp
没有抱怨
.var
是无效标识符。但是当我编译它时,
gcc
编译器对此抱怨并启动了一个错误。@fuz@AntoineL此外,根据
info-cpp
然后导航到
Tokenization
,它说“编译器不会重新标记预处理器的输出。每个预处理标记都成为一个编译器标记。”。这就是我们编译
.c
文件时发生的情况<代码>gcc
是前端。但是当我们使用gcc编译
.S
文件时,gcc使用
as
来编译它。但是没有记录
as
是否将重新标记。Ok。我想我在这里太迂腐了。也许在这里查看
##
可以防止意外的令牌解析结果,这样做是合理的,并且可以避免深入了解
cpp
实现细节。如果使用
.globl
而不使用
#
,cpp将不会插入
。这很奇怪,也没有必要,除非你在这之前定义了entfoobar。