この質問に触発されて
GDB を強制的に逆アセンブルするにはどうすればよいですか?
INT 21hをコンセプトに考えてみました。さて、私は内部構造について非常にさびた知識を持っていますが、詳細はそれほど多くありません。C64では通常の割り込みとマスク不可能な割り込みがあったことを覚えていますが、私の知識はここで終わりです。手がかりを教えてください。それはDOS関連の戦略ですか?
この質問に触発されて
GDB を強制的に逆アセンブルするにはどうすればよいですか?
INT 21hをコンセプトに考えてみました。さて、私は内部構造について非常にさびた知識を持っていますが、詳細はそれほど多くありません。C64では通常の割り込みとマスク不可能な割り込みがあったことを覚えていますが、私の知識はここで終わりです。手がかりを教えてください。それはDOS関連の戦略ですか?
ここから: キーボードの読み取り、コンソールおよびプリンターへの書き込みなど、さまざまな機能に使用される多目的 DOS 割り込み。また、以前のファイル制御ブロック (FCB) メソッドを使用して、ディスクの読み取りと書き込みにも使用されていました。
DOS は、PC にファイル/ディレクトリの抽象化を提供するために使用されるライブラリと考えることができます (およびもう少し)。int 21h
メモリ内のどこに配置されるかを事前に知らなくても、このライブラリからコードを簡単に呼び出せるようにする単純なハードウェア「トリック」です。あるいは、これを DOS API を利用する方法と考えることができます。
現在、ソフトウェア割り込みのトピックは複雑です。これは、インテルが古いソフトウェアとの互換性を維持しようとしながら、x86 ファミリに機能を追加するにつれて概念が時間とともに進化したためです。適切な説明には数ページかかりますが、簡潔にしようと思います。
主な問題は、リアル モードかプロテクト モードかということです。
リアル モードは、x86 プロセッサの単純な「オリジナル」操作モードです。これは、DOS が実行されるモードです (Windows で DOS プログラムを実行すると、リアル モード プロセッサが仮想化されるため、同じルールが適用されます)。現在実行中のプログラムは、プロセッサを完全に制御できます。
リアル モードでは、0 から 255 までの割り込みごとにどのアドレスにジャンプするかをプロセッサに指示するベクトル テーブルがあります。このテーブルは、BIOS と DOS、デバイス ドライバ、および場合によっては特別なニーズを持つプログラムによって読み込まれます。これらの割り込みの一部は、ハードウェア (キー押下など) によって生成できます。その他は、特定のソフトウェア条件 (0 による除算など) によって生成されます。いずれも命令を実行することで生成できますint n
。
プログラムは「割り込みを有効にする」フラグを設定/クリアできます。int
このフラグはハードウェア割り込みのみに影響し、命令には影響しません。
DOS 設計者は、DOS 要求を処理するために割り込み番号 21h を使用することを選択しました。この番号は実際には重要ではありません。当時は未使用のエントリでした。他にもたくさんあります (たとえば、番号 10h は BIOS にインストールされた、グラフィックを処理する割り込みルーチンです)。また、これはすべて IBM PC 互換機のみを対象としていることにも注意してください。たとえば、組み込みシステムの x86 プロセッサでは、ソフトウェアと割り込みテーブルの配置がまったく異なる場合があります。
保護モードは、286 プロセッサで導入され、386 で大幅に拡張された複雑な「セキュリティ対応」モードです。複数の特権レベルを提供します。OS はこれらすべてを構成する必要があります (OS が間違った設定を行うと、セキュリティを悪用される可能性があります)。ユーザープログラムは一般に、ハードウェアポートへのアクセス、割り込みフラグの変更、または特定のメモリ領域へのアクセスを試みる「最小限の特権」モードの操作に限定され、プログラムを停止し、OS が何をすべきか (終了するかどうか) を決定できるようにします。プログラムを変更するか、プログラムが必要と思われるものをプログラムに提供します)。
割り込み処理がより複雑になります。一般に、ユーザー プログラムがソフトウェア割り込みを実行する場合、割り込み番号は割り込みテーブルへのベクトルとして使用されません。むしろ、一般的な保護例外が生成され、その例外の OS ハンドラーが (OS がこのように設計されている場合) プロセスが必要とするものを処理し、要求を処理します。Linux と Windows は、過去に (現在ではないにしても)、システム コールにこの種のメカニズムを使用していたと確信しています。ただし、SYSENTER 命令など、これを実現する方法は他にもあります。
Ralph Brown の割り込みリストには、どの割り込みが何をするかに関する多くの情報が含まれています。int 21は、他のすべてと同様に、レジスタ値に応じて幅広い機能をサポートします。
Ralph Brown のリストの非 HTML バージョンも利用できます。
INT 命令はソフトウェア割り込みです。これにより、メモリ内の固定位置である割り込みベクトルが指すルーチンにジャンプします。INT 命令の利点は、JMP の 6 バイトとは対照的に、長さが 2 バイトしかないことと、割り込みベクトルの内容を変更することで簡単にリダイレクトできることです。
これは、割り込みに関する素晴らしいThe Art of Assembly Language Programmingからのものです。
80x86 では、一般に割り込みと呼ばれる 3 種類のイベントがあります。トラップ、例外、および割り込み (ハードウェア割り込み) です。この章では、これらの各形式について説明し、80x86 CPU および PC 互換マシンでのサポートについて説明します。
トラップと例外という用語はしばしば同義語として使用されますが、トラップという用語は、プログラマーが開始し、特別なハンドラー ルーチンへの制御の転送を予期することを示すために使用します。多くの点で、トラップは特殊なサブルーチン呼び出しにすぎません。多くのテキストでは、トラップをソフトウェア割り込みと呼んでいます。80x86 int 命令は、トラップを実行するための主要な手段です。通常、トラップは無条件であることに注意してください。つまり、int 命令を実行すると、制御は常にトラップに関連付けられたプロシージャに移ります。トラップは明示的な命令によって実行されるため、プログラム内のどの命令がトラップ処理ルーチンを呼び出すかを正確に判断するのは簡単です。
Int 0x21 は x86 ソフトウェア割り込みです。基本的には、ソフトウェア割り込み関数のアドレスをリストするメモリ内の固定ポイントに割り込みテーブルがあることを意味します。x86 CPU が割り込みオペコードを受信すると (または、特定のソフトウェア割り込みを実行する必要があると判断した場合)、そのテーブルを参照して、そのポイントへの呼び出しを実行します (そのポイントの関数は、戻るiret
代わりに使用する必要があります)。ret
Int 0x21 およびその他のソフトウェア割り込みを再マップすることができます (DOS 内であっても、これにはマイナスの副作用が生じる可能性があります)。マップまたはチェーンするための興味深いソフトウェア割り込みの 1 つは、Int 0x1C (注意が必要な場合は 0x08) です。これは、毎秒 18.2 回呼び出されるシステム ティック割り込みです。これは、シングル スレッドのリアル モードでも、「バックグラウンド」プロセスを作成するために使用できます (リアル モード プロセスは、割り込み関数を呼び出すために 1 秒あたり 18.2 回中断されます)。
DOS オペレーティング システム (または、Windows コンソールなどの DOS エミュレーションを提供するシステム) では、Int 0x21 は、実質的に DOS オペレーティング システムのメイン "API" にマップされます。AH レジスタに異なる値を提供することにより、ファイルを開く (AH=0x3D) や画面への印刷 (AH=0x09) など、異なる DOS 機能を実行できます。
これは「ソフトウェア割り込み」です。したがって、ハードウェア割り込みはまったくありません。
アプリケーションがソフトウェア割り込みを呼び出す場合、それは基本的にサブルーチン呼び出しを行うのと同じですが、(サブルーチン呼び出しとは異なり)呼び出すコードの正確なメモリアドレスを知る必要がない点が異なります。
システムソフトウェア(DOSやBIOSなど)は、ソフトウェア割り込みとしてAPIをアプリケーションに公開します。
したがって、ソフトウェア割り込みは一種のダイナミックリンクです。
(ほとんど) DOS インターフェース全体が、さまざまなレジスターのパラメーターを使用して、INT21h コマンドとして使用できるようになりました。組み込みのハードウェア テーブルを使用して正しいコードにジャンプするのはちょっとしたトリックです。また、INT 33h はマウス用でした。
実際、ここには多くの概念があります。基本から始めましょう。
割り込みとは、CPU に注意を要求し、現在のプログラム フローを中断し、割り込みハンドラー (ISR - 割り込みサービス ルーチン) にジャンプし、何らかの作業 (通常は OS カーネルまたはデバイス ドライバーによる) を行ってから戻ることを意味します。
割り込みの一般的な用途は何ですか?
CPU は、どこにジャンプしてテーブルを参照するかを決定します (例外ベクトル、割り込みベクトル、x86 リアル モードの IVT、x86 保護モードの IDT など)。一部の CPU には、ハードウェア割り込み用に 1 つのベクターがあり、例外用に別のベクターがあり、ISR は割り込みの発信元を識別するために何らかの作業を行う必要があります。他のものは多くのベクトルを持ち、非常に特定の ISR に直接ジャンプします。
x86 には 256 の割り込みベクトルがあります。元の PC では、これらはいくつかのグループに分けられていました。
00-04
NMI を含む CPU 例外。それ以降の CPU (80186、286、...) では、この範囲が拡大し、次の範囲と重なっています。08-0F
これらは、通常 IRQ0-7 と呼ばれるハードウェア割り込みです。PC-AT に IRQ8-15 を追加10-1F
BIOS 呼び出し。BIOS は具体的なマシンに依存する DOS の一部であるため、概念的には、これらはシステム コールと見なすことができます (CP/M ではそのように定義されていました)。20-2F
DOS 呼び出し。これらのいくつかは多重化されており、多数の機能を提供します。主なものは、ほとんどの DOS サービスを提供する INT 21h です。30-FF
残りは、外部ドライバーとユーザー プログラムで使用します。