[Back to MISC SWAG index] [Back to Main SWAG index] [Original]

    Unit LongJump;

    { This Unit permits a long jump from deeply nested Procedures/Functions back }
    { to a predetermined starting point.                                         }

    { Whilst the purists may shudder at such a practice there are times when such}
    { an ability can be exceedingly useful.  An example of such a time is in a   }
    { BBS Program when the carrier may be lost unexpectedly whilst a user is on  }
    { line and the requirement is to "back out" to the initialisation reoutines  }
    { at the start of the Program.                                               }

    { to use the facility, it is required that a call be made to the SetJump     }
    { Function at the point to where you wish the execution to resume after a    }
    { long jump. When the time comes to return to that point call FarJump.       }

    { if you are an inexperienced Programmer, I do not recommend that this Unit  }
    { be used For other than experimentation.  Usually there are better ways to  }
    { achieve what you want to do by proper planning and structuring.  It is     }
    { rare to find a well written Program that will need such and ability.       }

    Interface

    Const
      normal = -1;                         { return was not from a LongJump call }
    Type
      jumpType = Record                        { the data need For a return jump }
                    bp,sp,cs,ip : Word;
                 end;

    Function  SetJump(Var JumpData : jumpType): Integer;
    Procedure FarJump(JumpData : jumpType; IDInfo : Integer);

    Implementation

    Type
      WordPtr = ^Word;

    Function SetJump(Var JumpData : jumpType): Integer;
      begin                     { store the return address (the old bp register) }
        JumpData.bp := WordPtr(ptr(SSeg,SPtr+2))^;
        JumpData.ip := WordPtr(ptr(SSeg,SPtr+4))^;
        JumpData.cs := WordPtr(ptr(SSeg,SPtr+6))^;
        JumpData.SP := SPtr;
        SetJump := normal;                { show that this is not a FarJump call }
      end;  { SetJump }

    Procedure FarJump(JumpData : jumpType; IDInfo : Integer );
      begin
        { change the return address of the calling routine of the stack so that  }
        { a return can be made to the caller of SetJump                          }
        { Use IDInfo as an identifier of the routine the jump occurred from      }
        WordPtr(ptr(SSeg,JumpData.SP))^   := JumpData.bp;
        WordPtr(ptr(SSeg,JumpData.SP+2))^ := JumpData.ip;
        WordPtr(ptr(SSeg,JumpData.SP+4))^ := JumpData.cs;
        Inline($8b/$46/$06);                                     { mov ax,[bp+6] }
        Inline($8b/$ae/$fa/$ff);                                 { mov bp,[bp-6] }
      end;  { FarJump }

    end.  { LongJump }

[Back to MISC SWAG index] [Back to Main SWAG index] [Original]