数か月間、私は「自作」のオペレーティング システムに取り組んできました。現在、起動して 32 ビット保護モードに入ります。割り込みテーブルをロードしましたが、ページネーションを設定していません (まだ)。
例外ルーチンを作成しているときに、命令が例外をスローすると、例外ルーチンが実行されますが、CPU は例外をスローした命令にジャンプして戻ることに気付きました。これはすべての例外に適用されるわけではありません (たとえば、div by zero 例外は、除算命令の後に命令に戻ります)、次の一般的な保護例外を考えてみましょう。
MOV EAX, 0x8
MOV CS, EAX
私のルーチンは単純です。赤いエラー メッセージを表示する関数を呼び出します。
結果: MOV CS、EAX が失敗します -> エラー メッセージが表示されます -> CPU が MOV CS に戻ります -> エラー メッセージをスパムする無限ループ。
この問題について、オペレーティング システムと UNIX セキュリティの教師と話しました。彼は、Linux にはそれを回避する方法があることは知っているが、どの方法があるかはわからないと私に言いました。
単純な解決策は、その命令の長さを取得するために、ルーチン内からスロー命令を解析することです。その解決策はかなり複雑で、影響を受けるすべての例外ルーチンで比較的重い関数への呼び出しを追加するのは少し不快に感じます...
したがって、問題を回避する別の方法があるかどうか疑問に思っていました。この動作を変更できるビットを含む「魔法の」レジスタがあるのではないでしょうか?
--
提案/情報をお寄せいただきありがとうございます。
--
編集:なぜ問題のある命令をスキップして通常の実行を再開したいのか疑問に思う人が多いようです。
これには 2 つの理由があります。
まず第一に、プロセスを強制終了することは可能な解決策ですが、クリーンな解決策ではありません。これは、Linux で行われる方法ではありません。たとえば、(AFAIK) カーネルがシグナル (SIGSEGV だと思います) を送信しますが、すぐに実行を中断しません。アプリケーションはシグナルをブロックまたは無視して、独自の実行を再開できるため、これは理にかなっています。これは、何か間違った IMO を実行したことをアプリケーションに伝える非常にエレガントな方法です。
別の理由: カーネル自体が不正な操作を実行した場合はどうなるでしょうか? バグが原因である可能性がありますが、カーネル拡張が原因である可能性もあります。コメントで述べたように、その場合はどうすればよいですか? カーネルを強制終了して、スマイリー付きの素敵なブルー スクリーンを表示しますか?
だからこそ、命令を飛び越えられるようになりたい。命令のサイズを「推測」することは明らかにオプションではなく、命令の解析はかなり複雑に思えます (そのようなルーチンの実装を気にしているわけではありませんが、より良い方法がないことを確認する必要があります)。