Linux GCC编译代码:为什么整数声明需要几个语句?
我正在学习AT&T汇编,我知道数组/变量可以用.int/.long来声明,也可以用.eq来声明一个符号,用汇编来代替 它们在.data节(初始化)或.bss节(未初始化)中声明 但是,当我使用gcc编译一个非常简单的.c文件并使用“-S”命令行选项检查反汇编代码时,我注意到: (1) .s不同时使用.data和.bss,而仅使用.data (2) 整数(.long)的声明需要几个语句,其中一些语句对我来说似乎是多余或无用的 如下图所示,我根据我的问题添加了一些评论 $cat n.cLinux GCC编译代码:为什么整数声明需要几个语句?,linux,gcc,assembly,compilation,disassembly,Linux,Gcc,Assembly,Compilation,Disassembly,我正在学习AT&T汇编,我知道数组/变量可以用.int/.long来声明,也可以用.eq来声明一个符号,用汇编来代替 它们在.data节(初始化)或.bss节(未初始化)中声明 但是,当我使用gcc编译一个非常简单的.c文件并使用“-S”命令行选项检查反汇编代码时,我注意到: (1) .s不同时使用.data和.bss,而仅使用.data (2) 整数(.long)的声明需要几个语句,其中一些语句对我来说似乎是多余或无用的 如下图所示,我根据我的问题添加了一些评论 $cat n.c int i=
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
此外,“j”没有符号标记,也没有放在.bss节中
我做错什么了吗?请帮忙改正。非常感谢。(我猜您正在使用一些Linux系统)
它们在.data节(初始化)或.bss节(未初始化)中声明
不,您还有许多其他部分,特别是.comm
(对于“common”部分,初始化数据与多个对象文件共用,链接器将“合并”)和.rodata
用于只读数据。该格式足够灵活,允许在内存中加载多个节和多个段(其中一些未加载,更精确地说是内存映射)
文件中节的描述比您所相信的要复杂得多。花点时间多读一些,例如莱文的。请同时阅读和的文档和&。使用和浏览现有ELF可执行文件、对象文件和共享对象。同时阅读,
但是当我使用gcc
编译一个非常简单的.c
文件时,使用了-S
命令行选项
在检查由gcc
生成的汇编程序文件时,我强烈建议至少传递-fverbose asm
,要求gcc
在汇编程序文件中发出一些额外的有用注释。我通常还建议使用一些优化标志,例如至少使用-O1
(或者在最近版本的gcc
上使用-Og
)
我注意到:
(1) .s不同时使用.data和.bss,而仅使用.data
否,生成的代码使用.comm
部分,并将j
的值放在那里
(2) 整数(.long)的声明需要几个语句,其中一些语句对我来说似乎是多余或无用的
这些大部分不是汇编语句(翻译成机器代码),而是汇编指令;它们非常有用(它们不会浪费ld
产生的内存段中的空间,但ELF格式在其他地方有信息)。特别是.size
和.type
都是必需的,因为ELF文件中的符号表包含的地址不止一个(它还有大小的概念,以及非常原始的类型概念)
.LFB0
是一个gcc
(实际上是cc1
-)生成的标签。GCC不关心生成无用的标签(对于GCC后端中的汇编器生成器来说更简单),因为它们不会出现在对象文件中
有个“.long23”,我们知道是4个字节
您可能知道long是4字节,但该信息(大小为j
)应该进入ELF文件,因此需要显式的汇编程序指令
(我没有空间或时间来解释ELF格式,你需要阅读很多关于它的页面,它比你所相信的要复杂得多,也更完整)
顺便说一句,Drepper's相当长(超过40页),并解释了大量关于ELF文件的内容,重点是共享库。(我猜您正在使用一些Linux系统)
它们在.data节(初始化)或.bss节(未初始化)中声明
不,您还有许多其他部分,特别是.comm
(对于“common”部分,初始化数据与多个对象文件共用,链接器将“合并”)和.rodata
用于只读数据。该格式足够灵活,允许在内存中加载多个节和多个段(其中一些未加载,更精确地说是内存映射)
文件中节的描述比您所相信的要复杂得多。花点时间多读一些,例如莱文的。请同时阅读和的文档和&。使用和浏览现有ELF可执行文件、对象文件和共享对象。同时阅读,
但是当我使用gcc
编译一个非常简单的.c
文件时,使用了-S
命令行选项
在检查由gcc
生成的汇编程序文件时,我强烈建议至少传递-fverbose asm
,要求gcc
在汇编程序文件中发出一些额外的有用注释。我通常还建议使用一些优化标志,例如至少使用-O1
(或者在最近版本的gcc
上使用-Og
)
我注意到:
(1) .s不同时使用.data和.bss,而仅使用.data
否,生成的代码使用.comm
部分,并将j
的值放在那里
(2) 整数(.long)的声明需要几个语句,其中一些语句对我来说似乎是多余或无用的
这些大部分不是汇编语句(翻译成机器代码),而是汇编指令;它们非常有用(它们不会浪费ld
产生的内存段中的空间,但ELF格式在其他地方有信息)。特别是.size
和.type
都是必需的,因为ELF文件中的符号表包含的地址不止一个(它还具有大小的概念,并且非常简单)