4 - Forth Interest Group
4 - Forth Interest Group
4 - Forth Interest Group
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
IF 52 C, THEN \ PUSH DX<br />
THEN NEXT, ; --><br />
Screen 13<br />
\ EXTERN 15FEB93 RA 03JAN93<br />
\ : HEADER CREATE -2 ALLOT ; \ if you need it<br />
: CREATE-EXTERN ( cfa patch-addr --- )<br />
HEADER \ lays down <strong>Forth</strong> name and link for this word<br />
SWAP , , EXT-LINK, \ I cfa I patch I next-extern I<br />
BL WORD<br />
\ HERE $MOVE HERE \ include if WORD doesn't work at HERE<br />
C@ 1+ ALLOT ; \ I linker-name I<br />
: EXTERN ( #out #in --- ) ( ... --- ax dx I ax I )<br />
OVER 0 2 WITHIN O= IF ." INVALID # OUT PARAMS " ABORT THEN<br />
CODE-EXTERN \ cfa patch-addr<br />
CREATE-EXTERN ;<br />
--> USAGE: #out #in EXTERN DOG -dog<br />
creates <strong>Forth</strong> word DOG to execute external -dog<br />
with #in params on stack before and #out after<br />
Screen 14<br />
\ SHOW-FIXUPS UTILITY WORD RA 17JAN93<br />
: 4H.R BASE @ SWAP HEX 4 .R BASE ! ;<br />
: SHOWlFIXUP ( xlink --- )<br />
DUP 4H.R 2 SPACES \ XLINK<br />
XLINK>FIXADR DUP 4H.R 2 SPACES \ FIXADR<br />
2@ SWAP 4H.R ." :" 4H:R SPACE \ FIXUP<br />
DUP 2+ COUNT TYPE ;<br />
: SHOW-FIXUPS<br />
CR ." FIXUPS "<br />
CR . " XLINK FXADR SEG:OFF label "<br />
CR 1ST-XLINK<br />
BEGIN @ ?DUP<br />
WHILE DUP SHOWlFIXUP CR<br />
REPEAT ; --><br />
Screen 15<br />
\ SAVE-OBJ: OBJ RECORD WRITING 03JAN93 RA 29DEC92<br />
HEX FFFF CONSTANT TOP-ADDR \ we save up to this addr = 64K<br />
VARIABLE RECBUF \ holds address of record buffer<br />
VARIABLE RECBUFP \ pointer into record fbuffer<br />
: OBUF RECBUF RECBUFP @! ; \ sets pointer to beginning of buf<br />
: REC.HERE RECBUFP @ ; \ a minor convenience<br />
: BUF$, ( Sadr --- ) \ move and "comma-in" a string<br />
REC.HERE $MOVE REC.HERE C@ 1+ RECBUFP +! ;<br />
: (BUF,") \ based on ( . "1<br />
R> DUP COUNT + >R BUF$, ; COMPILE-ONLY<br />
: BUF, " COMPILE (BUF, 'I)<br />
11<br />
I ; IMMEDIATE COMPILE-ONLY<br />
: BUFC, ( c --- ) REC .HERE C! 1 RECBUFP +! ;<br />
: BUF,<br />
--><br />
( n --- ) REC.HERE ! 2 RECBUFP +! ;<br />
: DMP.REC RECBUF @ REC.HERE OVER - DUMP ;<br />
Screen 16<br />
\ SAVE-EXE: WR.REC RA 29DEC92<br />
VARIABLE REC-FBUF \ other <strong>Forth</strong> DOS interfaces use a handle<br />
other languages) are left there<br />
for the caller to clean up. Func-<br />
tions that return values return<br />
them in registers: in Borland<br />
and Microsoft C, 16-bit values<br />
are returned in AX and 32-bit<br />
values in DX;AX. Since <strong>Forth</strong><br />
tends to live in (single or mul-<br />
tiple) 64K segments, the exter-<br />
nal C (or other) functions we<br />
use will have to be referenced<br />
by long calls (segment:offset)<br />
and should therefore be com-<br />
piled in the medium, large, or<br />
huge models, or at least be<br />
declared as "far" or "huge."<br />
The huge model, though of<br />
course slowest, is the most<br />
straightforward, since huge<br />
functions save and set the DS<br />
register when they're entered<br />
and restore it when they leave,<br />
keeping <strong>Forth</strong> from having to<br />
know where C keeps its data,<br />
and preventing unexpected<br />
access to <strong>Forth</strong>'s own. The<br />
only data we have to share is<br />
passed (directly or by refer-<br />
ence) on the stack, which had<br />
better be big enough.<br />
So in <strong>Forth</strong> we need a way<br />
to make long calls to places we<br />
don't know about, in such a<br />
way that the Microsoft or<br />
Borland linker can fur them up<br />
for us. I have written a defining<br />
word, EXTERN, which lays<br />
down code for long calls and<br />
links all the words it creates<br />
into a forward-linked list of<br />
external references so they can<br />
be found easily when we write<br />
out the OBJ file.<br />
EXTERN takes two param-<br />
eters on the stack and is fol-<br />
lowed by two names: the <strong>Forth</strong><br />
word that will invoke the long<br />
call, and the external reference<br />
that the linker will use to re-<br />
solve the address of the call<br />
with the appropriate C func-<br />
tion. The usage is<br />
EXTERN <br />
<strong>Forth</strong> Dimensions 15 November 1993 December