home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Big Blue Disk 23
/
bbd23.zip
/
ML2INLIN.TXT
< prev
next >
Wrap
Text File
|
1988-06-29
|
7KB
|
117 lines
|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