インライン アセンブリを使用して C のベース ポインター レジスタ (%rbp) にアクセスする場合関数にアクセスした後、予期しないセグメント障害が発生します。 argument.
問題は、GCC が追跡する必要がある値を格納する RSP (または減算ポインター) の下の「レッド ゾーン」を踏むことにあります。提供されているコード例では、インライン アセンブリ内でプッシュ命令が使用されており、%rsp を 8 だけデクリメントし、関数の引数 (&x) の下位 32 ビットを上書きします。
インライン アセンブリが完了すると、GCC破壊された値を 4 バイト ストアのアドレスとして使用しようとします。これにより、セグメントが生成されます。
この問題には主に 3 つの解決策があります。
レッド ゾーン オーバーランを使用する代わりに、「=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 サイトの他の関連記事を参照してください。