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(因此永远不会停止主循环)让我猜测处理程序没有正确返回或只被调用一次。另一方面,链接工作正常(删除包装行并替换set_protected_modechain_protected_mode)。我错过了一条线吗?

4

1 回答 1

0

您需要链接旧的中断处理程序,就像在文档中链接到的示例 Jonathon Reinhart 中一样,因为旧的处理程序会告诉中断控制器停止断言中断。它还具有保持 BIOS 时钟滴答作响的额外好处,因此每次运行程序时它都不会损失几秒钟。否则,当您的中断处理程序返回时,CPU 将立即再次调用该处理程序,您的程序将陷入无限循环。

也不能保证 GCC 会endHandler放在handler. 我建议只锁定页面handler开始和下一页,以防它跨越页面:

_go32_dpmi_lock_code((void *) handler, 4096);

注意这里需要强制转换,因为没有从指向函数类型的指针到指向 void 的指针的自动转换。

于 2017-02-08T21:09:07.583 回答