2

コーディングの競争に参加するときにスタックオーバーフローを回避するために、次のコードを使用することがあります。

int main()
{
  static const int _STACK_SIZE = MAXN*10;
  static int _STACK[_STACK_SIZE*2], _ESP;
  __asm__ __volatile__
  (
      "movl %%esp, %0\n" 
      "movl %1, %%esp\n":
      "=g"(_ESP):
      "g"(_STACK + _STACK_SIZE):
  );


  // Do Something..


  __asm__ __volatile__
  (  
      "movl %0, %%esp\n":
      :
      "g"(_ESP):
  );
}

私の知る限り、このasmコード%espはスタックをバックアップしてに移動します_STACK[]


私の質問:なぜこのコードがSIGSEGVx86-64 Linuxサーバーで発生するのですか(私自身のx86 Linuxでうまく動作します)?そしてそれを修正する方法は?

たぶん%esp、64ビットポインタだからだろうか?

を削除しようとしました__asm__ __volatile__("movl %0, %%esp\n": : "g"(_ESP):);が、うまくいくようですか?

4

1 に答える 1

4

これは、x86-64アセンブリで、espゼロなどの32ビットレジスタを変更すると、対応する64ビットレジスタの上位32ビット(rspこの場合)がゼロになるためです。x86-64では、スタックポインタrspは64ビットレジスタです。

x86-64 Linuxは、0x7fffffffe6d0たとえば、スタックポインタを常に仮想アドレス空間のユーザー空間範囲の最上部近くに配置するため、仮想アドレス空間の下位32ビットの外側に常に配置されます。RSPの上位半分はゼロ以外であり、ESP!=RSPです。

したがって、変更するespことによりrsp、プログラムにアクセス権がないアドレスを指すようになり、セグメンテーション違反が発生します。x86-64コードでは、通常はまったく使用espしないため、x86-64コード内ののすべてのインスタンスをに置き換える必要がありespますrsp

于 2013-03-27T10:56:30.943 に答える