ホームページ >バックエンド開発 >C++ >C インライン アセンブリでベース ポインター (%rbp) を使用するとセグメンテーション違反が発生するのはなぜですか?

C インライン アセンブリでベース ポインター (%rbp) を使用するとセグメンテーション違反が発生するのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-01 07:57:14709ブラウズ

Why Does Using the Base Pointer (%rbp) in C   Inline Assembly Cause Segfaults?

問題: C インライン アセンブリでのベース ポインター レジスタ (%rbp) の使用

インライン アセンブリを使用して C のベース ポインター レジスタ (%rbp) にアクセスする場合関数にアクセスした後、予期しないセグメント障害が発生します。 argument.

説明

問題は、GCC が追跡する必要がある値を格納する RSP (または減算ポインター) の下の「レッド ゾーン」を踏むことにあります。提供されているコード例では、インライン アセンブリ内でプッシュ命令が使用されており、%rsp を 8 だけデクリメントし、関数の引数 (&x) の下位 32 ビットを上書きします。

インライン アセンブリが完了すると、GCC破壊された値を 4 バイト ストアのアドレスとして使用しようとします。これにより、セグメントが生成されます。

解決策

この問題には主に 3 つの解決策があります。

  1. ワークスペースと出力に「メモリ」出力オペランド (スクラッチ配列など) を使用します。そこから読み取らないでください。
  2. add $-128, %rsp / sub を使用してレッド ゾーンをスキップします。 $-128、アセンブリ コードの周囲の %rsp。
  3. -mno-red-zone でコンパイルします (ただし、これは関数ごとのオプションではないことに注意してください)。

代替アプローチ

レッド ゾーン オーバーランを使用する代わりに、「=m」制約を使用してインライン アセンブリ内にワークスペースを明示的に割り当てることを検討してください。次の修正されたコード例:

void Bar(int &x)
{
    int tmp;
    long tmplong;
    asm ("lea  -16 + %[mem1], %%rbp\n\t"
         "imul , %%rbp, %q[reg1]\n\t"  // q modifier: 64bit name.
         "add  %k[reg1], %k[reg1]\n\t"    // k modifier: 32bit name
         "movl , %[mem1]\n\t" // some asm instruction writing to mem
           : [mem1] "=m" (tmp), [reg1] "=r" (tmplong)
           :
           : "%rbp"
         );
    x = 5;
}

ここでは、「=m」制約により、ワークスペースがレッド ゾーン内に割り当てられ、関数の引数の上書きが回避されます。

以上がC インライン アセンブリでベース ポインター (%rbp) を使用するとセグメンテーション違反が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。