home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-22 | 51.8 KB | 1,345 lines |
-
- TP&Asm Integrated Compile-Time Assembler Version 2.0
- TP&Asm-M Memory Mode Assembly Language Development Tool Version 2.0
-
- Copyright (c) 1989 Richard W. Prescott
- All Rights Reserved
-
- ═══════ Built-In Assembly Language Support for Turbo Pascal Compilers ═══════
-
- All brand and product names mentioned herein are trademarks or registered
- trademarks of their respective holders.
-
- ┌─────────────────────────────────────────────────────────────────────┐
- │ This file contains detailed reference information to enable you to │
- │ make effective use of the TP&Asm assembly environment. For general │
- │ information on getting started please see the file README. │
- └─────────────────────────────────────────────────────────────────────┘
-
-
- The following topics are described below:
-
- 1. Command Line Options
- 2. The Assemble Statement
- 3. The Asm Statement
- 4. The Internal Statement
- 5. General Assembler Syntax
- 6. TP&Asm-specific Options
- 7. Supported Mnemonics
-
-
- The following additional topics are covered in the separate file
- TP&ASM2.REF:
-
- 8. Error Messages
- 9. Trouble Shooting
-
-
-
- 1. Command Line Options
-
- In the following discussion, "TPA(M)" is used in statements that
- apply to both TPA and TPAM.
-
- Use TPA if you have the TP&Asm Integrated Compile-Time Assembler,
- and TPAM if you have the TP&Asm-M Memory Mode Assembly Development
- Tool.
-
- TP&Asm is invoked by typing one of the following lines at the DOS
- prompt:
- TPA(M) <full command line>
- TPA(M) <abbreviation> <options>
- TPA(M)
-
- Full Command Syntax: At the DOS prompt, type
-
- TPA(M) <full command line>
-
- where TPA(M) refers to EITHER TPA or TPAM, and <full command line>
- is any valid command line that could be executed directly from the
- DOS prompt. TP&Asm will load into memory and then execute the
- command line, exactly as if it had been executed by DOS. If a
- supported Turbo Pascal compiler is loaded at any point during the
- execution of the command line, you will see a message indicating
- that the assembler is active, and assembly support will be enabled.
- TP&Asm will not interfere with the operation of other non-compiler
- applications.
-
- Examples: (the following examples apply equally well to TPA and
- TPAM)
-
- TPA mybatch
- run the batch file MYBATCH.BAT which changes directories and
- then runs turbo. Assembly support will be enabled.
-
- TPAM tpc myprog /r"param1 param2"
- run TPC Version 4.0 to compile MYPROG.PAS and run in memory.
- (Please see the Version 4.0 Owner's Handbook for information
- on the /r command line option). Assembly support will be
- enabled.
-
- TPA command
- load a copy of the command processor and return you to the
- DOS prompt. You have just made TP&Asm "Memory resident"!
- Now EACH time you run a supported compiler, you will get a
- message indicating that the assembler is active, and
- assembly support will be enabled. Each time you exit a
- compiler, you will get a message indicating that the
- assembler is inactive. Type EXIT to quit the command
- processor and remove TP&Asm from memory. (You should not
- run any RESIDENT programs from the command shell or you will
- not be able to remove it from memory).
-
- Abbreviated Syntax: At the DOS prompt, type one of the following:
-
- TPA(M) c <options>
- TPA(M) d <full command line>
-
- TPA(M) c <options> is equivalent to: TPA(M) tpc <options>,
- which runs the command line compiler with the specified options.
- Example:
- TPA c myprog (same as: TPA tpc myprog )
- (Please see the Turbo Pascal Owner's Guide for available options).
-
- TPA(M) d <full command line> will run any valid DOS command line
- through debug with assembly support enabled. This is primarily of
- interest to Turbo Version 4.0 users. (Requires DEBUG.COM from
- your DOS disk). Examples:
- TPAM d turbo (same as: TPAM debug turbo.exe )
- TPA d tpc test /r (same as: TPA debug tpc.exe test /r )
-
- NOTE: the recommended method of using any debugger with TP&Asm is to
- run the debugger from TP&Asm:
- TPA(M) <debugger> <parameters required by debugger>
- (Please be thoroughly familiar with the proper operation of your
- debugger before attempting this, since it is definitely possible to
- crash your system through improper use of a debugger. Save your
- work frequently, and be prepared to reboot.)
-
-
- Quick Command Syntax: At the DOS prompt, type
-
- TPA(M)
-
- where TPA(M) refers to EITHER TPA or TPAM. TP&Asm will load into
- memory and then execute TURBO.EXE, exactly as if you had typed
- "turbo" at the DOS prompt. You will see a message indicating that
- the assembler is active, and assembly support will be enabled.
- ( This is the same as executing: TPA(M) TURBO ).
-
-
-
-
- 2. The Assemble Statement
-
- The syntax for the assemble statement is:
-
- Assemble <remainder of line must be empty>
-
- <Standard Assembly language statements>
-
- End
-
- Use of a semicolon ";" after the final "End" is governed by
- standard Pascal statement syntax. Assembly ends with the first
- "End" encountered in the mnemonic field. The entire line is then
- passed on to the compiler, permitting use of an Assemble statement
- in either clause of an "IF .. THEN .. ELSE" conditional statement.
-
- The keyword "Assembly" is permitted as a synonym for "Assemble".
- This is useful to avoid misleading constructions like:
- IF <Pascal Condition> THEN Assemble
- which gives the false impression of conditional assembly. True
- conditional assembly is possible using the PAS statement described
- in the section TP&Asm-specific options. Conditional execution of
- an assembly block is more clearly indicated by:
- IF <Pascal Condition> THEN Assembly
-
- The Assemble statement can be used in any situation where an Inline
- statement would be valid, including in the definition of (Assembly)
- Inline directive/MACROs.
-
- Examples:
-
- {- Conditional execution of assembly code based on runtime value of x: }
- IF x > 0 THEN Assembly
- : <assembly statements>
- End {without semicolon} ELSE Assembly
- : <assembly statements>
- End; {requires semicolon}
-
- {- Define an (Assembly) Inline directive/MACRO: }
- PROCEDURE ClearInterrupts;
- Assemble
- Cli
- End; {MACRO ClearInterrupts}
-
- {- Define a callable procedure with assembly code: }
- PROCEDURE PrintScreen;
- BEGIN
- {- Pascal statements may be placed before ... -}
- Assemble
- Int 5
- End; {Assemble}
- {- ... or after the assembly code -}
- END; {PrintScreen}
-
-
- Assembly sections may be mixed freely with other Pascal statements
- throughout the statement part of a block. Transfer between Pascal
- and assembly sections is freely permitted:
-
- ■ A Pascal label may be specified as the target of any assembly
- Call, Jmp, Loop, or conditional jump. As with the Pascal "Goto"
- statement, the label must be defined in the current block.
-
- ■ An assembly label may be specified as the target of a Pascal
- "Goto" statement. The target label must be declared in a
- standard Pascal "Label" statement. (Assembly labels which are
- referenced only within the current Assemble statement need not
- be declared).
-
- ■ Pascal Procedure and Function identifiers may be specified as
- the target of any assembly Call (or Jmp), or as immediate data
- offsets in assembly data manipulation instructions, eg:
- Mov Dx,PasProc ;load Ofs(PasProc) into Dx
- The Procedure or Function must be defined in the current program
- or in a Unit specified in the Uses clause. Assembly references
- are fully recognized by the Turbo smart linker.
-
- "System" Procedures and Functions do not use true PROC Calls and
- therefore cannot be called from assembly language, either
- directly or indirectly, except using "PAS" as described below.
-
- ■ The assembly keyword "PAS" may be used to insert single or
- multiple line Pascal statements within an assembly section.
- See the section entitled TP&Asm-specific options.
-
- As with the Inline statement, the registers BP, SP, SS, and DS
- should be restored before execution of any Pascal statements,
- including Procedure calls and "PAS" statements.
-
- Please see the numerous .PAS files on the distribution disk
- (archive TP-ASM.ZIP, available on CompUServe) for additional
- examples of Assemble statement usage.
-
-
- 3. The Asm Statement
-
- Situations that require only a single line of assembly code
- may be more concisely specified using an "Asm" statement. The
- keyword "Asm" is used to instruct the compiler that the remainder
- of the current line is to be interpreted as an assembly language
- statement, and that the following line is to be interpreted as a
- Pascal statement.
-
- As with the Assemble statement, the use of a semicolon ";" is
- governed by standard Pascal statement syntax, permitting use of
- an Asm statement in either clause of an "IF .. THEN .. ELSE"
- conditional statement.
-
- The Asm statement can be used in any situation where an Inline
- statement would be valid, including in the definition of (Assembly)
- Inline directive/MACROs.
-
- Examples:
-
- {- Single line assembly code in Pascal conditional statement: }
- IF x > 0 THEN Asm Push PasVar1
- ELSE Asm Push PasVar2; {comment permitted here}
-
- {- Define an (Assembly) Inline directive/MACRO: }
- PROCEDURE ClearInterrupts; Asm Cli;
-
- {- Define a callable procedure with assembly code: }
- PROCEDURE PrintScreen;
- BEGIN
- {- Pascal statements may be placed before ... -}
- Asm Int 5;
- {- ... or after the assembly code -}
- END; {PrintScreen}
-
-
-
- 4. The Internal Statement
-
- The Internal statement is intended as a convenient mechanism for
- moving working External assembly code into your program, or for
- developing assembly code intended for final compilation with an
- external assembler. (Note however that the Assemble statement
- provides an equally powerful mechanism for using assembly language
- which has fewer limitations and is considerably easier to use,
- allowing, for example, direct reference to procedure and function
- parameters by name).
-
- First, please refer to the Version 4 Owner's Handbook or Version 5
- Reference Guide for the syntax for using EXTERNAL programs. The
- following discussion assumes you are converting an existing EXTERNAL
- program to INTERNAL.
-
- For Internal Proc/Functions defined in a PROGRAM, the following
- changes are required:
-
- 1) Remove or comment out the Link directive {$L ...}
- Internal Proc/Functions are automatically linked by the Turbo
- smart linker, with dead code removal on a Proc by Proc basis.
-
- 2) Replace the word "External" with "Forward" in the
- Proc/Function heading.
-
- 3) The Internal statement should be placed somewhere following
- the forward declaration and before the PROGRAM "BEGIN" block.
-
- For Internal Proc/Functions defined in a UNIT, the following
- changes are required within the IMPLEMENTATION section:
-
- 1) Remove or comment out the Link directive {$L ...}
- Internal Proc/Functions are automatically linked by the Turbo
- smart linker, with dead code removal on a Proc by Proc basis.
-
- 2a) For PRIVATE Proc/Functions which are defined only in the
- implementation section, replace the word "External" with
- "Forward" in the Proc/Function heading.
-
- 2b) For PUBLIC Proc/Functions which are defined in the interface
- section, remove or comment out the entire Proc/Function
- heading in the implementation section.
-
- 3) The Internal statement should be placed in the implementation
- section somewhere following the forward declaration (if present)
- and before the Unit "BEGIN" block (if present).
-
- Ths syntax required in the INTERFACE section of a Unit is the same
- as for External.
-
- The full syntax for the Internal statement is given below.
-
- Examples:
-
- {- The following code section implements an Internal PROC in a -}
- {- PROGRAM or as a PRIVATE Proc in a Unit IMPLEMENTATION section. -}
-
- PROCEDURE PrintScreen; Forward;
-
- Internal Print
- CODE Segment
- PrintScreen PROC NEAR
- Int 5
- Ret
- PrintScreen ENDP
- CODE ENDS
- END
-
- BEGIN {MAIN program or UNIT initialization}
- PrintScreen;
- END.
-
- {- The following code defines a unit with a single public PROC -}
- {- which is implemented using an Internal statement. -}
-
- Unit PrtScr;
- interface
- PROCEDURE PrintScreen;
-
- implementation
- Internal Print
- CODE Segment
- PrintScreen PROC FAR
- Int 5
- Ret
- PrintScreen ENDP
- CODE ENDS
- END
-
- END. {Unit PrtScr}
-
-
-
- The following syntax description is admittedly somewhat obtuse;
- It is intended to be read in the context of a working External
- procedure or function. (Most external assembly code written for
- Turbo Versions 4.0 or 5.0 should already match this syntax).
-
- The syntax for the Internal statement is:
-
- Internal <DataName> <remainder of line must be empty>
-
- Data Segment <options (ignored)> \
- <data allocation and EXTRN statements> > optional
- Data ENDS /
-
- Code Segment <options (ignored)>
- <optional assembler overhead statements (ignored)>
-
- <ProcName1> PROC <optional Near/Far specification>
- <Standard Assembly language statements>
- <MUST include at least one "RET <ParamSize>">
- <ProcName1> EndP
-
- <additional PROC/ENDP sections> > optional
-
- Code ENDS
-
- END <optional text (ignored)>
-
- (Note: "DataName" must not duplicate any other Pascal identifier
- used in your program).
-
- Please Note: assembly ends with the first "End" encountered in the
- mnemonic field. Everything to the right of "End" is ignored, and
- the next line will be treated as the start of a new Pascal
- statement.
-
- It is the programmer's responsibility to insure that the assembly
- code matches the syntax required for external assembly code for the
- particular compiler version being used, with the following
- exception:
-
- All GLOBAL Pascal identifiers that have been defined prior to the
- Internal statement may be referenced by name, without the need
- for an EXTRN statement. (TP&Asm ignores all EXTRN statements).
- This includes references involving UnitName and record component
- qualifiers, which are not permitted in EXTERNAL routines.
-
- In particular, the programmer must insure that parameters and
- function results are correctly referenced relative to a properly
- initialized base or index register, and that parameters and/or
- function results are removed from the stack on exit as required by
- the particular compiler version being used. Again, this should
- automatically be true for working external code designed for that
- compiler version.
-
- Please see the file INTERNAL.PAS on the distribution disk for
- an example of an Internal statement which contains assembly code
- for both a Procedure and a Function.
-
-
- Note:
- In prior versions of TP&Asm each Internal PROC was implemented as
- a standard Pascal Procedure or Function, with additional code added
- as necessary to reverse the effects of the standard Procedure entry
- code. Beginning with Release 2, TP&Asm builds Internal PROCs with
- no entry or exit code. (In the examples above, for example, the
- procedure PrintScreen will consist of precisely 3 bytes of code).
-
-
-
-
- 5. General Assembler Syntax
-
- This section is NOT intended to be an assembly language tutorial.
- It contains only a few brief notes intended to compare TP&Asm
- syntax requirements with the requirements of other assemblers you
- may own or be familiar with.
-
- Because of its quick feedback and ability to freely mix Pascal and
- Assembly statements, TP&Asm is an excellent tool to use in learning
- Assembly language. Please, however, plan to obtain a separate
- tutorial or reference on the use of 8086/88 Assembly language.
-
- The assembler I use and recommend for stand-alone and/or linkable
- assembly language program/modules is A86, a full featured shareware
- assembler written by Eric Isaacson. It comes complete with a very
- nice reference manual on disk, which, together with a few working
- sample programs, MAY be all you need to learn the basics of assembly
- language programming.
-
-
- General notes:
-
- The basic syntax of a TP&Asm assembly statement is:
-
- <optional label> <mnemonic> <operands> <optional comment>
-
- These language elements can be upper or lower (or mixed) case, and
- may be placed in any position on the line, separated from each
- other by at least one space or tab.
-
- The comment, if present, must begin with a semicolon and extends to
- the end of the line. TP&Asm ignores everything following the
- semicolon, except as noted below under TP&Asm-specific options.
-
- The label, if present, must not duplicate any Pascal identifier
- used in your program, and must be unique from other labels used in
- the same assemble statement, with the following exception: For
- compatibility with A86, labels which consist of a single letter
- followed by any number of decimal digits (L1, P253, etc) are
- considered to be "Local labels" which may be redefined and reused.
- Code labels must end with a colon, except for PROC statements, in
- which a colon is optional. Data labels must not end with a colon.
-
- The mnemonic can be any standard 8086 mnemonic, optionally prefixed
- by one of the following:
-
- LOCK
- A segment override: Cs, Ds, Es, or Ss
- A string repeat prefix: Rep, RepZ, RepNZ, RepE, or RepNE
-
- Use of a colon after the prefix is optional. Prefixes may be
- placed on the preceding line, if desired. It is generally an error
- to specify more than one prefix for the same instruction (in the
- sense that the processor may not do what you intended), however
- TP&Asm supports all combinations of one segment override with one
- string prefix, by converting the combination to a loop as
- illustrated below:
-
- RepE Cs Movsb is converted to L0: Cs Movsb
- LoopE L0
-
- which moves bytes from Cs:[Si] to Es:[Di]. (If the loop technique
- is not used, "RepE Cs Movsb" may not repeat, and "Cs RepE Movsb"
- may take the first byte from Cs:[Si], and subsequent bytes from the
- default Ds:[Si] - probably not what you intended). Note that the
- default (Es) DESTINATION segment for string operations cannot be
- overridden - this is a requirement of the processor, not TP&Asm.
-
- A full list of supported mnemonics is provided below. The file
- USAGE.PAS contains one or more examples of correct usage of each
- of the supported mnemonics.
-
-
- Operands refers to any operands required by the mnemonic, separated
- by commas. Either source or destination operand may be prefixed by
- a segment override, where again, use of a colon is optional:
-
- Mov Ax,Es:[Di]
-
- If the size of the operand (Byte, Word, or DWord) is not known to
- the assembler, or if you wish to use an operand differently than it
- was defined, you must place one of the following size specifiers
- before the operand (specifiers on the same line are synonyms):
-
- B Byte Ptr
- W Word Ptr
- D DWord Ptr
-
- Examples:
-
- Mov Ax,ByteVar ; Syntax error if you defined VAR ByteVar: BYTE;
- Mov Ax,W ByteVar ; Load Ax with two bytes beginning with ByteVar
- Mov W Ax,ByteVar ; Same as above, overrides original definition
-
-
- The following conventions apply regarding numeric operands:
-
- As with other assemblers, all numbers must begin with a DECIMAL
- digit. (Thus Ch is a register, and 0Ch is a hexidecimal number).
-
- For compatibility with A86, all numbers that begin with "0" are
- assumed to be hexidecimal, whether or not there is a trailing
- "h". (Use Radix 10 to disable this assumption in the current
- assemble/internal statement).
-
- For compatibility with INLINE.COM, all numbers that begin with
- "$" are hexidecimal (and should NOT have a trailing "h").
-
- The Radix (or .Radix) statement may be used to specify the
- default base for numbers which would otherwise be ambiguous,
- namely, decimal digits without leading "$" or trailing "H".
- Use "Radix 10" to specify decimal, "Radix 16" for hexidecimal,
- and "Radix" to return to the default (leading 0 hexidecimal,
- otherwise decimal).
-
- TP&Asm does not support binary numeric operands. Please convert
- Binary operands to Hexidecimal.
-
- TP&Asm supports 4-function arithmetic on immediate (constant,
- NON-Data) operands, plus BIT and BY for compatability with A86.
- Standard order of evaluation applies, but may be overridden
- through the use of parentheses:
-
- Mov Al,2+3*6 ; same as Mov Al,20 (evaluate 3*6 first)
- Mov Al,(2+3)*6 ; same as Mov Al,30 (evaluate 2+3 first)
-
-
- Notes on Use of Offsets and SEG DATA as numeric operands:
-
- Within the FIRST code block of a Program or Unit, the offset of
- any assembly code or data label may be used in any instruction
- which requires immediate data:
-
- Mov Ax,Offset AssemblyDataLabel
- Sub Bx,AssemblyCodeLabel
-
- References to assembly Code labels refer to the OFFSET of the
- labeled instruction within the current code segment. The modifier
- "Offset" is not required. References to Data labels refer to the
- CONTENTS of the labeled location unless preceded by the modifier
- "Offset".
-
- If the first code block is a CsData statement as described in the
- section TP&Asm-specific Options, the Contents or Offset of any
- CsData Data label may be referenced in any subsequent Procedure
- or Function, as well as in the main Program or Unit BEGIN block:
-
- Cmp Bx,Offset CsDataLabel
-
- Reference to Pascal LABEL Offsets is not permitted.
-
- Throughout each Program or Unit, the offset of any Pascal
- Procedure, Function, or Variable may be used in any instruction
- which requires immediate data, with the following exceptions:
-
- 1) Byte references to Pascal Offsets are not permitted. For
- example, "Mov Al,Offset PascalSymbol" is not permitted even
- if Ofs(PascalSymbol) is in [0..127].
-
- 2) "Offset PascalSymbol" is not permitted as immediate data
- when the Destination operand is a Pascal Variable. For
- example, "Add PascalVariable,Offset PascalSymbol" is not
- permitted. The following technique must be used:
-
- Mov Reg,Offset PascalSymbol
- Add PascalVariable,Reg
-
- References to Pascal Procedure and Function identifiers refer to
- the OFFSET of the Proc/Function within its code segment (except
- when SETTING Function Results as described below). The modifier
- "Offset" is not required. References to Pascal VAR and (Typed)
- CONST identifiers refer to the CONTENTS of the Data Segment
- location unless preceded by the modifier "Offset":
-
- Mov Ax,Offset PascalVariable
- Dw PascalProcedure,PascalFunction
-
- The construct "SEG DATA" may be used in any assembly instruction
- which requires immediate data, with the exceptions that Byte
- references to "SEG DATA" are not permitted. For example, to
- restore the Turbo DS within a customized interrupt routine:
-
- Mov Ax,SEG DATA
- Mov Ds,Ax
-
-
- Notes on Absolute Code Segment References:
-
- TP&Asm permits assembly data to be freely allocated and referenced
- throughout the FIRST code block in each Program or Unit (that is,
- the FIRST true Procedure or Function in a Program or Unit, or the
- main BEGIN block of a Program or Unit with no Procedures or
- Functions defined). Data labels are retained in the symbol table
- throughout the first code block so that all assembly sections can
- reference the allocated data. This data is considered local to
- the first code block and is not available to subsequent Procedures
- and Functions.
-
- Since Turbo Versions 4 and 5 use "smart linking", it is generally
- not possible to accurately specify the location of any but the
- FIRST Proc/Function in a Program or Unit. For that reason, TP&Asm
- does not permit reference to assembly Data allocated in subsequent
- Procedures or Functions. Attempts to do so will result in the
- error "Invalid Absolute CSeg Reference".
-
- Use of assembly data definition is seldom necessary, and should
- generally be avoided in favor of using Pascal data defined via
- VAR or (Typed) CONST statements.
-
- The files DEMONEW.PAS and DOSEXEC.PAS in the archive TPA2-A.ARC
- contains examples using data allocated in the first Procedure of
- a Program.
-
-
- Notes on Forward References in Data Manipulation Instructions:
-
- TP&Asm is somewhat restrictive regarding the use of forward
- references in Data Transfer, Arithmetic, and Logic instructions
- (as opposed to Control Transfer instructions). In particular:
-
- All Pascal identifiers used as operands must be defined PRIOR
- TO the current Assemble or Internal statement. (This is
- consistent with the standard Pascal requirement that all
- identifiers be defined).
-
- The Internal DATA SEGMENT section, if present, must preceed the
- CODE SEGMENT section.
-
- FORWARD reference to assembly Data labels is not permitted. (All
- data definitions must be placed PRIOR TO the first reference).
- This is not really a restriction for assembly language within a
- Pascal program. The only reason you might be tempted to have data
- at the end of your assembly code is to reduce the size of the
- compiled program by placing buffers and other uninitialized data
- after the last Code statement. Since your last assembly statement
- can never be assumed to be the last code statement in your Pascal
- program, this is simply not allowed. Instead, define
- uninitialized data in Pascal:
- Var Buffer: ARRAY[1..20000] OF BYTE;
-
- Forward reference to CODE labels in the FIRST code block of a
- Program or Unit is permitted. For example:
-
- Add Ax,ForwardLabel - $
-
- is permitted within the FIRST true Procedure or Function in
- a Program or Unit.
-
-
- Notes on Operands to Control Transfer Statements:
-
- Control Transfer statements include the unconditional Jmp and
- Call, and the conditional Jumps (jZ, jPE, jCXZ, etc) and Loops
- (Loop, LoopNE, etc). The operand to a Direct control transfer
- statement must be a SINGLE symbol name which is either:
-
- 1) an assembly code label (including PROCs) within the current
- Assemble statement (or the current major PROC of the current
- Internal statement),
- 2) a Pascal LABEL within the current block, or
- 3) (for Call and Jmp only) a Pascal or Internal Procedure or
- Function Identifier.
-
- The operand to an Indirect control transfer statement may be any
- valid register or memory expression of the appropriate (Word or
- DWord) size.
-
- The JMP modifiers "Short" and "Long" (as used by A86) are
- permitted but are ignored. TP&Asm performs automatic minimum
- Jump-Sizing for all backward AND FORWARD Jumps and Loops (Jmp,
- jZ, jAE, jCXZ, Loop, LoopNZ, etc) within the current code block.
- A 3-, 5-, or 7-byte instruction sequence will automatically be
- generated if the target label is not within range of a 2 byte
- instruction.
-
- This includes automatic shortening of unconditional jumps:
-
- Jmp CloseBy .. becomes .. Jmp Short CloseBy ;2 bytes
-
- Automatic 5 byte "IF <Cond> Jmp" for backward AND FORWARD
- conditional jumps out of range:
-
- jNZ FarAway .. becomes .. jZ >L0 ;2 bytes
- Jmp FarAway ;3 bytes
- L0:
-
- And automatic 7 byte instruction sequences for backward AND
- FORWARD jCXZ & Loop's out of range:
-
- Loop FarAway .. becomes .. Loop >L0 ;2 bytes
- Jmp Short >L1 ;2 bytes
- L0: Jmp FarAway ;3 bytes
- L1:
-
- Note that TP&Asm does NOT pad forward jumps with NOP instructions,
- but rather always builds the smallest possible instruction.
-
- The automatic Jump-Sizing feature is not enabled in (Assembly)
- Inline Directive/MACROs. As described in the Turbo 4.0 and 5.0
- manuals, Inline Directives are intended for short sections of code
- which are unlikely to exceed 127 bytes. TP&Asm generates an error
- if a conditional jump out of range is attempted in an (Assembly)
- Inline Directive/MACRO.
-
- Pascal Proc/Functions can be called from assembly language using
- direct or indirect calls: "Call PasProc" will generate:
-
- 1) a NEAR Direct call if PasProc is a Procedure or Function
- defined in the CURRENT Program or implementation section in
- the {$F-} state.
- 2) a FAR Direct call if PasProc is a Procedure or Function
- defined in another Unit or in the CURRENT Program or
- implementation section in the {$F+} state.
- 3) a NEAR Indirect call if PasProc is a Word (Integer) Variable.
- PasProc must be initialized with the Ofs of a NEAR {$F-}
- Procedure or Function in the CURRENT Program or Unit.
- 4) a FAR Indirect call if PasProc is a Pointer or Procedure
- Variable. PasProc must be initialized with the Addr of a
- FAR {$F+} Procedure or Function.
-
- The default action in (3) may be overridden using the FAR
- modifier: "Call Far PasProc" will generate:
-
- 3b) a FAR Indirect call if PasProc is any Pascal Variable.
- MemL[DSeg:Ofs(PasProc)] must be initialized with the Addr
- of a FAR {$F+} Procedure or Function.
-
- The default action in (4) may be overridden using the NEAR
- modifier: "Call Near PasProc" will generate:
-
- 4b) a NEAR Indirect call if PasProc is any Pascal Variable.
- MemW[DSeg:Ofs(PasProc)] must be initialized with the Ofs of
- a NEAR {$F-} Procedure or Function in the CURRENT Program
- or Unit.
-
- The default actions in (1) and (2) may not be overridden, as
- this would always result in a mismatch between the Call and Ret
- instructions.
-
- For completeness, TP&Asm permits an unconditional JMP to a Pascal
- Procedure or Function. This would be useful only in very obscure
- situations, and should otherwise be avoided. A 3-byte Near jump
- or 5 byte Far jump is built, as necessary. The modifier "Short",
- if present, is ignored, since the Turbo linker does not permit
- Byte references.
-
-
- Notes on setting Function Results:
-
- To facilitate the setting of Pascal function results within
- assembly sections, Pascal Function identifiers of any simple TYPE
- can be specified as the Destination operand of a MOV instruction:
-
- Mov ByteFunction,Al - OR - Mov PointerFunction,Ax
- Mov PointerFunction+2,Dx
-
- The Function identifier should be thought of as representing a
- local variable of the appropriate size which is stored in the
- Stack segment and accessed relative to the Bp register. As with
- all local variables, the explicit specification of the [Bp] is
- not required.
-
- Pascal String Function identifiers can be specified as the Source
- operand in a Load Pointer (Les/Lds) instruction:
-
- Les Di,StringFunction ; Load Pointer to temporary storage area
- Es Mov [Di],Cl ; Put in Result Length
- Inc Di ; Point past length byte
- Rep MovSB ; Put in String
-
- String Function identifiers refer to the local Pointer Variable
- which is pushed on the stack by the Calling procedure and which
- references the temporary storage location established by the
- Caller.
-
- You should not attempt to set a Function result from within a
- nested sub-procedure.
-
-
- Notes on use of Qualified Identifier Syntax:
-
- TP&Asm supports the full qualified identifier syntax including
- both UnitName and record component qualifiers, for example:
-
- Test Ax,DOS.FZero
- Cmp Ax,UnitX.RecVar.NestRec.IntegerComponent
-
- UnitName qualifiers must be defined in a "Program" or "Unit"
- statement. (The symbol "PROGRAM" is not a valid qualifier).
-
- Embedded spaces are not permitted, so that the following would
- generate syntax errors:
-
- Test Ax,DOS. FZero
- Cmp Ax,UnitX.RecVar. NestRec.IntegerComponent
-
- Following a valid UnitName qualifier, the subsequent search
- is limited to PASCAL identifiers in the given unit. Likewise,
- following a valid record variable with a trailing ".", the
- subsequent search is limited to record components associated
- with that variable. This duplicates the compiler's symbol
- search strategy, and permits references to record components
- which duplicate assembly variables and reserved symbols.
- Thus, if RegVar is of TYPE Registers (from the DOS unit), the
- following is permitted:
-
- Mov Ax,RegVar.Ax ;- ( ">" or "<" not required )
-
- (If you wish to specify a record variable offset which is not
- a valid component name, including Pascal and assembly constants,
- use "+" in place of ".". Thus, if PasConst = 4 and AsmSym EQU 4,
- the following statements are all equivalent:
-
- Add Ax,RegVar.Cx
- Add Ax,RegVar+AsmSym
- Add Ax,RegVar+PasConst ;
-
- whereas "Add Ax,RegVar.PasConst" would generate a syntax error).
-
- The symbolic value of a record ComponentName is the numeric
- offset of that component from the beginning of the record. To
- reference this value irrespective of any record variable, you
- must prefix the ComponentName with a TypeDef qualifier. For
- example, "Add Di,DateTime.Hour" is the same as "Add Di,6",
- because 3 Integers (and hence 6 bytes) preceed Hour within the
- record type DateTime. Use of TypeDef qualifiers permits assembly
- reference to Dynamic record variables. For example, to refer
- to RecPtr^.ComponentX, where RecPtr is a VAR of TYPE ^RecType:
-
- Les Di,RecPtr ; Load Pointer into Es:Di
- Es Mov Ax,[Di]RecType.ComponentX ; apply ComponentName offset
-
- Note also that within a given Assemble/Internal statement, you can
- define assembly equates, permitting references like the following:
-
- AsmPtr EQU W Es [Di]
- :
- Les Di,RecPtr ; Load Pointer into Es:Di
- Mov Ax,AsmPtr.RecType.ComponentX ; apply ComponentName offset
-
- Reference to a ComponentName without a Record Variable or Record
- Type qualifier is not permitted.
-
-
- The following additional notes regarding operands apply:
-
- Pascal identifiers used as operands may optionally be prefixed
- by "<" or ">". This is primarily for compatability with Dave
- Baldwin's INLINE.COM, but also serves one other purpose: it
- allows you to refer to Pascal identifiers which duplicate
- assembler reserved symbols. Thus:
-
- Mov Al,Ch ; Places contents of Ch register into Al
- Mov Al,>Ch ; Places value of Pascal variable Ch into Al
- Mov Al,Ch1 ; Ch1 is not reserved - no ">" or "<" required
-
- For compatability with A86, "Local labels" (described above) used
- as operands may be prefixed by ">" to force a forward jmp when
- there is a prior definition:
-
- jNE L0 ; Backward jump if already defined (otherwise forward)
- jNE >L0 ; Forward jump even if there is a prior definition
-
-
-
-
- Notes for users of A86, by Eric Isaacson:
-
- Multiple operands to Push, Pop, Inc, and Dec are supported.
- Segment overrides can be specified for each operand:
- Push [Si],Es:[Di],[Bx] ; uses default Ds for [Si] and [Bx]
- Or a single segment override can be specified for all operands:
- Es Push [Bx+2],[Bx] ; uses Es override for both operands
-
- The final numeric operand to Inc and Dec is not supported.
- Inc Ax,3 ; will a generate syntax error
- Add Ax,3 ; use this instead
-
- The IF statement is supported, including "IF NCXZ" (for whatever
- it's worth).
-
- Local labels are supported, as described above. A local label
- which is never redefined does not require a ">" for forward
- references.
-
- Conditional Returns, Extensions to MOV, Operands to AAD/AAM, and
- Single-Operand TEST's are not supported.
-
-
-
- Notes for users of MicroSoft's MASM:
-
- TP&Asm supports the basic syntax used by the MicroSoft Macro
- Assembler, at least, to the best of my ability to determine that
- by studying assembly programs designed for MASM. If you discover
- any incompatabilities with commonly used MASM syntax, please let
- me know.
-
- TP&Asm supports a number of extensions for compatability with
- Eric Isaacson's A86 assembler, including multiple operands to
- Push, Pop, Inc, and Dec, Reusable local labels, and convenient
- abbreviations for Word Ptr, Byte Ptr, etc. (described above under
- General Notes). The following compatability extension has not
- yet been described:
-
- IF <condition> <statement> : the single statement specified
- will execute if the condition holds at runtime. Valid
- conditions are those for which there is a conditional jump
- instruction for the OPPOSITE condition. ("IF NCXZ" is allowed;
- "IF CXZ" is not allowed since there is no jNCXZ instruction).
-
- Example:
- jZ L1
- IF NZ Mov Result,FALSE ; same as --> Mov Result,FALSE
- L1:
-
-
- Notes for users of INLINE.COM, by Dave Baldwin:
-
- As noted above, TP&Asm permits the use of "$" as a hexidecimal
- specifier, and allows (but does not require) ">" or "<" to be
- used as a prefix to Pascal identifiers. These were features of
- the INLINE.COM version I have seen, and may or may not be
- required in the current version.
-
- TP&Asm does not permit the use of BY, WO, and DW as abbreviations
- for Byte Ptr, Word Ptr, and DWord Ptr. (BY and DW are reserved
- by the assembler for other purposes). Use the unabbreviated
- forms, or the abbreviations B, W, and D.
-
- Please see the MASM user's notes for a description of the IF
- statement, not described under General Notes.
-
-
-
-
- 6. TP&Asm-specific Options
-
- This section describes certain features that are unique to the
- TP&Asm/TP&Asm-M assembler.
-
-
- The Pas Statement
-
- TP&Asm provides the assembly keyword "Pas" for inserting single
- or multiple line Pascal statements within an assembly section.
- This may be used as an alternative to:
- 1) breaking the Assemble section into two or more blocks, and
- 2) defining the target of any jumps which cross the Pascal code
- in a Pascal Label statement.
-
- To include one or more lines of Pascal statement(s) within an
- assemble statement, simply precede each line with the prefix
- "Pas".
-
- Pascal statements may modify any of the following registers:
- Ax, Bx, Cx, Dx, Di, Si, and Es
- Your assembly code should save and restore these registers as
- needed.
-
- Example:
-
- Assemble
- :
- jNZ TargetLabel1
- :
- jAE TargetLabel2
- :
- Push Ax,Cx ;preserve registers Ax and Cx
- Pas BlockRead(InFile,Buffer,SizeOf(Buffer),BytesRead);
- Pop Cx,Ax
- TargetLabel2:
- :
- TargetLabel1:
- :
- End; {Assemble}
-
-
- The Pas statement may be used to implement conditional assembly as
- shown in the following example:
-
- Assemble
- :
- Pas {$IFDEF VER50}
- Call DosVersion ;This will assemble if VER50 is defined
- Pas {$ELSE}
- Mov Ah,30h ;This will assemble
- Int 21h ; if VER50 is NOT defined
- Pas {$ENDIF}
- Cmp Al,3
- :
- End; {Assemble}
-
- Internal PROCs do not generate the standard Pascal procedure entry
- code and therefore cannot safely execute Pascal statements. For
- this reason, the Pas statement is not permitted in an Internal
- block.
-
-
- The CsData Statement
-
- Beginning with version 4, Turbo Pascal Typed Constants are no
- longer stored in the Code segment. This change was required, among
- other reasons, because of the fact that Version 4 programs can have
- multiple Code segments. Nonetheless, in certain very specific
- situations, it is useful to be able to place named data in the
- current Code segment. As described in the preceding section, TP&Asm
- permits the allocation of Local data in the Code Segment within the
- FIRST code block in any Program or Unit.
-
- TP&Asm also permits the allocation of Global data in the current
- Code Segment in a block beginning with the keyword "CsData". The
- CsData statement must be the FIRST Code block in the current Program
- or Unit. The syntax for the CsData statement is as follows:
-
- CsData {remainder of line may contain a comment}
- :
- <Db, Dw, and/or Dd statements>
- :
- End; {semicolon is required}
-
- The CsData block is implemented as a "Procedure" with no executable
- code, beginning at offset 0 within the current code segment. All
- references to the first data label (at offset 0) are passed to the
- Turbo smart linker to insure inclusion of the entire CsData block in
- the final compiled code. Since the Turbo linker does not permit
- nonzero offset references to Pascal Procedures and Functions,
- references to subsequent data labels are processed directly and not
- passed to the linker. It is therefore essential that some reference
- be made to the first data label if reference is made to any CsData
- labels. Simply order the data so that an unused data label is not
- placed first in the CsData block, or force inclusion of the CsData
- block with a statement of the form
- "Mov Ax,FirstDataLabel"
-
- The Unit DOS21_0A.PAS in the archive TP-TSR contains an example
- of the CsData statement. It is used to implement a customized
- interrupt procedure which can chain to the original interrupt vector
- rather than IRET to the calling program. To permit this, the
- original value of the interrupt vector must be stored in the Code
- Segment so that ALL registers may be restored before issuing an
- indirect "Jmp OldVector" via the stored address. (Addresses stored
- in the Data Segment are not accessible after Ds is restored).
-
-
-
- TP&Asm Directives
-
- TP&Asm Directives provide a mechanism for modifying the following
- characteristics of the assembler:
-
- Use of Presumptions
- Treatment of Warning Errors
-
- These modifications will remain in effect for the duration of the
- current Assemble/Internal statement OR until reset by another
- TP&Asm directive. The combination <semicolon><sharp>, as in ";#",
- is reserved by TP&Asm to indicate the beginning of a TP&Asm
- directive. The semicolon must be the first non-blank character
- on the line.
-
- Use of Presumptions.
-
- ;#P+ Enable Presumptions (default)
- ;#P- Disable Presumptions
-
- TP&Asm keeps track of any Segment Overrides and/or Base register
- specifications necessary to reference your Pascal and Assembly
- variables. With presumptions enabled, these segment and base
- specifications are automatically provided if you choose to omit them
- in your data reference. Thus you may use
-
- Mov Ax,LocalVar ; - OR -
- Mov Ax,LocalVar[Bp] ; Full Specification
-
- if LocalVar is a Local Pascal variable in the current Proc/Function;
-
- If CSegVar is an assembly variable in CsData block, (see above),
- then you could use any of the following
-
- Mov Ax,CSegVar
- Mov Ax,Cs CSegVar ; Full Specification - OR -
- Cs Mov Ax,CSegVar ; Full Specification
-
- to reference CSegVar. In each case TP&Asm assembles the full
- specification. Using presumptions allows you to make most
- references to Pascal and Assembly variables just as you do in
- Pascal, without worrying about where the compiler stores these
- variables. The resulting assembly code has the form that would
- be used in a straightforward ("tiny model") assembly program with
- all data accessible from the Ds register. Note that ASSUME
- statements are unnecessary, and are ignored by TP&Asm.
-
- The Directive ";#P-" allows you to disable presumptions in
- situations where you believe the default specification is not
- correct, or if you just don't feel comfortable with the idea that
- the assembler is providing these specifications 'behind your back'.
- When presumptions are disabled you must use the full specifications
- as indicated in the examples above.
-
- You should seldom find it necessary to disable presumptions,
- however there are two situations that warrant closer attention.
- The first applies to string operations (Movsb, Cmpsw, etc), and
- the second applies to users who want to refer to Local variables
- which are not in the current Proc/Function.
-
- For String operations you must of course properly initialize the Es
- register to the segment of the destination string. In addition,
- the assembler must determine if a segment override is necessary in
- connection with the source address in the Si register. If Si is
- loaded with an Lds instruction:
-
- Lds Si,MemoryReference
-
- then TP&Asm will assume the Ds register is properly initialized
- and will not provide a segment override.
-
- If Si is loaded in one of the following fashions:
-
- Lea Si,VarName ; - OR -
- Mov Si,Offset VarName
-
- and Si is NOT MODIFIED before being used in a String operation, then
- TP&Asm will automatically provide any necessary override. Si is
- considered to have been modified by any instruction which has Si as
- DESTINATION operand, with the following exceptions:
- Test, Cmp, Inc, and Dec
- (The first two do not modify their operands. With the second two,
- TP&Asm makes the reasonable assumption that the segment associated
- with the Source address in Si should not change as a result of an
- Increment/Decrement operation).
-
- Example:
-
- Xor Ch,Ch
- Lea Si,LocalStringVar ; Local Pascal VARs are stored on the Stack
- Lodsb ; TP&Asm supplies Ss override
- Mov Cl,Al
- Rep Movsb ; TP&Asm supplies Ss override and
- ; converts double prefix to LOOP
- Add Si,Bx ; SI HAS BEEN MODIFIED
- ;- You have placed an address in Si for which it is impossible
- ;- for the assembler to Presume the proper segment
- ;- TP&Asm assumes you know what you're doing, and therefore
- ;- SUPPLIES NO OVERRIDE (Source will use the default Ds register),
- ;- but generates a Warning Error IF WARNINGS ARE ENABLED
- Cmpsb ; TP&Asm supplies no override
-
-
- You may determine if the assembler is providing a segment override
- using ASMWATCH with Turbo 5.0. The watch expression "CPU.CsIp^,m"
- displays a hex dump beginning at current instruction. If the first
- byte of a repeated or non-repeated string instruction is $36 or $2E,
- an override is being provided.
-
-
- To reiterate, with respect to string operations with
- Presumptions Enabled:
-
- 1) you must properly initialize the Es and Di Registers
- 2a) Load Ds and Si using Lds:
- Lds Si,MemoryReference
- - OR -
- 2b) Load Si only, using one of the following:
- Lea Si,VarName ; - OR -
- Mov Si,Offset VarName
- 3) Subsequent statements SHOULD NOT MODIFY Si, until
- AFTER the string operation
- 4) you must restore Ds if it was modified
-
- Or, with Presumptions Disabled:
-
- 1) you must properly initialize Es, Di, and Si
- 2) If the source string is not in the Data Segment, you must
- either set Ds to the segment of the Source string, or use
- an explicit segment override with the string mnemonic
- 3) you must restore Ds if it was modified
-
-
- To reference LOCAL variables which are NOT in the current Procedure
- or Function, the preferred method is to define a local variable in
- the current Proc/Function and use Pascal as follows:
-
- PROCEDURE Outer;
- VAR SomewhatLocalVar;
-
- PROCEDURE Inner;
- VAR LocalVar;
- BEGIN
- {- if assembly code USES the value of SomewhatLocalVar: -}
- LocalVar := SomewhatLocalVar;
- Assemble
- < use LocalVar in place of SomewhatLocalVar >
- End; {Assemble}
- {- if assembly code needs to MODIFY SomewhatLocalVar: -}
- SomewhatLocalVar := LocalVar;
- <etc>
-
- With Turbo Versions 4 & 5 it is possible to make assembly references
- to Local variables which are NOT in the current Proc/Function,
- however: you will need to disable presumptions, properly initialize
- the Bx register, and provide the full specification:
-
- ;#P-
- Mov Bx,[Bp+4] ; Initialize Bx to Caller's Stack Frame
- Ss Mov Ax,SomewhatLocalVar[Bx]
- ;#P+
-
-
- Treatment of Warning Errors.
-
- ;#W+ Halt on Warnings
- ;#W- Ignore Warnings (default)
-
- TP&Asm performs an extensive set of syntax checks on your assembly
- code (including many that can only be detected at compile time), and
- reports any such error on the standard compiler error line, with the
- cursor placed on the line that caused the error. The full list of
- standard error messages is provided in the file TP&ASM2.REF.
-
- In addition to these standard error messages there is a small set of
- warning error messages, mostly having to do with possible errors in
- the use of segment overrides, that will be generated only when
- Warnings are enabled. Warnings are normally disabled so as not to
- interfere with (possibly) valid instructions. Use the directive
- ";#w+" to enable warnings and ";#w-" to disable them again.
-
- The warning error messages are also listed, with brief explanations,
- in the file TP&ASM2.REF.
-
-
-
-
- 7. Supported Mnemonics
-
- TP&Asm supports the following 8086 mnemonics and data definition
- directives:
-
- AAA AAD AAM AAS ADC ADD
- AND CALL CBW CLC CLD CLI
- CMC CMP CMPSB CMPSW CWD DAA
- DAS DB DD DEC DIV DW
- EQU HLT IDIV IMUL IN INC
- INT INTO IRET JA JAE JB
- JBE JC JCXZ JE JG JGE
- JL JLE JMP JNA JNAE JNB
- JNBE JNC JNE JNG JNGE JNL
- JNLE JNO JNP JNS JNZ JO
- JP JPE JPO JS JZ LAHF
- LDS LEA LES LOCK LODSB LODSW
- LOOP LOOPE LOOPNE LOOPNZ LOOPZ MOV
- MOVSB MOVSW MUL NEG NOP NOT
- OR OUT POP POPF PUSH PUSHF
- RCL RCR REP REPE REPNE REPNZ
- REPZ RET RETF ROL ROR SAHF
- SAL SAR SBB SCASB SCASW SHL
- SHR STC STD STI STOSB STOSW
- SUB TEST WAIT XCHG XLAT XLATB
- XOR
-
-
- The following conditional execution prefix is supported for
- compatibility with Eric Isaacson's A86 assembler:
-
- IF
-
-
- The following prefix is supported for inserting single or
- multiple line Pascal statements within an assembly section.
-
- PAS
-
-
- The following data definition and type qualifiers are supported:
-
- B BYTE W WORD D DWORD
- BIT BY DUP OFFSET SEG DATA
- PROC NEAR F FAR ENDP
-
-
- TP&Asm recognizes the following other assembly directives:
-
- ORG RADIX SEGMENT ENDS END
-
-
- TP&Asm uses the standard set of register mnemonics:
-
- AL BL CL DL AH BH CH DH
- AX BX CX DX SI DI BP SP
- CS DS ES SS
-
-
- The following directives are unnecessary and are ignored:
-
- AT COMMON LABEL MEMORY PARA STACK
- ASSUME EXTRN PAGE PUBLIC SUBTTL TITLE
- PTR SHORT LONG
-
- The following invalid string mnemonics should be replaced by the
- five character versions specifying byte or word (CMPSB, MOVSW, etc):
-
- CMPS LODS MOVS SCAS STOS
-
-
- TP&Asm does not currently support 8087 mnemonics or mnemonics
- which are unique to a specific processor (80286, 80386, NEC, etc).
- These mnemonics are reserved for upward compatibility to future
- versions of TP&Asm, and cannot be used as Assembly data labels.
-
- For compatibility with MASM, most assembly reserved words other than
- prefixes and qualifiers can be used as code labels.
-
- All reserved words can be used as Pascal symbols and referenced in
- assembly language by prefixing the symbol with ">" or "<", or with
- a valid UnitName or record qualifier, as discussed in the section
- on General Assembler Syntax.
-
-