アセンブリの OUTB 機能はどのようにして三重障害を引き起こすのでしょうか?
-
23-08-2019 - |
質問
私のシステム プログラミング クラスでは、小さくてシンプルな趣味の OS に取り組んでいます。私は個人的に ATA ハードディスク ドライバーの開発に取り組んでいます。たった 1 行のコードが障害を引き起こし、システムがすぐに再起動されるようであることを発見しました。問題のコードは、IDE 割り込みの割り込みサービス ルーチンの最後にあります。私は IDE チャネルを使用していたので、それらはスレーブ PIC (マスターを介してカスケード接続されている) を介して送信されます。当初、私のコードは割り込み終了バイトをスレーブに送信するだけでしたが、教授はそれをマスター PIC にも送信する必要があると言いました。
ここに私の問題があります。EOIバイトをマスターPICに送信する行のコメントを解除すると、システムがトリプルフォールトして再起動します。同様に、コメントを付けたままにしておくと、システムは実行されたままになります。
_outb( PIC_MASTER_CMD_PORT, PIC_EOI ); // this causes (or at least sets off) a triple fault reboot
_outb( PIC_SLAVE_CMD_PORT, PIC_EOI );
システムの残りの部分を見ずに、ここで何が起こっているのかを説明できる人はいるでしょうか?
注記:暗中模索として、_outb() 呼び出しを別の _outb() 呼び出しに置き換えて、IDE コントローラーの割り込みが確実に有効になるようにしましたが、生成されるアセンブリはほぼ同じになります。これは故障の原因ではありませんでした。
*_outb() は、x86 OUTB 命令のラッパーです。
EOI をマスター PIC に送信する私の機能の何がそんなに特別で、問題になっているのでしょうか?
コードを見ないと回答できないかもしれませんが、ご覧いただきありがとうございます。
解決
トリプル障害は、通常、スタックオーバーフローまたは奇数スタックポインタを指します。障害や割り込みが発生すると、システムはすぐに(障害ハンドラを呼び出す前に)スタックにいくつかのより多くの迷惑をプッシュしようとします。スタックがまずいされている場合は、これは、別の障害が発生し、スタック上でより多くのものをプッシュしようとする他の障害を引き起こします。この時点で、システムはあなたを断念し、リブートします。
(約20年前に、デルで仕事をしながら)私は実際に(キーボードコントローラを介して行われるために使用される)外部ハードウェアなしでCPUリセットを発生させる方法で愚かな特許を持っているので、私はこれを知ってます:
MOV ESP,1
PUSH EAX ; triple fault and reset!
OUTB命令は、独自の障害を引き起こすことができません。私の推測では、あなたが割り込みを再有効化され、そして何かがあなたのスタックと間違っている間に割り込みがトリガされます。
他のヒント
PIC を再度有効にするとき、CPU の割り込みフラグをセットした状態で行っていますか、それともクリアした状態で行っていますか (つまり、の後でやってるの? CLI
オペコード、または、 STI
オペコード)?
CPU の割り込みフラグが有効になっていると仮定すると、PIC を再度有効にする行為により、保留中の割り込みが CPU に到達できるようになります。これはコードを中断したり、IDT によって指定されたベクトルにディスパッチしたりすることになります。
したがって、エラーを直接引き起こしているのはオペコードではないことが予想されます。むしろ、問題があるのは、PIC を再度有効にした結果として発生する割り込みの結果として実行されるコードです。