READ.ME file for XLI examples ----- Introduction The XLI directory contains source code examples of XLI interfaces implemented in the following languages: Lattice C, version 3.0 Microsoft C, version 4.0 Turbo Pascal, version 3.0 Turbo C, version 1.0 Microsoft Macro Assembler, version 4.0 Instructions for building each executable file are contained in the source file. The TRIG_xx files build functional duplicates of NEWTRIG.EXE, the file that implements the transcendental functions in PC Scheme 3.0. If you have the Lattice C compiler, the instructions given will build the exact duplicate of NEWTRIG.EXE. Two other files, EXEC.C and SOUND.ASM, are XLI programs, distinct from the above, that you may find useful in their own right. Corresponding .EXE's are provided so you can use them immediately just by inserting their pathnames in your .XLI control file. ----- Description of files in XLI directory READ.ME this file TRIG_LC.C Lattice C source (small model) GLUE_LC.ASM asm routine to link with above; implements far calls to XLI for small model program TRIG_LC.XLI XLI control file for above TRIG_MS.C Microsoft C source (small model) GLUE_MS.ASM asm routine to link with above; implements far calls to XLI for small model program TRIG_MS.XLI XLI control file for above TRIG_TP.PAS Turbo Pascal source Note: Due to floating point representation differences between Turbo Pascal and PC Scheme, this file implements simple add, subtract, and multiply of integers, so the "trig" designation is a misnomer. TRIG_TP.XLI XLI control file for above TRIG_TC.PAS Turbo C source (small model) TRIG_TC.XLI XLI control file for above PMATH.S Scheme source file that interfaces with NEWTRIG.EXE. Since XLI routine names inside XCALL's are independent of the names of the underlying functions that implement them, this one file should work with any of the executable files generated from the different sources (except Turbo Pascal, which implements a different set of examples). SOUND.ASM Microsoft Macro Assembler source for generating sounds on the PC SOUND.DOC user documentation for SOUND.ASM SOUND.EXE executable version of SOUND.ASM EXEC.C Lattice C source (small model) for running executable programs via XLI rather than DOS-CALL EXEC.DOC user documentation for EXEC.C EXEC.EXE executable version of EXEC.C ----- Debugging XLI external routines - I During the first stages of developing an XLI interface there may be problems with connecting the external program to PC Scheme (PCS). This is awkward to debug because XLI bids an external program as a child task, and the child is not yet in memory where a machine breakpoint can be installed. The following may help to localize where such problems lie. First enter PC Scheme normally, specifying a non-existant .XLI file to prevent the non-functioning interface from loading. Then enter (%XLI-DEBUG 0) and remember the number that is returned. This will become the offset value we will use below. Exit PCS and reenter with: DEBUG R DEBUG's R command dumps the processor registers. Note the value of the ES register and add 10 (hex) to it; we will use this as a segment value. Now if you disassemble PC Scheme with the U command at the segment:offset, you will see a series of JMP instructions. The first one represents the completion of bidding the child and is for use only by XLI. The second and third JMP instructions are the "wait" and "bye" entry points into XLI for your program. Now you can put a breakpoint at the "wait" JMP, then proceed. If this address is never reached, it says that your program is not jumping to XLI at the correct spot, and not much else can be done from the Scheme side to help you. However, if you print the value of the DOS termination address in your initialization code, it should match the segment:address that we derived above for the U command. This provides a useful check that you are indeed peeking into the PSP at the proper place. Remember that this address is not itself used, but offsets 3 and 6 from it, to connect with the "wait" and "bye" JMP instructions. Once you can jump to the "wait" address, you can do other consistency checks. Dumping the stack at SS:SP, the top two words (4 bytes) are the far return address to your program. If you disassemble the instructions around this location, you should see the 2 pushes, the far call, and the 2 pops required to pass information to XLI. The next word down on the stack is the program's length as calculated by your program. Oftentimes this may be the hardest quantity to determine; you should find the examples included on the PC Scheme diskettes very helpful here, as the different languages listed each have different ways of determining this value. The next word down on the stack is the address of your PSP. At location PSP+5C (hex) should be the file block far pointer. That location, in turn, starts with the characters "RB" followed by the flags field and the lookup table and parameter block pointers. At this early stage the parameter block will probably contain garbage, but the lookup table should be reasonable, and don't forget the double slashes at its end. The code executed up to the point of jumping to the "wait" entry point will be the same for every XLI interface you write (except maybe for the file block flags). This makes it straightforward to use an existing interface as a template for the next one and feel certain that establishing the connection with XLI will go smoothly. Once you are past the initial call to "wait" and you have verified the above points, you can be certain that XLI has the proper information for talking with your program. Then you can move on to getting the individual XCALL's working. Some hints on this are given in the next section. ----- Debugging XLI external routines - II To debug XCALL's, you can do the following: DEBUG G This takes you into PC Scheme. To test an XCALL, do (%XLI-DEBUG arg) where arg=0 says turn off debug, and arg=1 says turn on debug. Then do your XCALL. You'll enter the debugger positioned at an INT 3 instruction. (If you just get the Scheme prompt, you forgot to run PC Scheme under DEBUG.) DEBUG won't let you proceed through this instruction correctly (P won't move and T steps into DEBUG itself), but note the IP register. Increment it by 1 to get past the INT 3. Then step past the RETF. Immediately after the RETF, you are back in your own code. Segment and base registers are correct, but remember XCALL doesn't preserve AX through DI registers. The stack should contain your program length (on top) and PSP segment address. From your PSP you should be able to find all your other data structures and verify their contents. Don't use DEBUG's Q command to stop PCS and return to DOS. This aborts PCS and prevents XLI from clearing the external routines from memory, which reduces the amount of usable memory considerably. Return instead to Scheme and use (EXIT).