在32位Open Watcom C中生成FAR跳转指令

我需要生成一个远跳指令来跳转到另一个ISR(中断服务程序)。 我正在开发一个32位FreeDOS应用程序。

在阅读了OW手册( cguide.pdf和clr.pdf )之后,我想出了两种无需 任何警告或错误即可成功编译的方法。

/* Code Snippet #1 */ #pragma aux old08 aborts ; void (__interrupt __far *old08)(void); // function pointer declaration void __interrupt __far new08(void) { /* Do some processing here ... */ (*old08)(); /* OW will now generate a jump inst. instead of call*/ } 

我想出的另一种方法是:

  /* Code Snippet #2 */ static void jumpToOld08(void); # pragma aux jumpToOld08 = \ ".686p" \ " DB 0xEA" \ "off_old08 DD 0" \ "sel_old08 DW 0" ; void __interrupt __far new08(void){ /* Do some processing here ... */ jumpToOld08(); } extern unsigned short sel_old08; extern unsigned int off_old08; sel_old08 = ( __segment )FP_SEG(old08); off_old08 = FP_OFF(old08); 

现在我的问题是上述哪两种方式更正确或更好? 任何想法或意见?

有没有其他方法可以实现这一目标?

interrupt函数总是很远。

对于指令本身而言,你手动构建的远跳是正确的,但是,我敢打赌,简单地跳转(而不是调用)将不会删除之前在其序言中堆栈上的new08()保存的东西(这可能是很多寄存器,最重要的是,还有你的old08()必须返回的返回地址!)。

为何如此有创意?

  #include  void _chain_intr( void (__interrupt __far *func)(void) ); 

此函数可用于跳转到链中的另一个中断处理程序。 此function永不返回。 它会弹出由interrupt关键字保存的所有寄存器并跳转到处理程序。 当func指定的中断处理程序接收控制时,堆栈和寄存器看起来好像刚刚发生了中断。

此函数只能在使用interrupt关键字声明的函数中使用。

在irq处理程序中, 跳转而不是调用的优势并不明显,但绝对是软件中断处理程序。 链中的下一个软件中断处理程序期望cpu寄存器包含一些信息,例如传递给它的参数,因此在跳转到下一个处理程序之前, chainintr会恢复所有cpu寄存器,就像下一个处理程序直接接收控件一样。

我可能会写这样的东西:

 void far_jump (uint32_t offset, uint16_t selector) { /* remove the (callee's) stack frame including the return address by manipulating esp & ebp */ /* the top of the stack now points to offset:selector */ _asm { retf ; or whatever the asm syntax dictates } /* esp & ebp will now point to the caller's stack frame */ } 

我记得32位模式将推选和弹出选择器作为32位单元,即使只使用低16位。