我最近正在阅读基于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
也有一个内置的令牌解析器,所以我认为这里不需要这种令牌粘贴,因为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
中没有记录。
答案 0 :(得分:2)
##
是什么意思?
从上一个和下一个中创建一个令牌,将它们粘贴在一起。这里的目的可能是为了防止预处理器在.
和以下标识符之间插入额外的空格,因为CPP不会使用标识符解析.
。
但
;
是什么意思?
在大多数体系结构的GAS语法中,它是一个语句分隔符。汇编语句通常由换行符分隔,但cpp
的宏不能轻易生成多行输出,因此需要另一个分隔符。
在其他一些汇编语法中(如NASM或MASM),;
是注释字符。
(根据您的补充更新。)
答案 1 :(得分:1)
我仔细阅读了info as
。事实证明,GNU as
定义的“评论和陈述”是针对具体目标的。不同的汇编语言可能具有不同的注释和语句语法,以及行分隔符。所以我需要深入研究MIPS语法。
答案 2 :(得分:1)
据我所知,除非##
,text
或{{1},否则globl
CPP运算符不且无效} {是ent
d为宏。
#define
CPP输出:#define LEAF(name)\
.##text;\
.##globl name;\
.##ent name;\
name:
LEAF(myname)
.text; .globl myname; .ent myname;myname:
CPP输出:#define LEAF2(name)\
.text;\
.globl name;\
.ent name;\
name:
LEAF2(myname)
输出与.text; .globl myname; .ent myname;myname:
令牌粘贴相同或不相同。
##
是此asm语法中的语句分隔符(如换行符),因此此宏切换到;
部分,并声明一个以宏arg作为名称的全局符号。那里还有一个.text
指令,我不知道它的作用。