2

在我的最后一个问题的基础上,我试图弄清楚指令如何准确地工作,特别是它们如何影响 C 中的链接和持续时间.local.comm

所以我进行了以下实验:

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在第二个示例中没有。谁能解释每个案例产生的两个输出之间的差异?

4

2 回答 2

2

.local指令将符号标记为本地的、外部不可见的符号,如果它不存在则创建它。对于 0 初始化的局部符号,它是必需的,因为.comm声明但不定义符号。对于 1 初始化的变体,符号本身 ( value:) 声明了该符号。

使用.localand.comm本质上是一种技巧(或至少是一种速记);另一种方法是将符号.bss显式放入:

        .bss
        .align 4
        .type   value, @object
        .size   value, 4
value:
        .zero   4
于 2012-11-27T12:23:42.113 回答
1

由于安全原因,Linux 内核在分配后将进程的虚拟内存归零。因此,编译器已经知道内存将用零填充并进行优化:如果某个变量初始化为 0,则无需在可执行文件中为其保留空间(.data在 ELF 可执行文件中,section 实际上占用了一些空间,而.bss部分仅存储其长度,假设其初始内容为零)。

于 2012-11-27T11:25:16.250 回答