home *** CD-ROM | disk | FTP | other *** search
-
- PROCEDURE SetupJumpTable;
- {-initialize the names and offsets of the near procedures}
- {
- ***************************************************
- * The programmer must maintain the lists below to *
- * include all global procedure names that will be *
- * called from the Far code segment. *
- ***************************************************
- }
- BEGIN
- {
- *** EXAMPLES and COMMENTS ********************************************
- * Order is unimportant, except that procedures which are called most *
- * often from far segment should be first in list. *
- * Case of the string is important. Must be same as string passed to *
- * MakeLongCall (avoids overhead time of uppercasing every call). *
- * Fill in your own procedure names below. *
- **********************************************************************
- }
- pnames[1] := 'mainproc1';
- poffsets[1] := Ofs(mainproc1);
- pnames[2] := 'mainproc2';
- poffsets[2] := Ofs(mainproc2);
- END; {SetupJumpTable}
-
- PROCEDURE MainCallHandler;
- {-pick up control from a far call and transfer to near procedure}
- VAR
- i : Integer;
- procofs : Integer;
- procname : BigTurboString;
- BEGIN
- {get procname from the es:si pointer passed in}
- INLINE(
- $31/$C9/ {XOR CX,CX}
- $26/ {ES: }
- $8A/$0C/ {MOV CL,[SI]}
- $FE/$C1/ {INC CL}
- $BF/procname/ {MOV DI,ofs(procname)}
- $FC/ {CLD }
- {10B:}
- $26/ {ES: }
- $AC/ {LODSB }
- $88/$03/ {MOV [BP+DI],AL}
- $47/ {INC DI}
- $E2/$F9 {LOOP 010B}
- );
- {match against the stored procnames}
- i := 0;
- REPEAT
- i := i+1;
- UNTIL (i > MaxNumProcs) OR (pnames[i] = procname);
- {error check}
- IF i > MaxNumProcs THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'Far procedure ', procname, ' not found....');
- Halt;
- END;
- {check for stack space, later}
- {assure stack aligned for parameter passing, later}
- {call the procedure}
- procofs := poffsets[i];
- INLINE(
- $C4/$46/< procofs/ {LES AX,procofs[BP]}
- $FF/$D0 {CALL AX}
- );
-
- {restore stack frame and FAR return}
- INLINE(
- $8B/$E5/ {mov sp,bp}
- $5D/ {pop bp}
- $CB {ret far}
- );
- END; {MainCallHandler}
-
- PROCEDURE LoadFarCode(FarComFileName : BigTurboString);
- {-load the FarComFile and set up the required addresses}
- CONST
- id1string : BigTurboString = 'FARCALLHANDLER FOLLOWS';
- id2string : BigTurboString = 'SETJUMPTABLE FOLLOWS';
- VAR
- f : FILE;
- len : Byte ABSOLUTE FarComFileName;
- i : Integer;
- size : Integer;
- FarCodeSeg : Integer;
- FarCodeOfs : Integer;
- ext : STRING[4];
- testlen : Byte;
- teststring : BigTurboString;
- BEGIN
-
- {assure it is a .COM file}
- ext := Copy(FarComFileName, len-3, 4);
- FOR i := 1 TO 4 DO ext[i] := UpCase(ext[i]);
- IF ext <> '.COM' THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'Far Code File must be a .COM file');
- Halt;
- END;
-
- {make sure it exists and open it}
- Assign(f, FarComFileName);
- {note we are using a block size of 1}
- {$I-} Reset(f, 1); {$I+}
- IF IOResult <> 0 THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'Far Code File not found....');
- Halt;
- END;
-
- {make sure there is something in it}
- size := FileSize(f);
- IF size = 0 THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'Far Code File is empty....');
- Halt;
- END;
-
- {make sure there is space for it}
- IF (size SHR 4) > (MaxAvail-32) THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'Far Code too large to load on heap....');
- Close(f);
- Halt;
- END;
-
- {allocate memory on heap}
- GetMem(FarCodePtr, size+512);
- {IMPORTANT: normalize seg and ofs so that we can make farcodeofs=$100}
- FarCodeSeg := Seg(FarCodePtr);
- FarCodeOfs := Ofs(FarCodePtr);
- WHILE FarCodeOfs > $100 DO BEGIN
- FarCodeOfs := FarCodeOfs-16;
- FarCodeSeg := FarCodeSeg+1;
- END;
- FarCodePtr := Ptr(FarCodeSeg, $100);
- FarCodeOfs := $100;
-
- {load code onto heap}
- BlockRead(f, farcodeptr^, size);
- Close(f);
-
- {store the pointers}
- FarJumpSet.segment := FarCodeSeg;
- FarHand.segment := FarCodeSeg;
- {store the local addresses}
- MainHand.offset := Ofs(MainCallHandler);
- MainHand.segment := CSeg;
-
- {search the far code for the idstrings identifying key offsets}
- {start at the top and work backwards, should be faster}
- i := size;
- testlen := Length(id1string)+1;
- REPEAT
- i := i-1;
- Move(Mem[FarCodeSeg:(FarCodeOfs+i)], teststring, testlen);
- UNTIL (i < 1) OR (teststring = id1string);
- IF i < 1 THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'ID string ', id1string, ' not found in Far code....');
- Halt;
- END;
- {store the adjusted offset for far calls}
- FarHand.offset := FarCodeOfs+i-7;
-
- testlen := Length(id2string)+1;
- REPEAT
- i := i-1;
- Move(Mem[FarCodeSeg:(FarCodeOfs+i)], teststring, testlen);
- UNTIL (i < 1) OR (teststring = id2string);
- IF i < 1 THEN BEGIN
- WriteLn(Con);
- WriteLn(Con, 'ID string ', id2string, ' not found in Far code....');
- Halt;
- END;
- {store the adjusted offset for far calls}
- FarJumpSet.offset := FarCodeOfs+i-7;
-
- {set up the local jump table}
- SetupJumpTable;
-
- {set up the far jump table}
- INLINE(
- $FF/$1E/FarJumpSet {CALL FAR FarJumpSet}
- );
- {we are done}
- END; {LoadFarCode}