ぐだぐだ低レベルプログラミング(243)x86(16bit)、割り込み/トラップゲート

Joseph Halfmoon

前回、リハビリかねてコールゲートを復習した筈が、突発事態にまたもや断絶。なんとか再々起動で今回は割り込みやら例外やらに入りたいと思います。プロテクト・モードの仕組みの復習ばかりしていて、プログラムを動かしていないのでフラストレーションたまってます。今度こそひと段落で来週こそはアセンブラに向き合いたいです。

※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら

※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。

    •  Windows 11 PC (i5-1235U)
    •  Ubuntu 24.04 LTS on WSL2
    •  QEMU 8.2.2
    •  FreeDOS 1.3
割り込みと例外

さて今回復習しておかないとならないのは、割り込み(interrupt)と例外(exception)です。割り込みは外部端子からプログラムの実行タイミングと関わりなく到来する信号で、実行中のプログラムを「適切なタイミング」で中断して、別なプログラム「割り込みハンドラ」を呼び出すことを要求します。いわゆる「ソフトウエア割り込み命令」という「割り込み」の一種に聞こえる命令が存在しますが「生態学的には」例外の中のトラップに分類されるのではないかと思います。

一方、例外というのは命令の実行が引き金となって発生する異常事態です。割り込みがプログラムの実行タイミングにお構いなしに襲来するのに比べると、プログラムの内部で引き起こされるのでその発生タイミングは「決まって」いるハズ。「決まって」いてもなんやかんや条件がいろいろあって、これまた何種類かに分類されます。

例外のクラス

さて、例外は以下の3つのクラスに分類されます。

    1. フォールト
    2. トラップ
    3. アボート

第1のフォールトは、例外を引き起こした命令の中で検出され、該当命令をポイントする形で報告される形式の例外です。例外発生前の状態に復元された状態で例外ハンドラが呼び出されます。そのため例外の原因を究明した上でなんらかの措置を行えば、該当命令を「再開」することが可能です。例えば、仮想記憶を実現するためのセグメント不在フォールトね。

一方第2のトラップは、原因となった命令そのものは実行完了した後になって報告されます。後の祭り? 該当の命令をなかったことにはできません。そしてトラップのハンドラからの戻り番地は該当命令の次の命令となります。先ほど述べたように、ソフトウエア割り込みなどはこれに該当します。

最後のアボートはヤバイやつです。どうしてよいか分からないっと。代表例はダブルフォールトですかね。既にフォールトの処理を行っている最中に重ねてフォールトが検出されてしまったような場合デス。万歳してOSの初期化からか?それでもダメなときはシャットダウンという最後の歯止めが残ってますわい。

IDT(インタラプト・デスクリプタ・テーブル)

さて、割り込みと例外は全部で256種類あり、0から255までのベクタ番号が割り振られてます。栄えある冒頭の0番は、ゼロ割り算の例外っす。外部から到来する割り込み信号INTRに対しては割り込みコントローラ(昔は8259Aがその代表選手)が番号を指定してきます。なお、NMI(ノン・マスカブル・インタラプト)は偉いので、割り込みコントローラなどの補助は不要、2番のベクタを占有してます。

0番から31番までは「インテル予約」ということになっており、各種例外のために使われることになってます。32番(16進で0x20)以降はユーザーが使える番号となっていますが、例えばマイクロソフト社のOSを使うならば32番付近からの下の方はOSが使っておしまいです。その辺はソフトの力関係? 後からプログラムを書く「ユーザー」様は「空いているところ」をよく調べた上で使わないとなりません。

さてこの256個のベクタに対してデスクリプタを並べているのがIDTです。過去回で出てきたGDTやLDTと似たテーブルですが、サイズは小さいです。そしてここには「システム・デスクリプタ」のうち限られたものだけを並べておくことが可能です。

さてIDTを使って、割り込みや例外を処理する様子が以下に。intr_EC

IDTには、割り込みゲート、トラップゲート、タスクゲートなどという恐ろし気なものどものみが記載されます。なお、トラップゲートといわれると先ほどの「トラップ」と1対1対応か、と思ってしまいますが、そうではないみたいデス。

    1. 割り込み、例外が発生したときに「タスクスイッチ」を起こしたければタスクゲートを使う
    2. 割り込み、例外が発生したときに「同一タスク」内で処理したければ、割り込みゲート、トラップゲートを使う
    3. 割り込みゲートとトラップゲートの差は、割り込みや例外を受け付けた後にIF(割り込み許可フラグ)をクリアする(割り込みゲート)か否かだけである。

しかしね、ここでいう「タスクスイッチ」は、x86のプロテクトモード・ハードウエアでサポートされている「タスクスイッチ」です。別に使わなくてもよいし。OSによってはx86のタスクスイッチなど使わんというケースも多い筈。

いろいろ準備してある割には、使われない機能が多くて残念?そうなのか?

ぐだぐだ低レベルプログラミング(242)x86(16bit)、コールゲートと制御転送 へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です