我正在尝试在保护模式下设置一个硬件中断处理程序,使用djgpp-2在dosbox-0.74中编译。下面是最小的代码(计时器中断),我猜:
#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 (因此永远不会停止主循环),这让我猜测处理程序没有正确返回或只被调用了一次。另一方面,链接工作得很好(删除包装器行,并用chain_protected_mode替换set_protected_mode )。我是不是漏掉了一行?
发布于 2017-02-09 05:09:08
您需要链接旧的中断处理程序,就像文档中链接的示例Jonathon Reinhart一样,因为旧的处理程序会告诉中断控制器停止断言中断。它还有一个额外的好处,那就是保持BIOS时钟滴答作响,这样每次运行程序时它都不会损失几秒钟。否则,当您的中断处理程序返回时,CPU将立即再次调用该处理程序,并且您的程序将陷入无限循环。
也不能保证GCC会把endHandler放在handler之后。我建议只简单地锁定handler开始的页面和下一个页面,以防它跨页面:
_go32_dpmi_lock_code((void *) handler, 4096);注意,这里需要强制转换,因为没有从指向函数类型的指针到指向void的指针的自动转换。
https://stackoverflow.com/questions/42111493
复制相似问题