为什么我的C++程序的汇编输出中充满了没有汇编代码的.ascii字符?

4
我正在使用CMake将一个C++文件编译成静态库,并通过修改由CMake生成的Makefile,向gcc命令添加-S -fverbose-asm标志以获取汇编输出。然而,生成的.cpp.s文件中充满了.ascii行,其中包含十六进制数据,而且没有汇编指令,如以下内容:
.ascii  "\346+\274\004@\226\032!n\247<)\212\264\205\377*\204\275\364e"
.ascii  "\314\026\270vi\263\373\327\n\367$\332\035\364N\212\316\254\324"

有人知道这是什么原因导致的吗?我该如何获得易读的汇编指令呢?
gcc版本:5.4.0

3
请展示C++源代码,并提供g++版本。另外,请在godbolt.org上检查是否能够重现代码。 - Jester
看起来是比 ASCII 更复杂的字符集的字符代码。 - Thomas Matthews
2
请确保您没有使用LTO。这似乎会产生您所描述的输出。 - Jester
1
@Jester:这是有道理的,GCC可能使用.ascii作为一种相对紧凑的方式来发出汇编器不知道的原始二进制格式(GIMPLE)。另一种选择是.byte 12, 34,...,这是2到4个源字节每输出字节,类似于带有八进制的ASCII。或者.long.quad会更接近2个源字节每输出字节。 - Peter Cordes
1
链接时优化,通常使用-flto启用。您的.s文件中应该会看到很多lto字符串。 - Jester
显示剩余3条评论
1个回答

4
你可能启用了链接期优化(gcc -flto)进行编译,这将生成“fat”对象文件,除了常规的汇编语言之外还包含GCC程序逻辑的中间表示。因此,在链接时可以进行整个程序的优化,允许跨源文件进行内联和进一步优化,这在仅可见原型时是不可能的。或者,如果你使用一个不支持LTO的链接器进行链接,它将忽略LTO部分并只使用常规的机器码部分。 https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html GCC使用具有八进制转义符的.ascii作为一种比较紧凑(在汇编源文件中)的方式来发出程序不知道的原始二进制(GIMPLE字节码)。
另一种选择是.byte 12,34,...,它需要2到4个源字节才能输出一个字节,类似于ASCII与八进制,后者提供1到4个字节(对于可打印ASCII范围内的任何字节为1)。
.long 0xabcd220c, 0x...或.quad会更接近每输出字节的2字节汇编源代码。
这种效率考虑仅适用于GCC将馈送给as的.s临时文件;在.o中,数据将以二进制形式存在(在一个具有特殊名称的目标文件部分中)。 GCC希望使用快速序列化为GCC格式的格式,并且对于汇编器来解析并转换回字节也很快。推测双引号字符串对于.ascii来说使得解析简单。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接