GCC编译代码:为什么整数声明需要几个语句?

时间:2016-09-22 05:15:38

标签: linux gcc assembly compilation disassembly

我正在学习AT&amp; T程序集,我知道可以使用.int / .long声明数组/变量,或使用.equ声明符号,这些符号将由程序集替换。< / p>

他们被宣布为.data部分(已初始化)或.bss部分(未初始化)。

但是当我使用gcc编译一个非常简单的.c文件时,&#39; -S&#39;命令行选项检查反汇编代码,我注意到: (1).s不同时使用.data和.bss,而只使用.data (2)整数(.long)的声明需要花费几个语句,其中一些语句对我来说似乎是多余的或无用的。

如下所示,我根据我的问题添加了一些评论。

$ cat n.c

int i=23; 
int j; 
int main(){ 
   return 0; 
} 

$ gcc -S n.c $ cat n.s

     .file    "n.c" 
     .globl    i 
     .data 
     .align 4 
     .type    i, @object #declare i, I think it's useless
     .size    i, 4 #There's '.long 23', we know it's 4 bytes, why need this line?
i: 
     .long    23       #Only this line is needed, I think
     .comm    j,4,4    #Why j is not put inside .bss .section?
     .text 
     .globl    main 
     .type    main, @function 
main:
.LFB0:                 #What does this symbol mean, I don't find it useful.
     .cfi_startproc 
     pushq    %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq    %rsp, %rbp 
     .cfi_def_cfa_register 6 
     movl    $0, %eax 
     popq    %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0:                 #What does this symbol mean, I don't find it useful.
     .size    main, .-main 
     .ident    "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609" 
     .section    .note.GNU-stack,"",@progbits 

我的所有问题都在上面的评论中,我再次在此再次强调:

     .type    i, @object 
     .size    i, 4
i: 
     .long    23

我真的认为上面的代码是多余的,应该简单如下:

i: 
     .long    23

此外,&#34; j&#34;没有符号标记,也没有放在.bss部分。

我有什么问题吗?请帮忙纠正。非常感谢。

1 个答案:

答案 0 :(得分:4)

(我猜你正在使用一些Linux系统)

  

它们被声明为.data部分(初始化)或.bss部分(未初始化)。

不,你有很多其他部分,特别是.comm(对于“常见”部分,初始化数据 common 到几个目标文件,链接器将“合并”)和.rodata表示只读数据。 ELF格式足够灵活,允许许多部分和许多段(其中一些段未加载 - 更准确地说是内存映射到内存中)。

ELF文件中的部分说明比您认为的要复杂得多。花点时间阅读更多内容,例如莱文Linkers and loaders。另请阅读文档以及scriptsGNU binutils以及ld(1)&amp; as(1)。使用objdump(1)readelf(1)来探索现有的ELF可执行文件,目标文件和共享对象。另请阅读execve(2)&amp; elf(5)

  

但是当我使用gcc编译一个带有.c命令行选项的非常简单的-S文件时

在检查由gcc生成的汇编程序文件时,我强烈建议至少传递-fverbose-asm,要求gcc在汇编程序文件中发出一些其他有用的注释。我通常也建议使用一些优化标志-e.g.至少-O1 {或者-Og gcc的近期版本。

  

我注意到:   (1).s不同时使用.data和.bss,而只使用.data

不,您生成的代码使用.comm部分,并将j的值放在那里。

  

(2)整数(.long)的声明需要花费几个语句,其中一些语句对我来说似乎是多余的或无用的。

这些主要不是汇编程序语句(翻译成机器代码),而是汇编程序指令;它们非常有用(并且它们不会在ld生成的内存段中浪费空间,但ELF格式在其他地方有信息)。特别需要.size.type,因为ELF文件中的符号表包含多个地址(它还有一个大小的概念,以及一个非常原始的类型概念)。

.LFB0gcc(实际为cc1 - )生成的标签。 GCC不关心生成无用的标签(对于GCC后端的汇编器生成器来说更简单),因为它们不会出现在目标文件中。

  

有'。long 23',我们知道它是4个字节,

您可能知道long是4个字节,但该信息(j的大小)应该进入ELF文件,因此需要显式的汇编指令....

(我没有空间或时间来解释ELF格式,你需要阅读很多关于它的页面,它比你想象的更复杂,更完整) < / p> BTW,Drepper的How To Write Shared Libraries很长(超过40页)并且解释了很多关于ELF文件的内容,重点关注共享库。