2011-07-31 14 views
10

ユーザーモード(特権レベル3)でいくつかのコードを実行する小さなOSを作成しています。そのユーザーレベルのコードから、メッセージを出力するOSに割り込みを戻したいと思う。今私は本当に私の割り込みハンドラがそのような引数を取るかどうか気にしない、私は実際には割り込みハンドラがコードが実行されたことを私(ユーザー)に通知したい。iretを使用してユーザーモードに切り替える

私の質問は、ユーザーモードでコードを実行するにはどうすればいいですか?私は、ローカルディスクリプタテーブルをコードセグメントとデータセグメント(両方ともユーザーモード権限を持つ)で設定する関数を持っています。私が理解できないことは、これらのセグメントをcs,ss、およびdsにロードする方法です。私は正常に私のLDTを読み込みますが、実際にどのように使用するのか分かりません。私はiretを使うべきだと聞いたことがありますが、どういうふうには分かりません。

私が持っているもう1つの質問は、割り込みハンドラがどのように動作するかです。ベクタ番号0x40の割り込みハンドラをインストールして、 "hello、user mode!"を出力したいとしましょう。私は割り込みハンドラを設定する方法を知っていますが、ユーザモードからカーネル割り込みハンドラに入るときにコンテキストがどのように切り替わるかを正確に理解していません。 csレジスタは変更する必要があります。私のルーチンはIDTエントリで指定されたコードセグメントから実行されるためです。私はまた、スタックセレクタもおそらく変化することを理解していますが、私はこれを確信することはできません。

誰かが割り込みゲートが呼び出されたときにどのようなコンテキスト変更が行われたのか教えてください。

答えて

20

iretを使用してリング3を取得するには、操作方法が文書化されているためです。もし割り込みを受信すると、プロセッサは、プッシュ:

  1. スタックセグメントポインタ(SS:ESP)、4つのワード
  2. EFLAGS
  3. リターンコードセグメント、命令ポインタ(CS:EIP)として、 4ワードとして
  4. 必要に応じてエラーコード。

iretは、手順1〜3を元に戻すことで機能します(必要に応じて手順4を元に戻すのはISRの責任です)。この事実を利用して、必要な情報をスタックにプッシュしてiret命令を発行することで、リング3に到達することができます。コードとスタックセグメントに適切なCPLがあることを確認します(下位2ビットはそれぞれに設定する必要があります)。ただし、iretはデータセグメントを変更しないため、手動で変更する必要があります。これを行うにはmov命令を使用しますが、これとスイッチングリングの間でスタック外のデータを読み取ることはできません。

cli 
mov ax, Ring3_DS 
mov ds, eax 
push dword Ring3_SS 
push dword Ring3_ESP 
pushfd 
or dword [esp], 0x200 // Set IF in EFLAGS so that interrupts will be reenabled in user mode 
push dword Ring3_CS 
push dword Ring3_EIP 
iret 

完全な動作例については、this tutorialを参照してください。


割り込みが発行されると、プロセッサはIDTを読み取り、ISRの適切なコードセグメントと命令ポインタを取得します。次に、新しいスタックセグメントとポインタを見つけるためにTSSを調べます。 ssespが適切に変更され、古い値が新しいスタックにプッシュされます。 ではなく、はデータセグメントレジスタのいずれかを変更します。 ISRのメモリにアクセスする必要がある場合は、手動で行う必要があります。

+1

申し訳ありません、あなたは私の質問に答えました。私が今理解していることは、私がカーネルスタックを含んでいるTSSを持っている必要があるということです。助けてくれてありがとう。 –

+0

私はこれをupvoteにちょうどログインしました!ありがとう!そこにいる他の人たちのために、私はosdevとIntel ISAマニュアルもお勧めします。彼らは本当に物事をクリアします。 – Sid

+0

IRETはデータセグメントを変更しないとはどういう意味ですか?汎用レジスタ内の値について話していますか? –

1

retfを行うこともできます。遠い特権のコードセグメントに戻ると、新しいssとspが特権スタックからポップされます。

遠くのコールや割り込みのために遠いリターンがあることを確認してください。それらの間の唯一の違いは、スタック上にフラグが存在することですが、それらを混在させるのは賢明ではありません。

また、例外がスタック上のエラーコードをプッシュすることがあることを忘れないでください。

関連する問題