Generating FAR jump instruction in 32-bit Open Watcom C

淺唱寂寞╮ 提交于 2019-12-25 05:17:16

问题


I need to generate a far jump instruction to jump to another ISR(Interrupt Service Routine). I'm developing a 32-bit FreeDOS application.

After reading OW manuals(cguide.pdf and clr.pdf), I figured out two ways that compiled successfully w/o any warning or error.

    /* 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*/
     }

The other approach that I figured out is:

      /* 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);        

Now my question is which of the above two ways is more correct or better? Any ideas or opinions?

Are there any other ways to accomplish this?


回答1:


interrupt functions are always far.

Your manually constructed far jump appears correct as far as the instruction itself is concerned, however, I bet, simply jumping (instead of calling) won't remove the stuff previously saved by new08() on the stack at its prologue (and that's potentially a lot of registers, and most importantly, there's also the return address buried to which your old08() has to return to!).

Why so inventive?




回答2:


    #include <dos.h>
    void _chain_intr( void (__interrupt __far *func)(void) );

This function can be used to jump to another interrupt handler in the chain. This function never returns. It pops off all the registers saved by the interrupt keyword and jumps to the handler. When the interrupt handler designated by func receives control, the stack and registers appear as though the interrupt just occurred.

This function can only be used within a function declared with a interrupt keyword.

The advantage of jumping rather than calling is not obvious in irq handlers, but definitely for software interrupt handlers. The next software interrupt handler in the chain expects cpu register to contain some info eg parameters passed to it, so before jumping to next handler chainintr restores all cpu registers as if the next handler directly recieves the control.




回答3:


I'd probably write something like this:

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 */
}

As I recall 32-bit mode will push and pop selectors as 32-bit units even though only the low 16 bits are used.



来源:https://stackoverflow.com/questions/11538081/generating-far-jump-instruction-in-32-bit-open-watcom-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!