3

でコンパイルするためにを使用して、保護モードでハードウェア割り込みハンドラーをセットアップしようとしています。これが可能な最小のコードです(タイマー割り込み)、私は推測します:

#include <dpmi.h>
#include <go32.h>
#include <stdio.h>

unsigned int counter = 0;

void handler(void) {
    ++counter;
}
void endHandler(void) {}

int main(void) {
    _go32_dpmi_seginfo oldInfo, newInfo;

    _go32_dpmi_lock_data(&counter, sizeof(counter));
    _go32_dpmi_lock_code(handler, endHandler - handler);

    _go32_dpmi_get_protected_mode_interrupt_vector(8, &oldInfo);

    newInfo.pm_offset = (int) handler;
    newInfo.pm_selector = _go32_my_cs();
    _go32_dpmi_allocate_iret_wrapper(&newInfo);

    _go32_dpmi_set_protected_mode_interrupt_vector(8, &newInfo);

    while (counter < 3) {
        printf("%u\n", counter);
    }

    _go32_dpmi_set_protected_mode_interrupt_vector(8, &oldInfo);
    _go32_dpmi_free_iret_wrapper(&newInfo);

    return 0;
}

ハンドラーをチェーンしているのではなく、置き換えていることに注意してください。カウンターはそれ以上増加しません1(したがって、メイン ループを停止することはありません)。これにより、ハンドラーが正しく返されないか、1 回だけ呼び出されると推測されます。一方、チェーンは正常に機能します (ラッパー行を削除して に置き換えますset_protected_mode) chain_protected_mode。行がありませんか?

4

1 に答える 1

0

ドキュメントにリンクされている Jonathon Reinhart の例のように、古い割り込みハンドラーをチェーンする必要があります。古いハンドラーは割り込みコントローラーに割り込みのアサートを停止するように指示するためです。また、BIOS クロックを刻み続けるという追加の利点もあるため、プログラムを実行するたびに数秒失われることはありません。そうしないと、割り込みハンドラーが戻ったときに、CPU がすぐにハンドラーを再度呼び出し、プログラムが無限ループに陥ります。

また、GCC が のendHandler後に配置されるという保証はありませんhandlerhandlerページにまたがる場合に備えて、ページの開始と次のページの両方を単純にロックすることをお勧めします。

_go32_dpmi_lock_code((void *) handler, 4096);

関数型へのポインターから void へのポインターへの自動変換がないため、ここではキャストが必要であることに注意してください。

于 2017-02-08T21:09:07.583 に答える