受保护的硬件中断处理程序卡住了? (DJGPP)
Protected Hardware Interrupt Handler Stuck? (DJGPP)
我正在尝试使用 djgpp-2 for compiling in 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
(因此永远不会停止主循环)让我猜测处理程序没有 return 正确或只被调用一次。另一方面,链接工作正常(删除包装线并将 set_protected_mode
替换为 chain_protected_mode
)。
我错过了一行吗?
您需要链接旧的中断处理程序,就像在文档中链接到的 Jonathon Reinhart 示例中一样,因为旧的处理程序将告诉中断控制器停止断言中断。它还具有保持 BIOS 时钟滴答作响的额外好处,因此每次 运行 程序时它都不会损失几秒钟。否则,当您的中断处理程序 returns 时,CPU 将立即再次调用该处理程序,您的程序将陷入无限循环。
也不能保证 GCC 会将 endHandler
放在 handler
之后。我建议只锁定 handler
开始的页面和下一页,以防它跨越页面:
_go32_dpmi_lock_code((void *) handler, 4096);
请注意,此处需要强制转换,因为不会自动将指向函数类型的指针转换为指向 void 的指针。
我正在尝试使用 djgpp-2 for compiling in 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
(因此永远不会停止主循环)让我猜测处理程序没有 return 正确或只被调用一次。另一方面,链接工作正常(删除包装线并将 set_protected_mode
替换为 chain_protected_mode
)。
我错过了一行吗?
您需要链接旧的中断处理程序,就像在文档中链接到的 Jonathon Reinhart 示例中一样,因为旧的处理程序将告诉中断控制器停止断言中断。它还具有保持 BIOS 时钟滴答作响的额外好处,因此每次 运行 程序时它都不会损失几秒钟。否则,当您的中断处理程序 returns 时,CPU 将立即再次调用该处理程序,您的程序将陷入无限循环。
也不能保证 GCC 会将 endHandler
放在 handler
之后。我建议只锁定 handler
开始的页面和下一页,以防它跨越页面:
_go32_dpmi_lock_code((void *) handler, 4096);
请注意,此处需要强制转换,因为不会自动将指向函数类型的指针转换为指向 void 的指针。