小物を設計する〜割り込みハンドラをCでもともと私の仕事は、ライブラリ屋(小道具屋?)。いろんなシステムハウス・ソフトハウスに、ライブラリやオブジェクト、資料なんかを提供しています。今回は、プロテクトモード・モニタをC言語で作るときに使えそうな小物について紹介します。トリッキーなモノも含まれていますので、注意してくださいね。そこからC言語を呼び出すのが、ポピュラーな方法でしょう。アセンブラの量が増えてイマイチです。そこで、こんなコードを考えてみました。_intr_magic_intr_magic:pushebpmovebp,esppushdspushespushamovax,0x10movds,axmoves,axmoveax,[ebp+4];呼び出し元アドレスcalleaxpopapopespopdspopebpaddesp,4;呼び出し元アドレス(オリジナル)破棄stiiretこのコードは、検証が済んでいません。コンパイラの種類や、状況によっては使えないかもしません。関数に指定しなければならないかについて説明します。call命令、関数からの復帰はret命令が生成されます。割り込みなのに、ret命令で戻ると、スタックに4バイトほどゴミが残ります。あと、割り込み時には、内部で使用する、あらゆるレジスタを保存する必要があります。これは、一般的な関数では行われません。少なくともeaxは戻り値として使用されるため、壊したい放題です。・関数からiret命令で戻れない。・レジスタを壊す可能性がある。いった理由で、割り込みハンドラとして登録できないわけです。このような処理を行ってくれるのです。これをなんとかC言語の関数をハンドラにできないかと思って作ったのが上記のプロシジャーです。関数を、割り込みハンドラの先頭で呼び出してください。このプロシジャーが呼び出され、EBPをPUSHした時点でのスタックは、次のようになっています。(一般保護違反による割り込みを除きます。このintr_magic()を実行した後、動作すべきアドレスが記載されています。このプロシジャーがcall文で呼び出されているので、当たり前の話です。(この時点でスタックは上の図よりだいぶ成長します)このアドレスを逆コールします。コールされた関数の戻り位置を逆にコールするのです。レジスタ破壊の問題もありません。これによって、レジスタ破壊が起こるケースですが、今のところ大丈夫そうです。C言語からアセンブラプロシジャーをcallしたときのアドレス部分のスタックを破棄します。これで、最初のcallは、なかったことになります。スタックをダマすことは結構よく使うテクニックです。仮想86モードにはいる時など重宝します。MUSAKUI-LABO。