レッドゾーンの目的は何ですか?


12

レッドゾーンは、「割り当てられていない」スタックポインターを超えるメモリ内の固定サイズの領域です。コンパイラは、単純なリーフ関数でその領域にアクセスするためのアセンブリを生成します。

しかし、私はレッドゾーンの本当の利点を見ることはできません。スタックポインタを超えてメモリにアクセスするのは非常に危険であり、データの破損を簡単に引き起こす可能性があります。なぜこれを行うのですか?2つのプロセッサ命令(push ebp、mov ebp esp)を保存しても、実際の速度は上がりません。

回答:


16

レッドゾーンは、純粋かつ単純に、命令を保存できる最適化です。これは、すべての関数の発行コードがスタックポインターから減算してローカルストレージを作成する必要がなくなったことを意味します。

sub XXX, %rsp 

リーフ関数ではない場合でも、すべての関数呼び出しの開始時に。多くの場合、コンパイラから出力されたコードは、スタックポインターの下にあるレッドゾーンの一時スペースを、保存する必要なく他の関数を呼び出す前に使用できます。これは、利用可能な便利な最適化です。

スタックポインターからサブする必要がなくなった場合、発行されたコードはrspをベースポインターとして使用でき、ジョブは通常rbpに予約され、発行されたコードはrbpを別の汎用レジスターとして使用できます。

これは最終的に、各関数呼び出しのプロローグとエピローグが、rbpを保存および復元する2つの命令を保存できることを意味します。

(GNUアセンブラー)

pushq %rbp       # prologue [ two instructions not necessary ]
movq %rsp,%rbp

.... [code]

movq %rbp,%rsp   # epilogue [ two instructions not necessary ]
popq %rbp        

gccでは、不要な場合は-mno-red-zoneフラグを渡すことができます(ただし、x86-64 ABIでは必要です)。LinuxカーネルはABIに準拠する必要はないため、すべてのカーネルコードは-mno-red-zoneでコンパイルされます。

さらに、スタックポインタを超えてメモリにアクセスすることは、それが予期される動作モードであれば危険ではありません。それは危険であるだけで、計画外で予期しないときに破損を引き起こす可能性があります。発行されたコードがそれを行うとき、それは何をしているかを知っています。


はい、私はこれを理解しています。しかし、1つの命令(espからのサブ)を保存することは本当に最適化ですか?私は、データを破損する可能性の本当の代償として数バイトと1プロセッササイクルを節約することを意味します。それを行う理由は他にもあるのでしょうか?
アレクサンダー・ジョジョ14

3
最適化されているのは実際にはespのsubではありません、esp から sub する必要がなくなったので、espをベースポインターとして(通常はebpによって行われます)、ebpを関数コードの他の何かに使用できます。最後に、espがベースポインターになったため、コードはプロローグ/エピローグのebpの保存と復元を回避できます。この追加情報で答えを明確にします
ブライアンオン14

レッドゾーンはx86-64 ABIの一部であるため、編集してebp / espではなくrbp / rspに変更しました(32ビットレジスタで同じ手法を使用することを妨げるものはありませんが、今日のようにコンパイラーはそれを行いません)
ブライアンオン14

1
フレームポインターの省略は、レッドゾーンとはまったく関係ありません。コンパイラーは、%rspどちらの方法でもベースポインターとして使用してスタックのインデックスを作成できます。
アレコフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.