当我查看GCC生成的汇编代码时,有许多行以.LBB
开头和一个数字。似乎它们不是操作指令。更像是标记文件的内容或什么。
什么是.LFB
,。LVL
,LBB
,LBE
等在编译器生成的汇编代码中?
.loc是否意味着“代码行”。这些行只是表示symbol table
?
这是一段代码,
main:
.LFB1:
.loc 1 8 0
.cfi_startproc
.LVL2:
.LBB4:
.LBB5:
.loc 1 2 0
movsd b(%rip), %xmm0
.LBE5:
.LBE4:
.loc 1 10 0
xorl %eax, %eax
.LBB7:
.LBB6:
.loc 1 2 0
mulsd a(%rip), %xmm0
.LBE6:
.LBE7:
.loc 1 9 0
movsd %xmm0, a(%rip)
.LVL3:
.loc 1 10 0
ret
.cfi_endproc
答案 0 :(得分:10)
<强>的.loc 强>
正如Ferruccio所提到的.loc
是一个调试指令,如果你告诉编译器使用-ggdb
生成调试信息,它只出现在GCC 4.8.2中。
.loc
,确切的输出取决于调试数据格式(DWARF2等)。
另一个是标签。
.L前缀
GCC使用.L
作为本地标签。
默认情况下,GAS不会在编译输出上生成任何符号,如https://sourceware.org/binutils/docs-2.18/as/Symbol-Names.html
所述本地符号是以某些本地标签前缀开头的任何符号。默认情况下,ELF系统的本地标签前缀为“.L”
在汇编程序中定义和使用本地符号,但它们通常不保存在目标文件中。因此,调试时它们不可见。您可以使用`-L'选项(请参阅包含本地符号:-L)来保留目标文件中的本地符号。
因此,如果您使用:as -c a.S
进行编译,则nm a.o
根本不会显示这些标签。
这才有意义,因为您无法从C程序生成此类标签。
还有一些选项可以管理它:
man as
--keep-locals
man ld
--discard-all
这似乎是GCC工具链的特定惯例,不属于ELF ABI或NASM。
此外,NASM和GAS都使用以句点开头的标签(但在GAS中不是.L
)生成局部符号的约定:http://www.nasm.us/doc/nasmdoc3.html#section-3.9但仍然存在于输出中。
<强>后缀强>
您提到的后缀似乎都与调试相关,因为它们都是在GCC 4.8.2上的gcc/dwarf2out.c下定义的,而DWARF2是ELF的主要调试信息格式:
#define FUNC_BEGIN_LABEL "LFB"
#define FUNC_END_LABEL "LFE"
#define BLOCK_BEGIN_LABEL "LBB"
#define BLOCK_END_LABEL "LBE"
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
根据我的实验,其中一些仅使用gcc -g
生成,有些甚至没有生成g
。
一旦我们有了这些定义名称,很容易生成生成它们的C代码,看看它们的含义:
LFB
和LFE
在函数的开头和结尾生成
LBB
和LBE
由以下代码生成,内部功能块范围为gcc -g
:
#include <stdio.h>
int main() {
int i = 0;
{
int i = 1;
printf("%d\n", i);
}
return 0;
}
LVL
:TODO我无法轻易理解它。我们需要更多地解释这个来源。
答案 1 :(得分:1)
.loc
指令用于指示相应的源代码行。
它表示相应源代码的文件号,行号和列号。
其余的看起来像标签。