[当我查看由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
。loc
正如Ferruccio .loc
所提到的,它是一个调试指令,只有当您告诉编译器使用-ggdb
生成调试信息时,它才会出现在GCC 4.8.2中。
.loc
记录在https://sourceware.org/binutils/docs-2.18/as/LNS-directives.html#LNS-directives,确切的输出取决于调试数据格式(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我无法轻松理解它。我们需要对源代码进行更多解释。
.loc
伪指令用于指示源代码的相应行。它指示相应源代码的文件号,行号和列号。