一般的な場合 ( x86/x64プラットフォーム) - 割り込みはいつでも実行できます。これにより、メモリ以下のスタック ポインターが上書きされます (現在のスタックで実行された場合)。これは、スタック ポインターの下に何かを一時的に保存しても、カーネル モードでは有効ではないためです。割り込みは現在のカーネル スタックを使用します。しかし、ユーザーモードの状況では、Windowsは割り込みテーブル(IDT)を構築し、割り込みが発生したときに常にカーネルモードとカーネルスタックで実行されます。その結果、ユーザー モード スタック (スタック ポインターの下) は影響を受けません。そして、関数呼び出しを行わなくなるまで、ポインタの下のスタックスペースを一時的に使用する可能性があります。例外が発生する場合(たとえば、無効なアドレスへのアクセスによる)-スペースベロースタックポインターも上書きされます-もちろん、CPU例外はカーネルモードとカーネルスタックで実行されますが、カーネルよりも経由でユーザー空間でコールバックを実行しますntdll.KiDispatchExecption
すでに現在のスタック空間にあります。一般に、これは Windows ユーザー モード (現在の実装) で有効ですが、何をしているのかをよく理解する必要があります。しかし、これはめったに使用されないと思います
もちろん、Windowsユーザーモードで、スタックポインターの下に書き込むことができるというコメントで指摘された正確さは、現在の実装の動作です。これは文書化または保証されていません。
ただし、これは非常に基本的なことです。変更される可能性はほとんどありません。割り込みは、常に特権カーネル モードでのみ実行されます。カーネル モードは、カーネル モード スタックのみを使用します。ユーザーモードコンテキストはまったく信頼されていません。ユーザーモードプログラムが間違ったスタックポインタを設定するとどうなりますか? mov rsp,1
またはで言う
mov esp,1
?この命令の直後に割り込みが発生します。そのような無効な esp/rsp で実行を開始するとどうなりますか? すべてのオペレーティング システムがクラッシュしました。この割り込みはカーネルスタックでのみ実行されるためです。ユーザースタックスペースを上書きしません。
また、スタックはスペースが限られていることに注意する必要があります (ユーザー モードでも)。1 ページ (4Kb) のエラーが発生した場合にアクセスします (ガード ページを下に移動するには、ページごとにスタック プローブを実行する必要があります)。
そして最後に、通常アクセスする必要はありません- どの問題で最初[ESP-4], EAX
にデクリメントしますか? ESP
ループでスタックスペースにアクセスする必要がある場合でも、スタックポインターを1回だけ減らす必要があります-1つの追加命令(ループ内ではない)は、パフォーマンスやコードサイズに変化はありません。
したがって、正式なものにもかかわらず、これはWindowsユーザーモードで正しく機能します。これを使用することをお勧めします(必要ではありません)
もちろん、正式な文書には次のように書かれています:
スタック使用量
RSP の現在のアドレスを超えるすべてのメモリは揮発性と見なされます
ただし、これはカーネルモードも含めて一般的なケースです。私はユーザーモードについて書き、現在の実装に基づいています
将来のウィンドウで可能になり、「直接」apcまたはいくつかの「直接」シグナルを追加します-一部のコードは、スレッドがカーネルに入った直後(通常のハードウェア割り込み中)にコールバックを介して実行されます。この後、esp 以下はすべて未定義になります。しかし、これが存在しないまで。このコードが常に(現在のビルドで)正しく機能するまで。