home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
tools
/
inline
/
inline.doc
next >
Wrap
Text File
|
1988-10-05
|
21KB
|
595 lines
October 4, 1988
INLINE ASSEMBLER
Version 2.20
OVERVIEW
INLINE.EXE is an assembler designed to produce Inline 8086/8088
and 8087 code for Turbo Pascal (tm) versions 3, 4 and 5 and Turbo
C (tm) version 2.x programs. Like other assemblers, INLINE
accepts as input an assembly language source file and produces an
object file. However, in this case, the 'object' file is an
ASCII file consisting of Inline statements which may be inserted
into the Pascal or C program.
Figure 1 illustrates a Pascal function with Inline code generated
by INLINE using the source file of Figure 2. Figures 3 and 4
show the equivalent for a C function.
LOADING AND RUNNING INLINE
First create an EXE file, INLINE.EXE, by compiling INLINE.PAS
using version 4 or 5 of the Turbo Pascal compiler.
From the DOS prompt, Inline is called as:
INLINE [/C] [Infile [Outfile]]
The '/C' switch is used if the generated object file is to be
formatted for C. The two optional filenames specify the names of
the assembly language input file and the object file to be
generated. If no extensions are given, .ASM and .OBJ are used by
default. Files with no extension may be input or created by
using a simple '.' for the extension. If the object filename is
missing from the command line, an OBJ file will be created using
the same name as the source file. If neither filename is
specified, then names will be requested once execution starts.
INLINE ABC DEF
will cause INLINE to look for a source file, ABC.ASM, and create
an object file, DEF.OBJ.
INLINE /C CASM
will use the source file CASM.ASM and generate CASM.OBJ formatted
for a C program.
Once execution begins, INLINE will run to completion with the
only console output being error messages.
1
SYNTAX
The appendix lists the mnemonics accepted by INLINE. Syntax and
mnemonics correspond to that used by most assemblers but note
should be made of the following:
1. Symbols may be used within instruction entries by preceding
the symbol with a '>' (16 bit symbol) or a '<' (8 bit
symbol). The characters '+' and '-' are considered part of
the symbol. This allows computations using symbols to be
passed on to the compiler where the computation can be made.
For instance, in
MOV AX,[>Symbol+4] ;'>Symbol+4' is passed on
MOV AX,[BP+>Symbol+4] ;again '>Symbol+4' is passed on
MOV AX,>Symbol+4[BP] ;also acceptable
Note that
MOV AX,[>Symbol+4+BP]
is not correct since the wrong instruction will be generated
and '>Symbol+4+BP' will be passed on.
In Turbo C, variable symbols generally require the use of
the '&' address operator--see the discussion of the
__emit__() function in the Turbo C manual for further
details. When INLINE's object code is formatted for C, the
'<' and '>' are dropped from the output but are still
required in the ASM source file to specify the data size.
2. Labels (for use with jump instructions) may be defined
simply by appending a ':' to the first item on a line.
Avoid using CS:, DS:, ES:, and SS: as labels, as these
specify segment overrides.
3. Numeric entries are assumed to be decimal unless preceded by
a '$', '0x' or '0X' which indicate a hexadecimal entry.
Characters within single quotes may be used for numeric
entries as:
CMP AL,'a'
4. Square brackets are used to indicate 'contents of'. If no
square brackets are used, an immediate operand is assumed.
MOV AX,[>Data] ;Load AX with the contents of Data.
MOV AX,>Data ;Load AX with Data.
2
5. Instruction prefixes and segment override prefixes may
precede the instruction on the same line or may be included
on a previous line. A colon is optional after the segment
prefix.
ES: MOV AX,[1234] ;ok
REPNE MOVSB ;ok
MOV AX,ES:[1234] ;incorrect syntax for INLINE
6. Comments may be included in the source. They are delimited
by a ';'.
7. Instructions which don't clearly specify the data size
require that BYTE PTR, WORD PTR, DWORD PTR, QWORD PTR, or
TBYTE PTR be used. These may be abbreviated by using the
first two letters.
inc byte ptr [>BData]
DEC WO >WARRAY[DI]
FLD QWORD [>Dbl_Real]
8. JMP instructions may use SHORT, NEAR, or FAR (these should
not be abbreviated). In the absence of one of these words,
a SHORT jump will be encoded if the label is already defined
and is within range. If the label is not defined, a NEAR
JMP will be encoded unless SHORT is used.
A FAR CALL or JMP may be made to a direct address by stating
both the segment and offset separated by a colon.
CALL FAR $1234:$5678
For Turbo Version 3 only, direct CALL's or JMP's may be made
to other Turbo procedures and functions using symbolic
names. The '*' location counter reference is required (not
available in version 4) to allow Turbo to determine the
correct displacement, as:
CALL >ProcName-*-2
Null JMP's which may be required for delay between port
calls on the 80286, may be made as;
JMP >0 ;or
JMP SHORT <0
Normally INLINE generates only one Inline statement per source
file. However, the 'NEW' pseudo-instruction may be used to
terminate one Inline statement and begin another. Using the NEW
instruction, it is possible to create a number of Inline
statements with one source file.
3
FLOATING POINT INSTRUCTIONS
An automatic WAIT (FWAIT) opcode is generated for each floating
point instruction except for the 'no wait' instructions (those
with 'N' for the second letter). However, a WAIT instruction may
be required before a floating point instruction having a segment
override to insure the WAIT is properly positioned.
WAIT
ES:FMUL DWORD [BX]
CAVEATS
INLINE has no way of knowing the value of any symbols used so the
user should be especially careful when using the '<' byte size
specifier. A case in point is when referring to stack variables.
In Turbo Pascal, consider the following:
MOV AX,<ABC[bp] vs
MOV AX,>ABC[bp]
The use of '<' here will result in saving one byte but will only
work correctly if ABC is in the range -128 to 127. Stack offsets
often exceed this in Turbo 4, so it is much safer to use '>'.
When accessing auto variables in Turbo C, it is essential to be
certain if the stack displacement is within the range of one byte
or requires two bytes. This is because the __emit__() function
of Turbo C apparently does not provide a way to extend a byte
displacement to two bytes when the '&' operator is used. Thus
mov ax,>&abc[bp]
will cause INLINE to generate an instruction requiring a two
byte displacement but the Turbo C compiler will only generate
one byte if &abc is in the range of -128 to 127. Functions which
have only a few simple auto variables will meet the -128 to 127
requirement and it's safe in those cases to use the '<' operator.
For functions which have many variables or arrays, structures,
strings defined locally, it's probably best to avoid referring to
the auto variables from the Inline code. This one byte, two byte
problem only applies to local variables. Global variables
always have a two byte displacement and an override is available
for defined constants.
Note that just because a constant is byte size does not make it
safe to use '<'. If ABC were defined as =255, then CMP BX,<ABC
would not assemble correctly as a constant in the range -128 to
127 would be expected. Here again, it's safer to use '>'.
4
When using register variables in C, it's very important to save
and restore the SI and DI registers if these registers are used
by the Inline code. (See figure 4.) Also, any variables referred
to within the __emit__() function will not be assigned to
registers.
Many instructions may be correctly assembled in more than one
way. This has caused some confusion in the past when INLINE
produced a byte sequence different from that expected. When in
doubt, check the byte sequence using DEBUG or run it through
UNINLINE for verification.
RESTRICTIONS
The object file is limited to 32k. This includes comments and
spaces.
Symbols (including any addons from + and -) are limited to 32
characters.
Labels may be used in jump statements only and not as data
references. While there is a DB pseudo-opcode, it is not very
useful with this restriction.
The number of statement labels that may be defined is limited
only by the heap space available.
5
VERSIONS
2.00 Added 8087 instructions.
2.01 Fixed bug which wiped out INT $A vector.
2.02 Fixed bug which prevented labels from starting with BY, WO,
DW, QW, and TB.
2.1 Add NEW pseudo-instruction. Fixed bug which occurred with
filenames having no extension. Other bugs fixed, notably
those effecting IN and OUT.
2.11 Calculate restricted range for short jumps correctly.
Fix bug so CALL/JMP <register> may be used.
2.12 Allow CALL and JMP direct instructions.
2.13 Allow JMP >0 and JMP SHORT <0 for null JMP's.
2.14 Change output format to better sync with TMAP's line
numbers.
2.15 Fix 'shl cl,1' which assembled as shl cl,cl
2.16 Change byte size check in MemReg so the likes of
MOV [DI+$FE],AX will assemble right.
Allow ',' in DB pseudo op instruction.
2.17 Convert source to Turbo 4.
2.18 Implement the sign extension bit for some instructions
2.19 Fix problem in 2.18 with sign extension bit on AX,AL
instructions.
2.20 Add C output format. Fix bug in cmp bx,>abc which assembled
for a byte size constant.
(C) Copyright 1985,86,87,88 by L. David Baldwin.
INLINE may be copied and distributed freely providing that no fee
is charged and it is not part of a package for which a charge is
made.
Please report all bugs, suggestions, and problems to Dave
Baldwin, CompuServe ID #76327,53.
22 Fox Den Rd., (Summer) 144 13th St. East, (Winter)
Hollis, NH 03049 Tierra Verde, FL 33715
(603) 465-7857 (813) 867-3030
Turbo Pascal and Turbo C are trademarks of Borland
International Inc.
6
FUNCTION Scan(Limit :Integer; Ch :Char; Var T ): Integer;
{Scan Limit characters for Ch. Return the number of characters
skipped to find a match. If not found, return result=Limit.
Limit may be negative for a backwards scan.}
Var
Rslt : Integer;
begin
Inline(
$FC/ { cld ;assume forward}
$8A/$86/>Ch/ { mov al,>Ch[bp] ;char to search for}
$8B/$8E/>Limit/ { mov cx,>Limit[bp];bytes to search}
$09/$C9/ { or cx,cx ;check sign}
$9C/ { pushf ;save flags}
$79/$03/ { jns x1}
$F7/$D9/ { neg cx ;make positive}
$FD/ { std ;but search in reverse}
$89/$CA/ {x1: mov dx,cx ;save full count}
$C4/$BE/>T/ { les di,>T[bp] ;ptr to start}
$F2/$AE/ { repne scasb ;search}
$75/$01/ { jne x2}
$41/ { inc cx ;found a match}
$29/$CA/ {x2: sub dx,cx ;find count to match}
$9D/ { popf}
$79/$02/ { jns x3}
$F7/$DA/ { neg dx ;make negative if reverse}
$89/$96/>Rslt); {x3: mov >Rslt[bp],dx ;put in function result}
Scan := Rslt;
end;
Figure 1: Pascal Function using Inline Code
cld ;assume forward
mov al,>Ch[bp] ;char to search for
mov cx,>Limit[bp];bytes to search
or cx,cx ;check sign
pushf ;save flags
jns x1
neg cx ;make positive
std ;but search in reverse
x1: mov dx,cx ;save full count
les di,>T[bp] ;ptr to start
repne scasb ;search
jne x2
inc cx ;found a match
x2: sub dx,cx ;find count to match
popf
jns x3
neg dx ;make negative if reverse
x3: mov >Rslt[bp],dx ;put in function result
Figure 2: INLINE Input File for Pascal
7
int scan(int limit, char ch, void far *t)
/* Scan Limit characters for ch. Return the number of characters
skipped to find a match. If not found, return result=limit.
limit may be negative for a backwards scan. */
{int rslt;
__emit__(
0x57, /* push di ;Important if reg vars used*/
0xFC, /* cld ;assume forward*/
0x8A,0x46,&ch, /* mov al,<&ch[bp] ;char to search for*/
0x8B,0x4E,&limit,/* mov cx,<&limit[bp];bytes to search*/
0x09,0xC9, /* or cx,cx ;check sign*/
0x9C, /* pushf ;save flags*/
0x79,0x03, /* jns x1*/
0xF7,0xD9, /* neg cx ;make positive*/
0xFD, /* std ;but search in reverse*/
0x89,0xCA, /*x1: mov dx,cx ;save full count*/
0xC4,0x7E,&t, /* les di,<&t[bp] ;ptr to start*/
0xF2,0xAE, /* repne scasb ;search*/
0x75,0x01, /* jne x2*/
0x41, /* inc cx ;found a match*/
0x29,0xCA, /*x2: sub dx,cx ;find count to match*/
0x9D, /* popf*/
0x79,0x02, /* jns x3*/
0xF7,0xDA, /* neg dx ;make negative if reverse*/
0x89,0x56,&rslt, /*x3: mov <&rslt[bp],dx ;put in function result*/
0x5F); /* pop di ;restore saved di*/
return rslt;
}
Figure 3: C Function using Inline Code
push di ;Important if reg vars used
cld ;assume forward
mov al,<&ch[bp] ;char to search for
mov cx,<&limit[bp];bytes to search
or cx,cx ;check sign
pushf ;save flags
jns x1
neg cx ;make positive
std ;but search in reverse
x1: mov dx,cx ;save full count
les di,<&t[bp] ;ptr to start
repne scasb ;search
jne x2
inc cx ;found a match
x2: sub dx,cx ;find count to match
popf
jns x3
neg dx ;make negative if reverse
x3: mov <&rslt[bp],dx ;put in function result
pop di ;restore saved di
Figure 4: INLINE Input File for C
8
APPENDIX
8086/8088 Opcode Mnemonics Recognized by INLINE
AAA HLT JNE LOOPNZ ROR
AAD IDIV JNG LOOPZ SAHF
AAM IMUL JNGE MOV SAL
AAS IN JNL MOVSB SAR
ADC INC JNLE MOVSW SBB
ADD INT JNO MUL SCASB
AND INTO JNP NEG SCASW
CALL IRET JNS NOP SHL
CBW JA JNZ NOT SHR
CLC JAE JO OR SS
CLD JB JP OUT STC
CLI JBE JPE POP STD
CMC JC JPO POPF STI
CMP JCXZ JS PUSH STOSB
CMPSB JE JZ PUSHF STOSW
CMPSW JG LAHF RCL SUB
CS JGE LDS RCR TEST
CWD JL LEA REP WAIT
DAA JLE LES REPE XCHG
DAS JMP LOCK REPNE XLAT
DB JNA LODSB REPNZ XOR
DEC JNAE LODSW REPZ
DIV JNB LOOP RET
DS JNBE LOOPE RETF
ES JNC LOOPNE ROL
8087 Opcode Mnemonics Recognized by INLINE
F2XM1 FDIVRP FLD FNOP FSTP
FABS FENI FLD1 FNSAVE FSTSW
FADD FFREE FLDCW FNSTCW FSUB
FADDP FIADD FLDENV FNSTENV FSUBP
FBLD FICOM FLDL2E FNSTSW FSUBR
FBSTP FICOMP FLDL2T FPATAN FSUBRP
FCHS FIDIV FLDLG2 FPREM FTST
FCLEX FIDIVR FLDLN2 FPTAN FXAM
FCOM FILD FLDPI FRNDINT FXCH
FCOMP FIMUL FLDZ FRSTOR FXTRACT
FCOMPP FINCSTP FMUL FSAVE FYL2X
FDECSTP FINIT FMULP FSCALE FYL2XP1
FDISI FIST FNCLEX FSQRT FWAIT
FDIV FISTP FNDISI FST
FDIVP FISUB FNENI FSTCW
FDIVR FISUBR FNINIT FSTENV
9