home *** CD-ROM | disk | FTP | other *** search
- |D╔══════════════════╗════════════════════════════════════════════════════════════
- |D║ |5The Happy Hacker |D║════════════════════════════════════════════════════════════
- |D╚══════════════════╝════════════════════════════════════════════════════════════
-
- ^C^1Machine Language to Turbo Pascal Inline
- ^Cby
- ^CAshraf Maher Kaiser
-
- Turbo Pascal allows the user to mix Pascal with Machine Language by using the
- Inline statement, which allows the insertion of the machine code in numeric
- format in the Turbo program. The process of writing the Inline statements is
- tedious and error prone if done manually. This utility reads in a .COM file and
- creates a file with equivalent Turbo Pascal Inline statement. Just write the
- function in assembly, assemble and link it and convert it to a .COM or .BIN file
- with the EXE2BIN utility (or you can input it using DEBUG), then run this
- utility to get a Turbo procedure (or function) with equivalent Inline
- statements.
-
- The user supplies the name of the file to be converted to Turbo Inline
- statements, and the name of the file to be created. The user may choose whether
- or not to have the offsets of the instructions printed, which may be useful for
- tracing branches in the code and data locations.
-
- The program works by determining the input file size, and writes out a file
- containing commands for DEBUG (the debugger that comes with MS-DOS) to
- disassemble the correct size of code. DEBUG is then invoked from within the
- program and its input is redirected from the file (INDEBUG) which contains the
- commands and its output is redirected to the file (OUTDEBUG). Finally, the
- output file (OUTDEBUG) is processed to create the Turbo file containing Inline
- statements. Therefore, the files COMMAND.COM and DEBUG.COM should be accessible
- to the program while running, and the program will prompt you for their drive
- letter and path. Note that you will need plenty of disk space for the input
- and output files.
-
- The program then asks for the procedure or function name of the routine.
- Then it asks for any global variable references for your procedure or function.
- Next, it asks for local variables, that is any variables accessed by the
- assembly language routine. Finally, it asks for the parameters to be passed to
- the procedure. After entering the data for each routine, you will have a chance
- to change any of the data associated with each section. If no type is entered
- with a local variable or a passed parameter, then the next type entered will be
- used unless you change from VAR to value or vice versa.
-
- The key to this program working properly is in the coding of your assembler
- program. Global variables should be placed in the data segment. The type of
- variable determines its offset as assembled in the binary file and will
- correspond to the offset from start of the data segment in the assembly file.
- The variables appear in the OUTDEBUG file as 4 digit offsets enclosed in
- brackets, i.e. [0000],[0002]. If the type of variable specified in ML2INLINE
- does not match the number of bytes defined in the assembler program, then
- ML2INLINE will not properly place the Turbo global variable names in the inline
- program. Here is an example of assembler code with the associated Turbo code.
-
- data segment
- test1 db ? test1: byte;
- test2 dw ? test2: integer;
- test3 db 81 dup(?) test3: string[80]; { specify as 81 bytes }
- test4 db ? test4: byte; { in ML2INLINE }
- data ends
-
- Local variables and passed parameters are referenced in the inline code from
- the base pointer [BP]. Local variables should be coded in the assembly listing
- as negative offsets to BP. The first variable is coded as [BP-1], the second as
- [BP-2], etc. Parameters passed to the inline procedure should be passed as
- positive offsets to BP. The first variable that Turbo pushes on the stack is
- coded as [BP+1], the second as [BP+2], etc. The ML2INLINE entry routine assumes
- a 1 byte offset to the pointer, but if you are passing more than 255 bytes to
- the inline routine or accessing more than 255 bytes of local variables, then you
- should add 256 to the parameter number in the assembly code for that and all
- variables that follow it and change the 2 byte offset reference in the ML2INLINE
- entry to yes. This is because the machine code is different for a one byte
- offset and a two byte offset. Remember that Turbo passes the last variable in
- its parameter list first, and the first one last, but local variables are
- assigned in normal order. The program follows this convention to keep you
- reminded of this. Here is an example of Turbo code and what ML2INLINE expects
- to see when it replaces the text.
-
- Procedure Test (Up, Down: byte; Across: integer);
- var
- i,j: byte;
- k: integer;
-
- ML2INLINE will replace [BP+3] with <Up, [BP+2] with <Down, and [BP+1] with
- <Across as passed parameters, and [BP-1] with i, [BP-2] as j, and [BP-3] with k
- as local variables. If Across is changed to a type of String[255] then Down and
- Up will need offsets of 258 (102h) and 259 (103h) respectively, and ML2INLINE
- will expect to see [BP+0102] and [BP+0103], and will place >Down and >Up in the
- inline code.
-
- If your routine accesses global variables, then you should place 2 nops at
- the end of the code segment. ML2INLINE will detect these and you can end the
- processing without the data segment bytes at the end of the inline code.
- ML2INLINE will process multiple procedures. Each procedure should be separated
- by at least 2 nops. The program detects 2 nops as the end of a procedure, so
- that you can write several procedures in one file. Global variables are
- accessed throughout all the procedures, but each procedure will have its own
- local variables and parameters. If you have nested procedures, you will have to
- place the proper amount of NOPs in your assembly code in order to get the
- correct compiled addresses. When Turbo compiles procedures, it places
- instructions at the beginning and end of every procedure and function. Turbo
- places 7 bytes of code before every procedure and 7 bytes after if you pass no
- parameters to the procedure. If you pass any parameters to the procedure, Turbo
- places 9 bytes after it. If you declare local variables to the procedure, Turbo
- places 1 extra byte of code if the total size of the local variables is 1 byte,
- 2 extra bytes if the size is 2 bytes, 3 extra bytes if the size is 3 to 255
- bytes and 4 extra bytes if the size is greater than 256 bytes. This will enable
- you to calculate the correct number of NOPs to put in your assembly language
- code.
-
- Since, there is not much extra disk space on this disk, you should run it
- from outside the BIG BLUE DISK menu. To run this program outside the BIG BLUE
- DISK menu, type ^1ML2INLIN^0.
-
- DISK FILES USED BY THIS PROGRAM:
- ^FML2INLIN.COM
- ^FML2INLIN.CFG
-