0

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

阅读 OW 手册(cguide.pdfclr.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);        

现在我的问题是以上两种方法中哪一种更正确或更好?有什么想法或意见吗?

有没有其他方法可以做到这一点?

4

3 回答 3

2

interrupt功能总是很遥远。

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

为什么这么有创意?

于 2012-07-18T09:39:46.743 回答
0

我可能会写这样的东西:

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 位。

于 2012-08-19T09:00:41.537 回答
0
    #include <dos.h>
    void _chain_intr( void (__interrupt __far *func)(void) );

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

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

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

于 2012-07-28T03:51:05.847 回答