Asm
Asm
Asm
ANSWER: Well, no, not exactly. You've bought a disk that has
great software on it; you haven't bought the software yet.
A86, like the vast majority of software offered by the $5-
per-disk distribution houses, is free-distribution software
(also known as "shareware", or "user-supported software").
That means I retain the rights to A86, but I choose to let
people pass it around. I have no business relationship
with any distribution houses in the U.S.; I don't get a
penny of the $5 (or whatever) you paid them for the disk
containing A86. So I need and expect to be paid by you,
because I make my living out of making and supporting
shareware products.
Shareware is great for authors like me, who have spent all
their years in their computer holes, learning to be great
programmers, and no time in business school learning
marketing and distribution techniques. We simply cast our
programs to the winds.
Now that I've said that, let's move on to the package. The A86
package consists of the program A86.COM, a collection of source,
batch, and library files used by the demonstration contained in
Chapter 2, and a sequence of DOC files that, when printed out in
order, make the manual. Each chapter is a DOC file whose name
is A??.DOC, where ?? runs from 00 though 17. Exception: chapter
6 is split into A06A.DOC and A06B.DOC. The second file is
wider, and should be printed at 12 cpi if you can manage it.
The other files can print at 10cpi with margins -- You should
set your printer to a 1-inch left margin, as the DOC files do
not attempt to provide a left margin for you. (You can modify
the PAGE.8 program to output the appropriate codes!)
0-3
TABLE OF CONTENTS
Introduction 1-1
Legal Terms and Conditions 1-1
Registration Benefits 1-3
Overview of A86 1-4
About the Author 1-6
How to Contact Me 1-7
A17.DOC INDEX
Introduction
1. You may copy the A86Vxxx.ZIP and D86Vxxx.ZIP files, and give
them to anyone who accepts these terms. The copies you
distribute must be complete and unmodified. You do not have
to be registered to distribute this package.
2. Even if you have not yet obtained full execution rights, you
may execute the programs in this package, in order to evaluate
them. If you decide that A86 is of use to you, you must
become a registered user by sending $50 US, ($52 if you are
outside North America) to:
Eric Isaacson
416 E. University Ave.
Bloomington, IN 47401-4739
Registration Benefits
Thank you for enduring the legalities. They are there to protect
me, and also to convince you that this is my business, from which
I make my living. I'll now return to a softer sell, to try to
make you want to register for my products.
Overview of A86
* A86 has language extension features that, once you start using,
you'll never want to do without. These include multiple
operands to PUSH and POP; conditional returns; MOV from one
segment register to another; assembly time assertion checking;
based structures; and IF (flag) (statement).
How to Contact Me
Now type the command ERDEMO, invoking the batch file ERDEMO.BAT.
This will invoke an assembly of a source file PAGE.BAD (copied
from PAGE.BL so you can run this demo again), into which I have
deliberately placed an erroneous statement, XCHG BL,AX. Note
that A86 tells you that it has inserted error messages into
PAGE.BAD, and saved the original source in PAGE.OLD.
Now use your favorite text editor to edit PAGE.BAD. You can use
your editor's string search function to find a tilde symbol,
which brackets all A86 error messages. Without altering the
messages, change the BL to BX, and exit your editor. Now type
the command A86 PAGE.BAD to reassemble the file. You should get
a successful assembly. Now type the command TYPE PAGE.BAD, and
note that A86 has removed the error messages for you. Wasn't
that easy?
Let's see A86 assemble a program with four source files. Type the
command A86 REV.8 to the console. A86 will assemble the REV.8
file you specified, see that there are undefined symbols in the
program, then assemble the files LINES.8, MSDOS.8, and USAGE.8,
listed in the library file A86.LIB, which I created using the
tool A86LIB available only to registered users.
2-2
Type the command TCOLS. The TCOLS program you just assembled
will execute, and notice that you have given it no parameters. It
thus gives you a self-documenting message. Note that towards the
end of the message is an example showing how TCOLS can be used to
print .XRF listings. You can do so now by turning your printer
on and typing an appropriate command; e.g., TCOLS <TCOLS.XRF 4 6
80 66 >PRN for 4 columns, skip 6 lines between pages, which are
80 columns by 66 lines.
If you examine the file TCOLS.LST with your favorite text editor,
you'll find a complete listing of the program, including the
expansion of the DEFAULT macro defined within the program.
Program Invocation
You may use the wild card delimiters * and ? if you wish, to
denote a group of source files to be assembled. A86 will sort
all matching names into alphabetical order for each wild card
specification; so the files will be assembled in the same order
even if they get jumbled up within a directory.
3-2
3. .COM otherwise.
If you want your program file to have no extension, you end the
file name with a period.
You may omit any of the output file names if you wish. If you do
so, A86 will output the program source.COM (or source.OBJ or
source.BIN), where "source" is a name derived from the list of
source files, according to the rules described in the section
"Strategies for Source File Maintenance" later in this chapter.
Any of the other output files will use the name of the program
output file, combined with the standard extension for that output
file.
Assembler Switches
Unless otherwise stated, the default setting for all the switches
is "minus". Multiple switches can be specified with a single
sign; e.g. +OG15L55 is the same as +O+G15+L55.
For example, if you execute the command SET A86=+O while in DOS
(typically in the AUTOEXEC.BAT file run when the computer is
started), then the O switch will be "plus", unless overridden
with a "minus" setting in the command line.
3-8
You may also include one or more file names in the A86
environment variable. Those files will always be assembled
first, before the files you specify on the command line. This
allows you to set up a library of macro definitions, which will
always be automatically available to your programs. Thus, for
example, the DOS command SET A86=C:\A86\MACDEF.8 +O will cause
both the O switch to default ON, but will also cause the file
MACDEF.8 of subdirectory A86 of drive C to always be assembled.
Here's how the feature works: when the command argument A86 is an
ampersand &, A86 will prompt for standard input. If the
ampersand is seen but there are other things following it, the
ampersand is ignored.
For example, you can place a list of file names and switch
settings into a file called FILELIST. You can then invoke the
assembler via
1. I name all my A86 source files with the same extension, which
is found on no other files. The particular extension I have
chosen is ".8". I did not choose the more common .ASM, because
I have a few source files designed for MSDOS's assembler. If
you don't like .8, I would suggest .A86.
Instruction Statements
MOV AX,BX
CALL SORT_PROCEDURE
ADD AL,7
A_VARIABLE DW 0
DB 'HELLO'
Assembler Directives
CODE SEGMENT
ITEM_COUNT EQU 5
Symbols are the "words" of the A86 language. All symbols are a
collection of consecutive letters, numbers, and assorted special
characters: _, @, $, and ?. Symbols cannot begin with digits:
anything that begins with a digit is a number. Symbols can begin
with any of the special characters just listed. Symbols can also
begin with a period, which is the only place within the symbol
name a period can appear.
4-2
Registers
Variables
Labels
LABEL_1:
LABEL_2: MOV AL,BL
Constants
The IF Statement
You may replace the above code with the single line:
IF Z MOV AX,BX
The above line generates exactly the same code as the previous 3
lines-- a conditional jump of the opposite condition, around the
statement given in the tail of the IF statement. The statement
can be a macro call, giving you the opportunity to skip something
more complicated.
You may use any condition that would follow the "J" in a
conditional jump instruction, except CXZ, which does not have a
reverse condition. The assembler interprets the condition by
appending a "J" to the beginning of the condition; so that the
symbols "C", "NC", "Z", "NZ", etc. are not reserved by the
assembler, and can be defined in other contexts.
Local Symbols
L2:
MOVSB
INC BX
LOOP L2 ; lack of ">" means L2 is above this statement
.
.
JNZ >L2 ; ">" indicates L2 is below this statement
.
JMP >L2 ; JMP L2 is disallowed here: cannot overlap ranges
.
L2:
5-4
I recommend that you assign all your local labels the names L0
through L9. If your program is so complex that it needs more
than 10 place holders in any one stretch of code, then that
stretch needs to be rewritten.
I've gotten a little flak from some users about this feature.
They claim it violates my policy against "behind your back"
actions. But I feel that this feature is completely equivalent
to code optimizations in other situations: the short JMP form
instead of the equivalent near JMP; a byte operand to ADD SI,4
instead of a word operand; the one-byte XCHG AX,BX instead of the
general XCHG rw,ew form; etc, etc, etc. In situations where there
is absolute functional equivalence between forms, A86 tries to
generate the most efficient form. But for those who are not
convinced, I offer the +G2 switch, described in Chapter 3.
Some users have also gotten the mistaken impression, from reading
Intel's confusing specs, that the longer LEA is sometimes faster
than the shorter MOV. This is never the case: those users are
reading the clock counts for the memory-fetch forms of MOV, not
the register-only or immediate-value forms. If you don't believe
it, try timing 1000 consecutive LEA's in a loop that executes
50000 times, vs. a similar loop with the equivalent MOV.
Effective Addresses
DATA_PTR DW ?
ESC_CHAR DB ?
Note that A86 discerned from context (loading into AL) that a
BYTE at 02000 was intended. Sometimes this is impossible, and
you must specify byte or word:
MOV AX,[BX]
MOV CX,W[SI+17]
MOV AX,[BX+SI+5]
MOV AX,[BX][SI]5 ; another way to write the same instr.
Or, indexing can be accomplished by declaring variables in a
based structure (see the STRUC directive in Chapter 9):
TABLE DB 4,2,1,3,5
MOV AL,TABLE[BX] ; load byte number BX of TABLE
The 386 processor also supports indexing using any of the eight
32-bit general registers. This type of indexing is of limited
use for memory referencing from real-mode programs (most programs
running under DOS), since offsets greater than 64K are disallowed
in real mode (you will get a General Protection Fault if you try
it). 32-bit indexing is, however, useful in conjunction with the
LEA instruction, giving an extremely powerful register arithmetic
instruction. For example, LEA ECX,[EAX+2*EBX+17000] performs two
additions and a multiplication, all in a single machine
instruction. Since no memory accessed is actually attempted,
this kind of LEA usage is allowed in real-mode DOS programs.
6-3
In 32-bit indexing, you may use one or two of any of the 32-bit
general registers. You may also scale one of the indexing
registers, by multiplying it by 2, 4, or 8. You may also add or
subtract a constant of any size up to a doubleword capacity to
the indexed quantity. If you use the same register twice and
scale one of the instances of that register, you get, in effect,
an odd-number scaling (3, 5, or 9) of that register; e.g., A386
will allow LEA EAX,[9*EBX] as an abbreviation for LEA
EAX,[8*EBX+EBX].
XCHG DX,[EAX]
MOV AL,[EAX+EBX]
ADD EBX,[ESI+8*ECX+3391811]
LEA ECX,[4*EBX-7]
The 86 family has four segment registers, CS, DS, ES, and SS,
used to address memory. The 386 and later processors add two
more segment registers FS and GS. Each segment register points
to 64K bytes of memory within the 1-megabyte memory space of the
86. (The start of the 64K is calculated by multiplying the
segment register value by 16; i.e., by shifting the value left by
one hex digit.) If your program's code, data and stack areas can
all fit in the same 64K bytes, you can leave all the segment
registers set to the same value. In that case, you won't have to
think about segment registers: no matter which one is used to
address memory, you'll still get the same 64K. If your program
needs more than 64K, you must point one or more segment registers
to other parts of the memory space. In this case, you must take
care that your memory references use the segment registers you
intended.
Note the distinction between the address override byte (67H) and
the operand override byte (66H). A86 must supply an address
override when the instruction involves a memory operand whose
address has 32 bits. A86 must supply an operand override when
the data being manipulated has 32 bits. In general, when a
32-bit register name appears inside the square brackets, that's
an address override; when it appears outside the square brackets,
that's an operand override. Examples:
6-9
Opcodes Instruction Description
The original IBM-PC, and the XT, accept the original floating
point chip, the 8087. Later processors accept corresponding
chips: the 287 for the 286, the 387 for the 386, etc. From a
programming standpoint, the 8087 and 287 are nearly identical:
the 287 adds the instructions FSETPM and FSTSW AX, and ignores
the instructions FENI and FDISI. There is, however, a rather
nasty design flaw in the 8087, that was corrected in the 287.
If they do, then you must provide an instruction called WAIT (or
synonymously FWAIT), which halts the 86 until the 87 is finished.
For almost all floating point instructions, it should not be
necessary to provide an explicit FWAIT; the 86 ought to know that
it should wait. For the 8087, it IS necessary to give an
explicit FWAIT before each floating point instruction: that is
the flaw.
You can tell A86 that the emulator might be used, by providing a
+f switch in the invocation line, or in the A86 environment
variable (make sure the f is lower case). Since your program
will be linked to the emulator, you must be producing an OBJ
file, not a COM file, for emulation support to take effect.
Whenever a floating point instruction is assembled, A86 will
generate an external reference at the opcode for the instruction.
Then, if the emulation package is linked with your program, the
opcodes will be replaced by the INT calls. If a special
non-emulation module is linked, the opcodes will be left alone,
and the floating point instructions will be executed directly.
The standard name for the top element of the floating point stack
is either ST or ST(0); the others are named ST(1) through ST(7).
Thus, for example, the instruction to add stack element number 3
into the top stack element is usually coded FADD ST,ST(3).
DEG_TO_RAD DT PI/180.
CS FLD T[M1]
JMP >M2
M1 DT 12.3
M2:
mem14 and mem94 are 14- and 94-byte buffers containing the 87
machine state.
7-6
w D9 E0 FCHS 0 := -0
9B DB E2 FCLEX clear exceptions
w D8 D1 FCOM compare 0 - 1
w D8 D0+i FCOM 0,i compare 0 - i
w D8 D0+i FCOM i compare 0 - i
w D8 /2 FCOM mem4r compare 0 - mem4r
w DC /2 FCOM mem8r compare 0 - mem8r
7-7
w DE F9 FDIV 1 := 1 / 0, pop
w D8 F0+i FDIV i 0 := 0 / i
w DC F8+i FDIV i,0 i := i / 0
w D8 F0+i FDIV 0,i 0 := 0 / i
w D8 /6 FDIV mem4r 0 := 0 / mem4r
w DC /6 FDIV mem8r 0 := 0 / mem8r
w DE C9 FMUL 1 := 1 * 0, pop
w D8 C8+i FMUL i 0 := 0 * i
w DC C8+i FMUL i,0 i := i * 0
w D8 C8+i FMUL 0,i 0 := 0 * i
w D8 /1 FMUL mem4r 0 := 0 * mem4r
w DC /1 FMUL mem8r 0 := 0 * mem8r
w DE C8+i FMULP i,0 i := i * 0, pop
w D9 F8 FPREM 0 := REPEAT(0 - 1)
w D9 F5 FPREM1 387 only: 0 := REPEAT(0 - 1) IEEE compat.
w D9 F2 FPTAN push, 1/0 := tan(old 0)
w D9 FC FRNDINT 0 := round(0)
w DD /4 FRSTOR mem94 87 state := mem94
w DD /6 FSAVE mem94 mem94 := 87 state
w D9 FD FSCALE 0 := 0 * 2.0 ** 1
9B DB E4 FSETPM set protection mode
w D9 FE FSIN 387 only: 0 := sine(0)
w D9 FB FSINCOS 387 only: push, 1 := sine, 0 := cos(old 0)
w D9 FA FSQRT 0 := square root of 0
7-9
w DD D0+i FST i i := 0
w D9 /2 FST mem4r mem4r := 0
w DD /2 FST mem8r mem8r := 0
w D9 /7 FSTCW mem2i mem2i := control word
w D9 /6 FSTENV mem14 mem14 := environment
w DD D8+i FSTP i i := 0, pop
w DB /7 FSTP mem10r mem10r := 0, pop
w D9 /3 FSTP mem4r mem4r := 0, pop
w DD /3 FSTP mem8r mem8r := 0, pop
w DF E0 FSTSW AX AX := status word
w DD /7 FSTSW mem2i mem2i := status word
w DE E9 FSUB 1 := 1 - 0, pop
w D8 E0+i FSUB i 0 := 0 - i
w DC E8+i FSUB i,0 i := i - 0
w D8 E0+i FSUB 0,i 0 := 0 - i
w D8 /4 FSUB mem4r 0 := 0 - mem4r
w DC /4 FSUB mem8r 0 := 0 - mem8r
w DE E8+i FSUBP i,0 i := i - 0, pop
w DE E1 FSUBR 1 := 0 - 1, pop
w D8 E8+i FSUBR i 0 := i - 0
w DC E0+i FSUBR i,0 i := 0 - i
w D8 E8+i FSUBR 0,i 0 := i - 0
w D8 /5 FSUBR mem4r 0 := mem4r - 0
w DC /5 FSUBR mem8r 0 := mem8r - 0
w DE E0+i FSUBRP i,0 i := 0 - i, pop
A86 allows floating point numbers as the operands to DD, DQ, and
DT directives. The numbers are encoded according to the IEEE
standard, followed by the 8087 and 287 coprocessors. The format
for floating point constants is as follows: First, there is a
decimal number containing a decimal point. There must be a
decimal point, or else the number is interpreted as an integer.
There must also be at least one decimal digit, either to the left
or right of the decimal point, or else the decimal point is
interpreted as an addition (structure element) operator.
Optionally, there may follow immediately after the decimal number
the letter E followed by a decimal number. The E stands for
"exponent", and means "times 10 raised to the power of". You may
provide a + or - between the E and its number. Examples:
Overview of Expressions
Most of the operands that you code into your instructions and
data initializations will be simple register names, variable
names, or constants. However, you will regularly wish to code
operands that are the results of arithmetic calculations,
performed either by the machine when the program is running (for
indexing), or by the assembler (to determine the value to
assemble into the program). A86 has a full set of operators that
you can use to create expressions to cover these cases. They are
given in the "Descriptions of Operators and Specifiers" section
later in this chapter.
Variables
Index Expressions
HIGH/LOW
For example,
BY
Addition (combination)
8-5
Other examples:
Subtraction
Syntax: operand - operand
You may only use these operators with absolute or floating point
numbers, and the result is always the same type. Either operand
may be a numeric expression, as long as the expression evaluates
to an absolute or floating point number. Examples:
Shifting Operators
Logical Operators
Examples:
Syntax: ! operand
8-7
Relational Operators
The relational operators may have operands that are either both
absolute numbers, or both variable names that have the same type.
The result of a relational operation is always an absolute
number. They return an 8-or 16-bit result of all 1's for TRUE
and all 0's for FALSE. Examples:
ARRAY_PTR:
DB 100 DUP (?)
WVAR DW ?
MOV AL,ARRAY_PTR B ; load first byte of ARRAY_PTR array into AL
MOV AL,WVAR B ; load the low byte of WVAR into AL
MOV AX,W[01000] ; load AX with the memory word at loc. 01000
LDS BX,D[01000] ; load DS:BX with the doubleword at loc. 01000
JMP F OUTSIDE_LOC ; jump to undeclared far location OUTSIDE_LOC
FLD T[BX] ; load ten-byte number at [BX] to 87 stack
For compatibility, A86 accepts the more verbose synonyms BYTE,
WORD, DWORD, FAR, QWORD, and TBYTE for B,W,D,F,Q,T, respectively.
NOTE that for A86, LONG will have effect only on the operand to
an unconditional JMP instruction; not to conditional jumps. That
is because conditional jumps farther than 127 bytes are available
only on the 386. If you run into this problem, then chances are
your code is getting out of control--time to rearrange, or to
break off some of the intervening code into separate procedures.
If you insist upon leaving the code intact, you can replace the
conditional jump with an "IF cond JMP".
OFFSET Operator
NEAR Operator
Syntax: [operand ]
MOV B[BX+50],047 ; move imm value 047 into mem byte at BX+50
MOV AL,[050] ; move byte at memory location 050 into AL
MOV AL,050 ; move immediate value 050 into AL
Colon Operator
There are three forms to the colon operator. The first form has
a constant as the segment register value. This form is used to
create an operand to a far (inter-segment) JMP or CALL
instruction. An example of this is the instruction JMP 0FFFF:0,
which jumps to the cold-boot reset location of the 86 processor.
The second form has a segment register name to the left of the
colon. This is the segment override form, provided for
compatibility. A86 will generate a segment override byte when it
sees this form, unless the operand to the right of the colon
already has a default segment register that is the same as the
given override.
ST Operator
The DEF operator returns a value of TRUE if the operand has been
defined previously in the assembly, false if it hasn't.
TYPE Operator
BVAR DB
WVAR DW ?
If this is too cryptic for you, there is always BVAR EQU B[$].
8-12
Operator Precedence
--Highest Precedence--
1. Parenthesized expressions
2. Period
3. OFFSET, SEG, TYPE, REF, DEF, and PTR
4. HIGH, LOW, and BIT
5. Multiplication and division: *, /, MOD, SHR, SHL
6. Addition and subtraction: +,-
a. unary
b. binary
7. Relational: EQ, NE, LT, LE, GT, GE =
8. Logical NOT and !
9. Logical AND
10. Logical OR and XOR
11. Colon for long pointer, SHORT, LONG, and BY
12. DUP
--Lowest Precedence--
Segments in A86
A86 views the 86 computer's memory space as having two parts: The
first part is the program, whose contents are the object bytes
generated by A86 during its assembly of the source. A86 calls
this area the CODE SEGMENT. The second part is the data area,
whose contents are generated by the program after it starts
running. A86 calls this area the DATA SEGMENT.
Please note well that the only difference between the CODE and
DATA segments is whether the contents are generated by the
program or the assembler. The names CODE and DATA suggest that
program code is placed in the CODE segment, and data structures
go in the DATA segment. This is mostly true, but there are
exceptions. For example, there are many data structures whose
contents are determined by the assembler: pointer tables, arrays
of pre-defined constants, etc. These tables are assembled in the
CODE segment.
DATA SEGMENT
ANSWER_BYTE DB ?
CALL_COUNT DW ?
CODE SEGMENT
JMP MAIN
TRAN_TABLE:
DB 16,3,56,23,0,9,12,7
MAIN:
MOV BX,TRAN_TABLE
XLATB
MOV ANSWER_BYTE,AL
INC CALL_COUNT
RET
Other than in the above example, you should not in general issue
an ORG within the CODE segment that would lower the value of the
output pointer. This is because you thereby put yourself in
danger of losing part of your assembled program. If you
re-assemble over space you have already assembled, you will
clobber the previously-assembled code. Also, be aware that the
size of the output program file is determined by the value of the
code segment output pointer when the program stops. If you ORG
to a lower value at the end of your program, the output program
file will be truncated to the lower-value address.
Again, almost no program producing a .COM file will need any ORG
directive in the code segment. There is an implied ORG 0100 at
the start of the program. You just start coding instructions,
and the assembler will put them in the right place.
9-3
CODE SEGMENT
DW 5 ; allocate one word, init. to 5
DB 0,3,0 ; allocate three bytes, init. to 0,3,0
DB 5 DUP 0 ; equivalent to DB 0,0,0,0,0
DW 2 DUP (0,4 DUP 7) ; equivalent to DW 0,7,7,7,7,0,7,7,7,7
DATA SEGMENT
XX DW ? ; define a word variable XX
YYLOW DB ; no init value: YYLOW is low byte of word var
YY
YY DW ?
X_ARRAY DB 100 DUP ? ; X_ARRAY is a 100-byte array
D_REAL DQ ? ; double precision floating variable
EX_REAL DT ? ; extended precision floating variable
DB 'HELLO'
9-5
DD 01234:05678
DD, DQ, and DT can also be used to initialize large integers and
floating point numbers. Examples:
Forward References
JNZ TARGET
.
.
TARGET:
ADD AX,10
Now when you use the symbol MAX_NAMES instead of the number 100
(for example, MOV CX,MAX_NAMES), it will be obvious that you are
referring to the maximum number of names in the table. Also, if
you decide to extend the table, you need only change the 100 in
the EQU directive to a 200 and every reference to MAX_NAMES will
reflect the change.
MAX_NAMES DB ?
Interrupt Equates
A86 allows you to equate your own name to an INT instruction with
a specific interrupt number. For example, if you place TRAP EQU
INT 3 at the top of your program, you can use the name TRAP as a
synonym for INT 3 (the debugger trap on the 8086).
Duplicate Definitions
DATA SEGMENT
OPTIONS:
.
.
OPT_COUNT EQU $-OPTIONS ; OPT_COUNT is the size of the table
CODE SEGMENT
OPT_INITS:
.
.
OPT_COUNT EQU $-OPT_INITS ; second OPT_COUNT had better be the same!
9-10
The = Directive
NOTE that this means that A86 does not support nested PROCs, in
which anything but the innermost PROC has the FAR attribute. I'm
sorry if I am blunt, but anybody who would subject their program
to that level of syntactic clutter has rocks in their head.
The LABEL Directive
LABEL defines "name" to have the type given, and a value equal to
the current output pointer. Thus, LABEL NEAR is synonymous with
a simple colon following the name; and LABEL BYTE, LABEL WORD,
LABEL DWORD, etc., are synonymous with DB, DW, DD, etc., with no
operands.
A86 now allows the inclusion of alternate source files within the
middle of a "parent" source file, via the INCLUDE directive.
When you give the name INCLUDE followed by the name of a file,
A86 will insert the contents of the named file into the assembly
source stream, as if it were substituted for the INCLUDE line.
There is no limit to the size of an INCLUDE file, and INCLUDEs
may be nested (the file included may itself contain INCLUDE
directives) to any level within reason. Parentheses are optional
around the file name; if you don't give them, there must be at
least one blank between the INCLUDE and the file name.
A86 allows you to produce either .COM files, which can be run
immediately as standalone programs, or .OBJ files, to be fed to
the MS-DOS LINK program. In this chapter I'll discuss .OBJ mode
of A86.
There are two ways you can cause A86 to produce a .OBJ file as
its object output. One way is to explicitly give .OBJ as the
output file name: for example, you can assemble the source file
FOO.8 by giving the command "A86 FOO.8 FOO.OBJ". The other way
is to specify the switch +O (letter O not digit 0). This is
illustrated by the invocation "A86 +O FOO.8", which will have the
same effect as the first invocation.
These 11 lines can be your entire source file! If you name the
file MUL10.8, A86 will create an object file MUL10.OBJ, that
conforms to the standard SMALL model of computation for high
level languages. If you use RETF instead of RET (thus, by the
way, getting the operand from BP+6 instead of BP+4), the object
module will conform to the standard LARGE model of computation.
All the red tape information required by the high level language
is provided implicitly by A86. I'll go through this information
in detail later, but you should need to read about it only if
you're curious.
It's now been over a decade since the fateful design meeting took
place, and I can report that the above scenario has never taken
place in the real world. And I can state with some authority
that it never will. The reason is that the only programs that
exceed 64K bytes in size are coded in high level language, not
assembly language. High-level-language compilers follow a very,
very restricted segmentation model-- no existing model comes
remotely close to supporting the scheme suggested by the
scenario. But the 86 assembly language can support it-- the
directives "G1 GROUP A,U" and "G2 GROUP B,U", followed by chunks
of code of the appropriate object size, headed by directives "A
SEGMENT", "B SEGMENT", and "U SEGMENT". The LINK program is
supposed to sort things out according to the scenario; but I
can't say (and I have my doubts) if it actually succeeds in doing
so.
If you do not provide a NAME directive, A86 will use the name of
the output object file, without the .OBJ extension. If you
provide more than one NAME directive, A86 will use the last one
given, with no error reported.
If you are writing new code, you'll probably want to keep the
flag "implicit". You use the PUBLIC directive only for those
symbols which have the form of local labels, but aren't (e.g., a
memory variable I1987 for 1987 income); and for absolute values
that are globally accessed -- e.g. specify "PUBLIC
OPEN_FILES_LIMIT" for a symbol defined as "OPEN_FILES_LIMIT EQU
20".
If you are porting existing code, that code will already have
PUBLIC directives in it, and A86 will go to "explicit" mode,
duplicating the functionality of other assemblers.
where "type" is one of: BYTE WORD DWORD QWORD TBYTE FAR
or synonymously: B W D Q T F
or: NEAR ABS PROC
A86 will allow more than one EXTRN directive for a given symbol,
as long as the same type is given every time. A86 will even
allow an EXTRN directive for a symbol that has already been
defined, as long as the type declared is consistent with the
symbol's definition. These allowances exist so that you can
assemble multiple files written for another assembler, that had
been fed separately to that assembler.
10-7
For those of you who are accustomed to the more traditional use
of EXTRN, and who do not like external records to be created
"behind your back", A86 offers the "+G16" option. If you include
"+G16" in the program invocation, A86 will require that all
undefined symbols be explicitly declared via an EXTRN. Any
undefined, undeclared symbols will be included in the .UND
listing of undefined symbols, and object-file output will be
suppressed.
Syntax: END
END start_addr
The "combine" specification tells how the chunk of code from this
module will be combined with the chunks of the same named
segment, that come from other modules. Yes, I know, that sounds
like what "align" does; but "combine" takes a different, more
major point of view:
The code just given declares a stack area of 200 bytes (100
words) for this module. If identical code occurs in each of
three modules which are then linked together, the resulting
STACK segment will have 600 bytes (the sizes are added), but
TOP_OF_STACK will be the same address (600) for each module
(each piece is overlayed at the top of the segment). That way,
every module can declare and access the top of the stack, which
is the only static part of the stack that any code should ever
refer to.
The DATA SEGMENT and STRUC directives work in .OBJ mode exactly
as they do in .COM mode-- they define a special assembly mode, in
which declarations are made, but no object code is output.
Offsets within DATA segments and structures are absolute, as in
.COM mode. Assembly resumes as before when an ENDS or CODE
SEGMENT directive is encountered.
These four lines can be inserted inside any other segment being
assembled. They will cause the two variable allocations to be
tacked onto the segment _DATA; and assembly will then continue in
whatever segment surrounded the four lines. Observe that the
"nesting" does not occur in the final program; only the
presentation of the source code is nested.
10-12
If you are not nesting segments inside one another, then the ENDS
directive serves only to lend a clean, "block-structured"
appearance to your source code. It does not assist A86 in any
particular way; in fact, it consumes a bit more object output
memory (slightly reducing object output capacity) if you have
ENDSs, rather than just starting up new segments with SEGMENT
directives.
The GROUP directive causes A86 to tell LINK that all the listed
segments can fit into a single 64K-byte block of memory, and
instruct LINK to make that fit. (If they won't fit, LINK will
issue an error message.) Having declared the group, you can then
use "group_name" as the segment register value that will allow
simultaneous access to all the named segments. The order of
names given in the list does not necessarily determine the order
in which the segments will finally appear within the group.
Macro Facility
Examples:
MOVM MACRO
MOV AL,#2
MOV #1,AL
#EM
VAR1 DB ?
VAR2 DB ?
FOO MACRO
DB '##1'
DB '#1'
#em
The format of the macro call line is also flexible. A macro call
consists of the name of the macro, followed by the operands to be
plugged into the macro. A86 prunes leading and trailing blanks
from the operands of a macro call. The operands to a macro call
are always separated by commas. Also, as in all A86 source
lines, a semi-colon occurring outside of a quoted string is the
start of a comment, ignored by A86. If you want to include
commas, blanks, or semi-colons in your operands, you must enclose
your operand in single quotes.
KF_ENTRY MACRO
CF_#1 EQU ($-KFUNCS)/2+080
DW KF_#1
#EM
KFUNCS:
KF_ENTRY UP
KF_ENTRY DOWN
DBW MACRO
DB #1
DW #2
#EM
; note that if quotes were not passed, the above lines would have
; to be DBW '''E''', E_POINTER; DBW '''W''', W_POINTER
FETCH_CHAR MACRO
LODSB
#1
CALL PROCESS_CHAR
#EM
A86's macro facility contains two kinds of loops: you can loop
once for each operand in a range of operands; or you can loop
once for each character within an operand. The first kind of
loop, the R-loop, is discussed in this section; the second kind,
the C-loop, is discussed later.
STORE3 MACRO
MOV AX,#1
#RY24 ; "repeat for Y running from 2 through 4"
MOV #Y,AX
#ER
#EM
STORE3 VAR1,VAR2,VAR3,VAR4
; the above call produces the 4 instructions MOV AX,VAR1; MOV VAR2,AX;
; MOV VAR3,AX; MOV VAR4,AX.
11-5
A86 recognizes the special operator #L, which is the last operand
in a macro call. #L can appear anywhere in macro text; but its
big power occurs in conjunction with R-loops, to yield an
indefinite-repeat facility.
CLEAR AX,BX ; generates both SUB AX,AX and SUB BX,BX in one macro!
Character Loops
We have seen the R-loop; now we discuss the other kind of loop in
macros, the character loop, or C-loop. In the C-loop, the
variable W,X,Y, or Z does not represent an entire operand; it
represents a character within an operand.
Note that any operand specifier can appear in contexts other than
by itself following a # within a macro. For example, BBL could
appear as the upper limit to an R-loop: #RZ1BBL loops with Z
running from the first operand to the third-to-last operand.
In the case of the variable operand to a C-loop, the "A" and "B"
specifiers denote the characters before or after the current
looping-character. An example of this is given in the next
section.
We have seen that you end an R-loop with a #ER, and you end a
C-loop with a #EC. We now present another way to end these
loops; a way that lets you specify a larger increment to the
macro's loop counter. You can end your loops with one of the 4
additional commands #E1, #E2, #E3, or #E4.
Negative R-loops
Example:
If you have a loop or loops ending when the macro ends, and if
the iteration count for those loops is 1, you may omit the #ER,
#EC, or #EQ. A86 closes all open loops when it sees #EM, with no
error.
For example, if you omit the #ER for the loop version of the
CLEAR macro, it would make no difference-- A86 automatically
places an #ER code into the macro definition for you.
JLV MACRO
J#1 LABEL#V2
#EM
JINDEX = 3
JLV NC,JINDEX+1 ; generates JNC LABEL4
JINDEX = 6
JLV Z,JINDEX+2 ; generates JZ LABEL8
LSTRING MACRO
DB #S1,'#1'
#EM
ZSTRINGS MACRO
DB #NL ; generates the number of operands passed
#RX1L
DB '#X',0
#EM
TEMP = 0
REPT 100
TEMP = TEMP + 1 ; MASM needs an explicitly-set-up counter
DB TEMP
ENDM
If the REPT does not occur within a macro, you must define a
macro containing the loop, which you may then immediately call.
11-10
JHASH MACRO
CMP AL,'##' ; is the scanned character a hash sign?
JNE >M1 ; skip if not
CALL MDEF_HASH ; process the hash sign
JMP #1 ; jump to the label provided
M1:
#EM
11-11
...
L3: ; loop here to eat empty lines, leading blanks
CALL SKIP_BLANKS ; skip over the leading blanks of a line
INC SI ; advance source ptr beyond the next non-blank
JHASH L3 ; if hash sign then process, and eat more blanks
CMP AL,0A ; were the blanks terminated by a linefeed?
JE L3 ; loop if yes, nothing on this line
L5: ; loop here after a line is seen to have contents
CMP AL,';' ; have we reached the start of a comment?
JE L1 ; jump if yes, to consume the comment
JHASH >L6 ; if hash sign then process it; get next char
...
L6:
LODSB ; fetch the next definition char from the source
CMP AL,' ' ; is it blank?
JA L5 ; loop if not, to process it
...
There are two ways that A86 lets you debug your macro expansions.
First, if A86 encounters an error within a macro expansion, it
now includes the offending expansion line within the error
message. This will often allow you to spot the problem. If you
need a complete listing of the expanded macro, the A86 listing
will now give you that. These facilities replace the old EXMAC
tool, which sometimes failed to expand excessively complicated
macros the way the assembler did.
Conditional Assembly
#if TEXAS
DB 0,1,2,3
#elseif OKLAHOMA
DB 4,5,6,7
#else
DB 8,9,10,11
#endif
11-13
#if !TEXAS
DB 0FF
#endif
X1 EQU 0
BAZ MACRO
#if X1
DB 010
#else
DB 011
#endif
#EM
BAZ
X1 EQU 1
BAZ
X1 EQU 0
BAZ MACRO
##if X1
DB 010
##else
DB 011
##endif
#EM
BAZ
X1 EQU 1
BAZ
11-14
amake texas
amake oklahoma
amake
The third line will produce the assembler invocation A86 = *.8;
causing no invocation variables to be declared. Thus both TEXAS
and OKLAHOMA will be false, which is exactly what you want for
the rest-of-the-nation version of the program.
Following is a list of the things you should watch out for when
converting from MASM to A86:
The last three constructs, IRP, REPT, and IRPC, usually occur
within macros; but in MASM they don't have to. The A86
equivalents are valid only within macros-- if they occur in
the MASM program outside of a macro, you duplicate them by
defining an enclosing macro on the spot, and calling that
macro once, right after it is defined.
12-4
PAYREC STRUC
PNAME DB 'no name given'
PKEY DW ?
ENDS
PAYREC 3 DUP (?)
PAYREC <'Eric',1811>
DB 'Eric '
DW ?
The TITLE directive specifies a title that will appear at the top
of every page of the entire assembly. The title consists of the
first 60 characters starting with the first nonblank after the
word TITLE on the line. If you give more than one TITLE
directive in a program, only the first will be recognized.
Omitted parameters (either left off the end or via leading commas
or 2 consecutive commas) will remain unchanged.
Cross-reference Facility
You may update A86.LIB by running A86LIB again; either with new
files or previously-recorded ones. If A86LIB is given a file it
had already read in a previous run, then A86LIB marks all the
symbols it had logged for the file as deleted, before rereading
the file. Those symbols that are still in the file are then
"unmarked". Thus, symbols that have been deleted from the file
disappear functionally from A86.LIB, but still occupy space
within A86.LIB. What I'm getting at is this: A86LIB will
tolerate alterations in library files quite nicely; but for
optimum storage efficiency you should delete A86.LIB and rebuild
it from scratch any time you delete anything from the library.
A86LIB is so fast that this is never very painful.
13-6
Once you have created a library with A86LIB, you access it simply
by calling the procedures in it from your A86 program. When A86
finishes an assembly and sees that there are undefined symbols in
your program, it will automatically look for copies of A86.LIB in
the current directory (then in other directories, as described in
the next section). If any of the undefined symbols are found in
the A86.LIB catalog, the files containing them are assembled.
You see this in the list of files output to the console by A86.
You may now have macros in your A86LIB library. Here's how it
works: when A86 sees a new symbol at the beginning of a line, in
a context where it would formerly have issued an error, A86 will
first look in the A86LIB libraries for the symbol. If it's
found, A86 will INCLUDE that library file on the spot, and then
assemble the line. NOTE that if the macro is being called within
a sequence of executable instructions, the library file must
generate no output object code.
SET A86LIB=C:\bin\lib;\tools\a86lib
then A86 will look for A86.LIB in the current directory, then it
will look for C:\bin\lib\A86.LIB, then \tools\a86lib\A86.LIB. A86
will keep looking in all three catalog files, assembling the
appropriate source files from any or all of them, until there are
no more undefined symbols, or there are no more source files to
assemble.
You may now also force a library search from within a source
file, by placing a line with INCLUDE by itself with no file
names, into the source code. A86 will include any library files
necessary to resolve any forward-references at the point of the
INCLUDE.
This is also reported when you have two operands that are
mismatched in size, and the mismatch is something other than
Byte vs. Word. Example: MOV AL,D[0100].
14-4
Recall from Chapter 5 that when you use a local label symbol
twice, you must distinguish a reference to that symbol by
prepending a > before the symbol's name if the reference is a
forward reference. You get this error if you have followed
such a forward reference with another reference, without the
>, before the next incaration of the symbol is defined.
There's a danger that you intended the reference to be to the
previous incarnation, which A86 doesn't allow. Example:
V4.00 December 1994. "Official" public release with all the new
features mentioned in V3.70 above. Added COMPAT.8 file to
implement some MASM directives as A86 macros.
D Dword specifier
DAA Decimal adjust add
DAS Decimal adjust sub
DATA Segment name
DB Define bytes
DD Define dwords
DEC Decrement
DEF Defined operator
DH Byte register
DI Word register
DIV Divide
DL Byte register
DQ Define Qwords
DRn Debug registers 0--7
DS Segment register
DT Define Twords
DUP Duplicate operator
DW Define words
DWORD Memory specifier
DX Word register
F Far specifier
F2XM1 87 Instruction
F4X4 IIT-2C87 Instruction
FABS 87 Instruction
FADD 87 Instruction
FADDP 87 Instruction
FAR Far specifier
FBANK IIT-2C87 Instruction
FBLD 87 Instruction
FBSTP 87 Instruction
FCHS 87 Instruction
FCLEX 87 Instruction
FCOM 87 Instruction
FCOMP 87 Instruction
FCOMPP 87 Instruction
FCOS 387 Instruction
FDECSTP 87 Instruction
FDISI 87 Instruction
FDIV 87 Instruction
FDIVP 87 Instruction
FDIVR 87 Instruction
FDIVRP 87 Instruction
FENI 87 Instruction
FFREE 87 Instruction
FIADD 87 Instruction
FICOM 87 Instruction
FICOMP 87 Instruction
FIDIV 87 Instruction
FIDIVR 87 Instruction
FILD 87 Instruction
FIMUL 87 Instruction
FINCSTP 87 Instruction
FINIT 87 Instruction
FIST 87 Instruction
FISTP 87 Instruction
FISUB 87 Instruction
FISUBR 87 Instruction
16-4
FLD 87 Instruction
FLD1 87 Instruction
FLDCW 87 Instruction
FLDENV 87 Instruction
FLDL2E 87 Instruction
FLDL2T 87 Instruction
FLDLG2 87 Instruction
FLDLN2 87 Instruction
FLDPI 87 Instruction
FLDZ 87 Instruction
FMUL 87 Instruction
FMULP 87 Instruction
FNCLEX 87 Instruction
FNDISI 87 Instruction
FNENI 87 Instruction
FNINIT 87 Instruction
FNOP 87 Instruction
FNSAVE 87 Instruction
FNSTCW 87 Instruction
FNSTENV 87 Instruction
FNSTSW 87 Instruction
FPATAN 87 Instruction
FPREM 87 Instruction
FPREM1 387 Instruction
FPTAN 87 Instruction
FRNDINT 87 Instruction
FRSTOR 87 Instruction
FS Segment register
FSAVE 87 Instruction
FSCALE 87 Instruction
FSETPM 87 Instruction
FSUB 87 Instruction
FSUBP 87 Instruction
FSUBR 87 Instruction
FSUBRP 87 Instruction
FTST 87 Instruction
16-5
GE Greater/equal operator
GROUP Group of segments
GS Segment register
GT Greater than operator
HIGH High byte of word op
HLT Halt
IDIV Integer divide
IF Skip/conditional term
IMUL Integer multiply
INT Interrupt
INTO Interrupt on overflow
INVD Invalidate data cache
INVLPG Invalidate TLB entry
IRET Interrupt return
IRETD Interrupt return 32-bit
JA Jump on above
JAE Jump above equal
JB Jump on below
JBE Jump below equal
JC Jump on carry
JL Jump on less
JLE Jump less equal
JMP Jump unconditional
JNA Jump not above
JNAE Jump not above equal
JNB Jump not below
JNBE Jump not below equal
JNC Jump not carry
16-6
JO Jump overflow
JP Jump parity
JPE Jump parity even
JPO Jump parity odd
JS Jump on sign
JZ Jump on zero
LOOP Instruction
LOOPE Loop on equal
LOOPNE Loop not equal
LOOPNZ Loop not zero
LOOPZ Loop on zero
LOW Operator
16-7
MOD Operator
MOV Instruction
MOVS Move string
MOVSB Move string byte
MOVSD Move string doubleword
MOVSW Move string word
MOVSX Move sign extended
MOVZX Move zero extended
MUL Multiply
RADIX Directive
RCL Rotate carry left
RCR Rotate carry right
RDMSR Read model specific reg
RDTSC Read time stamp counter
REF Referenced operator
RET Return
RETF Far Return
ROL Rotate left
ROL4 NEC Instruction
ROR Rotate right
ROR4 NEC Instruction
RSM Resume from sys mgmt.
SI Word register
SIDT 286 Prot Instruction
SLDT 286 Prot Instruction
SMSW 286 Prot Instruction
SP Word register
SS Segment register
16-9
T Tbyte specifier
TBYTE Memory specifier
TEST Instruction
TESTBIT NEC Instruction
THIS This-location specifier
TITLE Listing title
TRn Test registers 6--7
TYPE Operator
VERR 286 Prot Instruction
VERW 286 Prot Instruction
W Word specifier
WAIT Instruction
WBINVD Write back, invalidate
WORD Word specifier
WRMSR Write model specific reg
INDEX 17-1
287 directive, 7-2
386 indexing, 6-2
387 support, 7-2
A-after operator in macros, 11-6
A86 environment variable, 3-7
A86.LIB file, 13-5
A86.LIB library catalog, 2-1
A86LIB environment variable, 13-6
A86LIB library tool, 13-5
AAD with operand, 5-4
AAM with operands, 5-4
about the author, 1-6
ABS operator in EXTRN, 10-6
absolute segments in OBJ mode, 10-10
address listing control, 3-4
address override byte, 6-5
address, my, 1-1
align operand list, 10-9
align specification, 10-9
alignment using EVEN, 9-3
allocation directives, 9-3
ampersand, use to specify standard input, 3-8
AND expression operator, 8-6
angle brackets in MASM, 12-4
arithmetic on floating-point numbers, 7-4
arithmetic, 32-bit with LEA, 6-3
ASP Ombudsman, 1-7
assembler variables, 9-10
assertion checking, 9-9
ASSUME directive, 6-4
asterisk multiplication operator, 8-5
AT combine type, 10-10
at-sign @, in symbols, 4-1
attribute operators/specifiers, 8-8
AUTOEXEC.BAT, 3-7
automatic paging control, 3-6
automatic paging controls, 13-2
B operator in EXTRN, 10-6
B override expression operator, 8-8
B-before operator in macros, 11-6
base registers, 6-2
base, default, 12-2
based structure example, 6-2
based structures, 9-6
bases for numbers, 8-1
bases, ambiguous, 8-2
batch file controls, 11-14
BCD numbers, 7-5
benefits of registration, 1-3
BIN extension for object files, 9-2
BIN extension, 3-2
binary base, 8-1
Binary Coded Decimal numbers, 7-5
biography, 1-6
BIOS interface, books on, 3-1
BIT expression operator, 8-6
block-structure in MASM, 12-4
17-2
books on assembler, recommended, 3-1
Boolean negation operator, 8-6
BP indexing size anomaly, 6-5
brackets, 8-9
British contact, 1-1
bugs, reporting, 1-7
built-in constant names, 7-4
built-in symbols, 16-1
built-in symbols, equates to, 9-8
BY operator, 8-4
BYTE align type, 10-9
BYTE override expression operator, 8-8
C programming language, linking to, 10-1
C switch, 3-2
C-loops in macros, 11-5
capacity, 1-5
capacity, source file, 3-9
case sensitivity, 3-2
case-insensitive comparisons, 8-8
catalog file A86.LIB, 13-5
categories of A86 elements, 4-1
cb specifier, 6-7
cd specifier, 6-7
changing the default base, 8-2
character loops in macros, 11-5
characters allowable in symbols, 4-1
characters recognized in A86 language, 4-2
choices for 87 operands, 7-6
class name, specifying, 10-11
classes, 10-4
clear-register macro, 11-1
clear-register macro, 11-5
closing of macro loops, 11-10
CODE ENDS directive, 9-2
code generation of forward references, 9-7
code label specifier, 6-7
CODE SEGMENT directive, 9-1
CODE segment, link to Pascal, 10-11
colon operator, 8-10
colon, deciding when to use, 4-4
columnar output, 2-2
COM extension, 3-2
COM programs, how to detect, 12-1
combine operand list, 10-9
combine specification, 10-9
combine types, 10-9
combining switches, 3-7
COMMENT directive, 4-2
comments in macros, removal of, 11-2
comments, 4-2
COMMON combine type, 10-10
comparison of strings, 8-7
COMPAT.8 macro file, 12-2
compatibility, 12-1
compression of macro text, 11-2
Compuserve section, 1-7
computation models, 10-2
17-3
concatenating terms in an expression, 8-5
conditional assembly and macros, 11-13
conditional assembly, 11-11
conditional calls, see IF, 5-1
conditional jump, far, see IF, 5-1
conditional line filtering, 13-1
conditional returns, 5-2
conditionals, list control, 3-4
constant operand to FLD, 7-4
constants, floating, 8-3
constants, format of, 8-1
constants, large, 9-5
constants, overview, 4-4
contacting me, 1-7
contents, 0-3
control-character notation, 8-5
controls, invocation, user-definable, 11-14
converting MASM programs, 12-1
CPU-specific instructions, 3-5
crashes, system, on lack of FWAIT, 7-2
creating programs to assemble, 3-1
credit cards, 1-1
cross reference demo, 2-2
cross reference listing, 13-3
cross-reference output switch, 3-7
cw specifier, 6-7
D operator in EXTRN, 10-6
D override expression operator, 8-8
D switch, 3-2
data allocation statements, samples, 4-1
DATA ENDS directive, 9-2
DATA SEGMENT directive, 9-1
DATA segment, link to Pascal, 10-11
DB directive, 9-3
DD directive, 9-3
DD examples, 9-5
DEC, multiple and numeric operands, 5-1
decimal base, 8-1
decimal output of macro operands, 11-8
DEF operator, 8-10
default base, changing, 8-2
default base, decimal, 3-2
default bases, 8-1
default forward references, 3-3
default output file name, 3-9
default segment registers, 6-3
default segment, OBJ mode, 10-12
defined symbols, testing for, 8-7
defining macros, 11-1
demonstration, 2-1
description of 87 instructions, 7-6
description of instructions, 6-9
Dettmann, Terry, 3-1
digits in file names, 3-9
digits, hex, 8-1
directives in a86, 9-1
directives, samples, 4-1
17-4
displacement field, 6-5
displaying macro expansions, 11-11
division operator, 8-5
dollar sign $, in symbols, 4-1
dollar sign operator, 8-11
DOS interface, books on, 3-1
double hash ## signs in macros, 11-2
double hash signs ## in macros, 11-13
double-precision, 7-5
double-quotes in strings, 9-5
doubleword indexing, 6-2
doubleword pointer initialization, 9-5
DQ directive, 9-3
DQ example, 9-5
DT directive, 9-3
DT example, 9-5
DUP construct, 9-4
duplicate definitions, 9-9
DW directive, 9-3
DWORD override expression operator, 8-8
E switch, 3-2
e-mail address, 1-7
EA byte, 6-5
eb specifier, 6-7
EBP indexing size anomaly, 6-6
ed specifier, 6-7
editing programs, 3-1
effective addresses, 6-1
effective addresses, encoding, 6-5
electronic mail, 1-7
ELSE, 11-12
ELSEIF, 11-12
EM end-of-macro symbol, 11-1
emulation, floating-point, 7-2
encoding of effective addresses, 6-5
encoding of floating-point numbers, 8-3
END directive, 10-7
end of a macro, 11-1
end of file, 10-7
END used as an operand value, 9-7
ENDIF, 11-12
ENDM, 12-3
ENDP directive, 9-11
ENDS directive, OBJ mode, 10-11
ENDS directives in COM mode, 9-2
English contact, 1-1
environment string, invocation equates in, 11-15
environment variable A86LIB, 13-6
environment variable, a86, 3-7
EQ expression operator, 8-7
EQ in comparing strings, 8-7
EQU directive, 9-7
equal-sign string compare, 8-8
equals-sign directive, 9-10
equates to built-in symbols, 9-8
equates to interrupts, 9-9
ER end-of-repeat symbol, 11-4
17-5
ERDEMO.BAT batch file, 2-1
ERR extension, 3-2
error file redirection, 3-2
error messages, 1-5
error messages, explanation, 14-1
evaluating macro operands, 11-8
EVEN directive, 9-3
ew specifier, 6-7
EX exit macro symbol, 11-10
examples of A86 statements, 4-1
examples of floating constants, 8-3
examples of numbers, 4-2
examples of type matching, 4-5
examples of useful memory accesses, 6-4
exclamation point operator, 8-6
exclusive features, 5-1
EXE programs, how to detect, 12-1
exiting from middle of macro, 11-10
EXITM simulation, 11-10
EXITM, 12-3
EXMAC, what happened to, 11-11
explicit EXTRNs, 3-4
explicit EXTRNs, forcing, 10-7
explicit OBJ specification, 10-1
explicit public names, 10-5
explicit WAITs, 7-1
exponent specifier, 8-3
expressions and forward references, 9-7
expressions in conditional assembly, 11-11
extended-precision operands, 7-5
extensions of source files, 3-9
external names and LINK, 10-3
extra coprocessor support, 7-2
EXTRN directive, 10-6
EXTRNs, explicit, 3-4
F operator in EXTRN, 10-6
F override expression operator, 8-8
F switch, 3-3
f switch, 7-3
FALSE in conditional assembly, 11-12
FALSE return value, 8-7
far label constants, 8-10
FAR override expression operator, 8-8
FBANK instruction on IIT-2C87, 7-2
FDISI instruction, 7-1
features, exclusive, 5-1
FENI instruction, 7-1
file breaks, listing control, 3-6
file in which a symbol was defined, 13-4
file lists, 3-9
file maintenance, 3-9
file names, digits in, 3-9
files, source, 3-1
filtering conditional lines, 13-1
FLD, immediate operand, 7-4
floating constants, examples of, 8-3
floating point operand types, 7-5
17-6
floating point operands, choices for, 7-6
floating point stack, 7-3
floating-point constants, format of, 8-3
floating-point emulation, 7-2
floating-point processor, 7-1
footprint, code generation, 1-3
forcing explicit EXTRNs, 10-7
forcing explicit EXTRNs, 3-4
forcing library lookup, 13-7
format of assembler source lines, 4-3
format of macros, 11-2
formfeed control, 3-6
FORTRAN, 10-10
forward references, 12-2
forward references, 9-6
forward references, default, 3-3
fragments, 10-3
FSETPM instruction, 7-1
FSTSW AX form, 7-1
FWAIT instruction, 7-1
G switch and EXTRNs, 10-7
G switch, 3-3
gaps in code, page breaks at, 13-3
GE expression operator, 8-7
Great Britain contact, 1-1
greater-mark ">" for local symbols, 5-3
GROUP directive, 10-12
groups, reason for, 10-3
GT expression operator, 8-7
H switch, 3-4
hash sign # in invocation, 13-7
hash sign #, conditional assembly, 11-11
hash signs # in macros, 11-13
hash signs # in macros, 11-2
hash signs #, literalizing in macros, 11-2
hex address listing control, 3-4
hex object lines, extra, 3-4
hexadecimal base, 8-1
HIGH operator, 8-4
high-level language computation models, 10-2
history of A86, 15-1
I switch, 3-4
ib specifier, 6-8
IBM, 12-1
IEEE standard for floating-point, 8-3
IF conditional assembly symbol, 11-11
IF statement, 5-1
IFDIF, 12-3
IFE, 12-3
IFIDN, 12-3
IIT-2C87 support, 7-2
immediate operand to FLD, 7-4
implicit public names, 10-5
INC, multiple and numeric operands, 5-1
incentives to register, 1-3
INCLUDE directive, 9-12
include file listing control, 3-6
17-7
INCLUDE with no file name, 13-7
indefinite repeats, 11-5
indentation of source listing, 3-4
indentation of wraparound lines, 3-7
index expressions, 8-4
index registers, 6-2
indexed memory, 6-2
inferior assemblers, 12-1
inferior assemblers, porting to, 12-5
initializations of floating-point, 7-3
instruction set chart, explanation, 6-7
instruction set, 87, 7-6
instruction statements, samples, 4-1
instructions on specific CPUs, 3-5
instructions, list of, 6-9
instructions, special, 6-8
integer operands to 8087, 7-5
Intel assembler, 12-1
Intel meeting, 10-3
intermediate numeric results, 7-5
Internet mail address, 1-7
interrupt equates, 9-9
interrupts, grabbing, 12-2
invocation variables in environment string, 11-15
invocation variables, 11-14
invoking A86, 3-1
IRET operand, 5-2
IRP and IRPC functionality, 11-1
IRP, 12-3
IRPC, 12-3
iw specifier, 6-8
JHASH example, 11-10
juxtaposing terms in an expression, 8-5
K base for numbers, 8-2
keyboard entry coding example, 11-3
L last-operand in macros, 11-5
L switch for listing, 13-1
L switch, 3-4
L2E and L2T constants, 7-4
LABEL directive, 9-11
labels, examples, 4-4
large constant initialization, 9-5
large macro operand numbers, 11-9
large model of segmentation, 10-2
last-operand in macros, 11-5
LE expression operator, 8-7
LEA and 32-bit arithmetic, 6-3
LEA instruction, optimizing, 3-3
LEA optimization, 5-4
leading underscore, in C, 10-1
legal terms, 1-1
length byte, generating in macro, 11-8
length of a symbol name, 4-2
LG2 constant, 7-4
library search, trigger in source, 9-12
line numbers, suppressing, 3-4
line-format, 4-3
17-8
LINES.8 library file, 2-1
LINK program, 10-3
linkage, 10-1
LIST directive (leading period), 13-2
list of instructions, 6-9
listing control directives, 13-2
listing control switches, 13-1
listing hex object bytes, 3-4
listing in A86, 13-1
listing indentation of source, 3-4
listing of 87 instructions, 7-6
listing of cross references, 13-3
listing, specific formats, 13-1
listings, how to activate, 3-4
LN2 constant, 7-4
loading named segments, 12-2
local labels in macros, 11-10
local labels, simulating, 12-6
local symbols, 5-3
local symbols, specifying, 9-10
location, this, operator, 8-11
logical operators, 8-6
long default jump, 3-3
LONG expression operator, 8-8
looping in macros, 11-4
loops with large index, 11-9
LOW operator, 8-4
lower case letters in symbols, 3-2
LST file, producing, 13-1
LT expression operator, 8-7
m specifier, 6-8
macro compatibility, 12-2
macro exiting from within loop, 11-10
macro expansions, displaying, 11-11
macro file, default, 3-8
macro libraries, making, 13-5
macro listing global control, 3-4
macro loops, closing, 11-10
macro loops, skipping increments, 11-6
macro operand substitution, 11-2
macro operands, computing number, 11-9
macros and conditional assembly, 11-13
macros, 11-1
macros, defining, 11-1
mailing list, 1-4
main module, 10-3
MAIN symbol, 10-7
maintenance of files, 3-9
manual, scope of, 3-1
MASM compatibility, 12-1
MASM compatible CODE, DATA, 10-11
MASM conditional assembly, simulating, 11-14
matching of types, examples, 4-5
matrix multiplication on IIT-2C87, 7-2
maximum length of a symbol name (127), 4-2
maximum source file size, 3-9
meeting at Intel, 10-3
17-9
MEMORY combine type, 10-10
memory forms, overlooked, 6-4
memory operand forms to 87 instructions, 7-5
memory requirements, 3-9
memory resident code, 12-2
memory variables, specifying, 6-1
menu systems and A86, 3-8
Microsoft, 12-1
minus operator, 8-5
MIX tool, compatibility, 3-3
mixing constant types in word inits., 8-5
mnemonics, 8086, 6-9
mnemonics, one for many instructions, 4-5
MOD modulo operator, 8-5
model of segmentation, grotesque, 10-3
ModRM byte, 6-5
module names, 10-5
modules, object, 10-3
MOV immediate into segment reg, 5-2
MOV of memory operands, 5-2
MOV of segment registers, 5-2
MOV substitute for LEA, 5-4
MOV with three operands, 5-2
move-memory macro example, 11-1
MOVSx, numeric operand to, 5-1
MSDOS.8 library file, 2-1
MTCOLS.BAT batch file, 2-2
multiple allocation using DUP, 9-4
multiple files in OBJ mode, 10-1
multiple increments in macro loops, 11-6
multiple operands to PUSH,POP,INC,DEC, 5-1
multiply by 10 coding example, 10-1
multiply operator, 8-5
NAME directive, 10-5
name of output files, 3-1
NE expression operator, 8-7
NE in comparing strings, 8-7
NEAR expression operator, 8-9
NEC chips, lack of AAD with operands, 5-4
NEC chips, special instructions, 6-8
NEC instructions, allowing, 3-5
negation, Boolean, 8-6
negative R-loops in macros, 11-7
nested IF blocks, 11-12
nested PROCs, lack of, 9-10
nesting of loops in macros, 11-8
new file listing control, 3-6
NIL prefix, 9-9
NOLIST directive (leading period), 13-2
non-combinable segments, 10-10
NOP and EVEN directive, 9-3
Norton, Peter, 3-1
NOT expression operator, 8-6
null invocation names, 11-15
null operands to macros, 11-3
number operands in expressions, 8-3
numbering, suppressing, 3-4
17-10
numbers, examples, 4-2
numbers, examples, 8-1
numbers, floating, 8-3
numbers, format of, 8-1
numeric operands to INC,DEC, 5-1
numeric operands to STOSx,MOVSx, 5-1
O switch, 10-1
O switch, 3-2
O switch, 3-5
OBJ extension, 3-2
OBJ file generation, 3-5
OBJ internal optimization, 3-3
OBJ production made easy, 10-1
object file name, 3-1
object modules, 10-3
octal base, 8-1
OFFSET expression operator, 8-9
Ombudsman, ASP, 1-7
online support, 1-7
opcodes, 8086, 6-9
opcodes, 87, 7-6
operand choices for 87 instructions, 7-6
operand number, generating, 11-9
operand override byte, 6-6
operand types to 87 instructions, 7-5
operating system requirements, 3-9
operation of A86, 3-1
operator precedence, 8-12
Optimized LEA instruction, 5-4
OR expression operator, 8-6
ORG directive, 9-2
outer segment, OBJ mode, 10-12
output files, naming, 3-1
overlooked memory forms, 6-4
overrides, 32-bit, 6-6
overrides, segment, 12-2
overrides, segment, 6-4
overview of A86, 1-4
overview of expressions, 8-3
P switch, 3-5
page breaks, automatic, 13-3
page breaks, manual, 13-3
PAGE directive, 13-2
page numbers, column control, 3-7
PAGE specifier, 10-9
PAGE.8 program, 2-1
PAGE.BAD source file, 2-1
PAGE.COM program, 2-1
pagination control switch T, 3-6
paging, automatic, 3-6
PARA specifier, 10-9
parameters, MASM local, 12-4
parenthesized operand numbers, 11-9
Pascal segment names, 10-11
Pascal, linking to, 10-2
passing macro operands by value, 11-8
Pentium instructions, 6-8
17-11
period as first character of a symbol, 4-1
period operator, 8-5
permanent switch settings, 3-7
phone number, my, 1-1
PI constant, 7-4
piping file names to A86, 3-8
plus operator, 8-5
POP, multiple operands, 5-1
POPA simulation for 8088, 3-5
port programs to inferior assemblers, 12-5
pound sign #, SEE hash sign
Power C, compatibility, 3-3
powers of ten, 8-3
precedence of operators, 8-12
prices, 1-2
printer eject program, 2-1
PROC directive in MASM, 12-4
PROC directive, 9-10
procedure-level summary listings, 13-3
procedures, 9-10
processor control, 3-5
processor-specific instructions, 6-8
program invocation, A86, 3-1
program location operator, 8-11
program size in expressions (END), 9-7
program starting location, OBJ mode, 10-7
programs, how to create, 3-1
prompt for file names, 3-8
PTR operator, 8-5
Public Brand Software, 3-1
PUBLIC combine type, 10-9
PUBLIC directive, 10-5
public names and LINK, 10-3
PUSH multiple operands, simulating, 12-5
PUSH, multiple operands, 5-1
PUSHA simulation for 8088, 3-5
Q operator in EXTRN, 10-6
Q override expression operator, 8-8
question mark ?, in symbols, 4-1
question-mark operator, 9-4
quoted-string macro operands, 11-3
QWORD override expression operator, 8-8
R-loops in macros, 11-4
R-loops, negative, 11-7
RADIX directive, 8-2
rb register specifier, 6-8
red tape, 1-4
red tape, 10-1
redefinable symbols, 5-3
redefining invocation variables, 11-15
redefining symbols, 9-9
redirection of error files, 3-2
REF operator, 8-10
references of symbols, listing, 13-3
registers, 8086, 4-3
registers, general, 6-1
registration benefits, 1-3
17-12
registration benefits, 13-5
relational operators, 8-7
release history, A86, 15-1
relocation and linkage, 10-1
repeat counts to string instructions, 5-1
repeating code using DUP, 9-4
REPT directive, simulating, 11-9
requirements, system, 3-9
reserved symbols, 16-1
reserved symbols, 4-2
RET instruction, meaning of, 9-10
RET operand, 5-2
RETF instruction and PROC, 9-10
RETF operand, 5-2
REV.8 source file, 2-1
REV.COM program, 2-1
reversing strings example, 2-1
rotate immediate simulation for 8088, 3-5
rw register specifier, 6-8
S switch, 3-5
samples of A86 statements, 4-1
scaled indexing, 6-3
scientific notation, 8-3
section number control, 3-6
section numbers, controlling, 13-2
SEG operator, 10-13
SEGMENT AT, non-OMF, 12-5
SEGMENT directive, non-OBJ mode, 12-5
SEGMENT directive, OBJ mode, 10-8
segment override colon operator, 8-10
segment overrides, 12-2
segment overrides, 6-4
segment registers managed by GROUP, 10-12
segment registers, default, 6-3
segmentation and memory access, 6-3
segmentation models, 10-2
segments in A86, 9-1
segments, loading named, 12-2
selective NOLIST for macros (#H), 13-2
shareware distribution, 1-1
shift immediate simulation for 8088, 3-5
shifting expression operators, 8-6
SHL and SHR expression operator, 8-6
SHORT expression operator, 8-8
simple macro syntax, 11-1
single-precision, 7-5
size of effective addresses, 6-5
size of macro operands, 11-8
size of program in expressions (END), 9-7
size of source files, 3-9
size of structures, 8-11
skipped lines, suppressing, 3-4
slash division operator, 8-5
slash specifier, 6-5
small model of computation, 10-2
source file as default TITLE, 3-6
source files, 3-1
17-13
source libraries, 13-5
special instructions, 6-8
Specialty Software, 7-2
speed, 1-4
square brackets operator, 8-9
ST floating-point stack specifier, 8-10
STACK combine type, 10-9
STACK segment, relocatable, 10-11
stack segments in OBJ mode, 10-9
stack, floating point, 7-3
standard input command tail, 3-8
starting location, OBJ mode, 10-7
STOSx, numeric operand to, 5-1
strategies for file maintenance, 3-9
string allocation, 9-5
string comparison operators, 8-7
STRUC directive, 9-5
STRUC, implicit via SEGMENT AT, 12-5
structure initialization, 12-4
structure, based, example, 6-2
structured programming constructs, 5-1
structures and MASM, 12-4
structures, size of, 8-11
sub-directories of programs, 3-9
substitution of macro operands, 11-2
subtitle default to source file, 3-6
subtraction operator, 8-5
SUBTTL subtitle directive, 13-2
summary of procedure calls, 13-3
suppressing line numbers, 3-4
suppressing list controls, 3-4
suppressing skipped lines, 3-4
suppressing symbols file, 3-5
switches, assembler, 3-2
switches, combining, 3-7
switches, user-definable, 11-14
SYM extension, 3-2
symbol listing control, 3-5
symbol table file name, 3-2
symbols file, suppressing, 3-5
symbols, allowable characters for, 4-1
symbols, MASM local, 12-4
symbols, redefining, 9-9
symbols, reserved, 16-1
system crashes on lack of FWAIT, 7-2
system requirements, 3-9
T operator in EXTRN, 10-6
T override expression operator, 8-8
T switch, 3-6
table of contents, 0-3
tabs, recommendation against, 4-3
TBYTE override expression operator, 8-8
TCOLS.8 source file, 2-2
TCOLS.COM program, 2-2
telephone number, my, 1-1
terms, legal, 1-1
TEST with one operand, 5-4
17-14
Texas invocation switch, 11-14
Texas, 11-12
TEXT segment name, 10-12
THIS operator, 8-11
tips for memory access, 6-4
TITLE default to source file, 3-6
TITLE directive, 13-2
titling control switch T, 3-6
TO in invocation, 3-1
TRUE in conditional assembly, 11-12
TRUE return value, 8-7
truncation of listing lines, 3-7
Turbo Pascal segment names, 10-11
Turbo Pascal, linking to, 10-2
type matching, examples, 4-5
TYPE operator, 8-11
types in the a86 language, 4-3
types, assumed, 10-2
UND undefined symbols file, 10-6
undefined symbol types, assumed, 10-2
undefined symbols listing in OBJ mode, 10-6
underscore, in symbols, 4-1
underscore, leading, in C, 10-1
underscores within numbers, 8-1
unusable user symbols, 16-1
up arrow symbol and invocation equates, 11-15
USAGE.8 library file, 2-1
user symbols, 4-2
USES clause, converting, 12-4
value, passing by, 11-8
variable forward references, 9-7
variable operands in expressions, 8-3
variables declared at invocation, 11-14
variables, 9-10
variables, examples, 4-3
verbose forms, floating point, 7-3
verbose PROC, 9-10
version history, A86, 15-1
W operator in EXTRN, 10-6
W override expression operator, 8-8
W switch, 3-7
WAIT instruction, 7-1
Wettstein, Greg, 1-7
widowed listing lines, avoiding, 13-2
wild cards in source files, 3-2
wild cards, order of, 3-9
WORD align type, 10-9
WORD override expression operator, 8-8
wraparound listing control, 3-7
X specifier for numeric bases, 8-1
X switch, 3-7
XCHG of memory operands, 5-3
XCHG with segment register, 5-3
XOR expression operator, 8-6
XREF output switch, 3-7
XRF files, producing, 13-3