在last question的基础上构建我试图弄清楚.local
和.comm
指令的确切运作方式,特别是它们如何影响C中的关联和持续时间。
所以我进行了以下实验:
static int value;
生成以下汇编代码(使用gcc):
.local value
.comm value,4,4
初始化为零时,会产生相同的汇编代码(使用gcc):
.local value
.comm value,4,4
这听起来合乎逻辑,因为在这两种情况下我都希望变量存储在bss段中。此外,在使用ld --verbose
进行调查后,看起来所有.comm
变量确实都放在了bss段中:
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
// ...
}
当我将变量初始化为非零值时,编译器会按照我的预期在数据段中定义变量,但会产生以下输出:
.data
.align 4
.type value, @object
.size value, 4
value:
.long 1
除了不同的段(分别为bss和数据),感谢您之前我现在理解的帮助,我的变量在第一个示例中被定义为.local
和.comm
,但在第二个示例中没有被定义为{{1}}。任何人都可以解释每个案例产生的两个产出之间的区别吗?
答案 0 :(得分:2)
.local
指令将符号标记为本地非外部可见符号,如果它尚不存在则创建它。 0初始化的局部符号是必要的,因为.comm
声明但不定义符号。对于1初始化变体,符号本身(value:
)声明符号。
使用.local
和.comm
基本上是一种黑客攻击(或者至少是一种速记);另一种方法是将符号明确地放入.bss
:
.bss
.align 4
.type value, @object
.size value, 4
value:
.zero 4
答案 1 :(得分:1)
由于安全原因,Linux内核在分配后将进程的虚拟内存归零。因此,编译器已经知道内存将用零填充并进行优化:如果某个变量初始化为0,则无需在可执行文件中保留空间(.data
部分实际占用一些空间在ELF可执行文件中,.bss
部分仅存储其长度,假设其初始内容为零。