2

の最後の質問.localに基づいて、.commディレクティブがどのように正確に機能するか、特にそれらがCのリンケージと期間にどのように影響するかを理解しようとしています。

だから私は次の実験を実行しました:

static int value;

これにより、次のアセンブリコードが生成されます(gccを使用)。

.local  value
.comm   value,4,4

ゼロに初期化すると、同じアセンブリコードが生成されます(gccを使用)。

.local  value
.comm   value,4,4

どちらの場合も、変数がbssセグメントに格納されることを期待しているため、これは論理的に聞こえます。さらに、を使用して調査した後、すべての変数が実際にbssセグメントに配置されているld --verboseように見えます。.comm

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   // ...
  }

ただし、変数をゼロ以外の値に初期化すると、コンパイラーはデータセグメント内の変数を予想どおりに定義しますが、次の出力を生成します。

        .data
        .align 4
        .type   value, @object
        .size   value, 4
value:
        .long   1

以前に理解したさまざまなセグメント(それぞれbssとdata)に加えて、私の変数は最初の例では定義されていますが.local.comm2番目の例では定義されていません。それぞれのケースから生成された2つの出力の違いを誰かが説明できますか?

4

2 に答える 2

2

ディレクティブは、シンボルをローカルの.local外部からは見えないシンボルとしてマークし、まだ存在しない場合は作成します。.commシンボルを宣言しますが定義しないため、0で初期化されたローカルシンボルに必要です。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実行可能ファイルにスペースを取りますが、.bssセクションは、最初の内容がゼロであると想定して、その長さのみを格納します)。

于 2012-11-27T11:25:16.250 に答える