x86でプロテクトモードで割り込みがトリガーされた場合、どの割り込み番号が発生したかを把握することはできますか?たとえば、int0xFFと呼んだとします。ハンドラーで、int 0xFFが呼び出されたことを確認できますか?
3 に答える
一意の割り込みハンドラー(または、少なくとも一意のエントリポイントとプロローグコード)がある場合は、もちろん、と区別することができint 0xFF
ますint 0x30
。ISRアドレスはに格納されているIDT
ため、ここから差別化が始まります。
独自のISRに代わる優れた方法はありません。これが理由です...
ISRでは、呼び出し元のスタックを調べ、差出人アドレスを確認し、差出人アドレスの直前のコードを調べて、それが2バイトint n
命令(バイト:0xCD、nとしてエンコード)か他のものかを確認できます。問題は、1バイトの命令(それぞれ0xCCおよび0xCEとしてエンコードされている)もあることint 3
ですinto
。0xCD + 0xCC(int 0xCC
)または0xCD + 0xCE(int 0xCE
)と単に0xCC(int 3
)または0xCE(into
)をどのように区別しますか?0xCCまたは0xCEの前に何かがある可能性があります。命令の長さが可変であるため、コードを逆方向に簡単かつ確実に分析/逆アセンブルすることはできません。
割り込み/例外をトリガーする他の方法についてはどうud2
ですか?または、#GP、#PFをトリガーする命令?それらは任意の命令にすることができます。
また、例外はまったく同じ方法で処理されないことに注意してください。それらのいくつかには、ISRに入る前にCPUによってスタックに保存された追加情報が付属しています。これはエラーコードです。他の人はこのエラーコードを持っておらず、ISRは実行する前にそれを削除する必要がありますiret
。例外ベクトルの決定に誤りがあると、コードがクラッシュまたはハングします。
ここで、ハードウェア割り込みについて...どのハードウェア割り込みが処理されているかを判断できる場合があります。PIC
には(in-service register
)ISR
があり、ビットを1(AFAIR)に設定するとIRQ
、が示されますが、優先度の高い割り込みが優先度の低い割り込みを処理するように(ISR内で割り込みを有効にすることにより)、ISRをプリエンプトさせると、割り込みの識別はすぐに複雑になります。必要以上に。
したがって、すべてのIRQ、例外、およびシステムコールに固有のISRを使用するだけです。または、1つの共通ISRを使用しますが、複数の一意のエントリポイントを使用して、それぞれがスタックに一意の番号(=ベクトル番号)を保存します。その後の共通コードは、この番号を抽出し、その割り込みベクトルに必要なことを実行します。
値をスタックにプッシュするスタブを作成することは、これに対処するための優れた方法であり、JamesMolloyチュートリアルで使用されます。
%macro ISR_NOERRCODE 1
global isr%1
isr%1:
cli ; Disable interrupts firstly.
push byte 0 ; Push a dummy error code.
push byte %1 ; Push the interrupt number.
jmp isr_common_stub ; Go to our common handler code.
%endmacro
%macro ISR_ERRCODE 1
global isr%1
isr%1:
cli ; Disable interrupts.
push byte %1 ; Push the interrupt number
jmp isr_common_stub
%endmacro
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
ISR_NOERRCODE 4
ISR_NOERRCODE 5
ISR_NOERRCODE 6
ISR_NOERRCODE 7
ISR_ERRCODE 8
ISR_NOERRCODE 9
ISR_ERRCODE 10
ISR_ERRCODE 11
ISR_ERRCODE 12
ISR_ERRCODE 13
ISR_ERRCODE 14
ISR_NOERRCODE 15
/* More entries */
私は割り込みハンドラの専門家ではありませんが、元のコードが実行を再開できるように、どこかにリターンアドレスが必要です。このアドレスを古くすることができれば、おそらく割り込みの番号が含まれている前のアドレスを調べることができます。