Создание команды FAR jump в 32-битном режиме Open Watcom C

Мне нужно сгенерировать инструкцию с большим прыжком, чтобы перейти к другому ISR (Routing Service Routine). Я разрабатываю 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() в стеке при его prologе (и это потенциально много регистров, и, что самое главное, есть также обратный адрес, который был захоронен, к которому должен вернуться ваш old08() !).

Почему так изобретательно?

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

Эта функция может использоваться для перехода к другому обработчику прерываний в цепочке. Эта функция никогда не возвращается. Он выталкивает все регистры, сохраненные ключевым словом прерывания, и переходит к обработчику. Когда обработчик прерываний, назначенный func, получает управление, стек и регистры выглядят так, как будто только что произошло прерывание.

Эта функция может использоваться только в функции, объявленной с ключевым словом прерывания .

Преимущество прыжков, а не вызовов не очевидно в обработчиках irq, но определенно для обработчиков прерываний программного обеспечения. Следующий обработчик прерываний программного обеспечения в цепочке ожидает, что регистр cpu будет содержать некоторую информацию, например, переданные ему параметры, поэтому перед переходом на следующий обработчик chainintr восстанавливает все регистры процессора, как если бы следующий обработчик непосредственно получал элемент управления.

Я бы, наверное, написал что-то вроде этого:

 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 бит.