Contents of the A86.DOC file
This is intended as a guide to get A86 to work for all the
programs in the Tutor. It only covers things that won't work or
things A86 does differently. It does not cover any of the
benign options like local labels.
===== CHAPTER 1
You need to take your text editor and change the last line of the
template files. At the moment they read:
You may either eliminate the line or change it to:
If you don't, you will get this error message:
END start~40 Conflicting Multiple Definition Not Allowed~
Do this for all the original template files, because this line
will always cause an error. You will find out why when you get to
You should also insert the word PUBLIC just before the line with
ASSUME. Do this in all the template files.
ASSUME cs:CODESTUFF, ds:DATASTUFF
You will find out why in Chapter 15.
A86 has some unusual defaults, so you need to change them when
you assemble a file. If your file is named myprog.asm, the
command line you want to use for the rest of this tutorial is:
>a86 +DOSX myprog.asm
You must use the file extension .asm when you call the program.
You can make a batch file (let's call it QASM.BAT) which has:
a86 +DOSX %1.asm
Then all you need to do is:
Those four options on the command line are:
The PC Assembler Tutor - Copyright (C) 1990 Chuck Nelson
The PC Assembler Tutor 2
+D numbers with leading 0s are default decimal
+O make an object file
+S don't create an ancillary symbol table
+X require specific declaration of external information
They should be used from now on. When you are through with all
the chapters, you can decide whether you want to continue using
them all. If you are using D86, you need to eliminate the 'S'.
The declaration should be +DOX since you will need the symbol
===== CHAPTER 2
Please read all of chapter 2 before you read these comments.
The defaults and definitions are the same with two exceptions.
First, any number that begins with a '0' is hex by default. That
is, 22 is a decimal number and 022 is a hex number. This has some
serious side effects. Take the number:
This is 847, right? No. It is 0847Dh = 34,637. In Chapter 7 we
will use these binary numbers:
These should be 75 and 4 respectively, but A86 evaluates them as
01001011Bh = 268500992 and 0100Bh = 4107. Since half of the
binary numbers you use will start with a 0, half of your binary
numbers will be wildly incorrect. In order to correct the
situation, you need to put a +D on the command line. This is the
'D' of +DOSX. The D will insure that all numbers starting with 0
will be decimal. This gets rid of all the side effects.
Alternatively, you can put:
at the top of your files before any of the code or data. This has
the same effect. Of course, if you really do want hex numbers,
this can be overridden with a specific 'h' after any number.
There is another major problem with data definitions. Let's say
that you want the following definitions:
weight dw ?
cost dw 20
profit dw ?
but you forget to put in some of the initializations in your text
file (a situation which is not unknown):
Using A86 3
profit dw ?
All other assemblers will generate an error. You must either put
in an initial value or you must say that you want no initial
value (by putting in a question mark). Not only does A86 not
generate an error, it does something strange. If there is neither
initialization nor a question mark, A86 will calculate an address
for the variable but WILL ALLOCATE NO SPACE FOR IT. What this
means is that in our above example, 'weight', 'cost', and
'profit' will all be at the same memory address. 'Weight' and
'cost' will have the same address with no space allocation.
'Profit' will be at the same memory address too, but will have
space allocated for it.
This is all done silently, so you don't know that this is being
done. There is no way to shut this off. You might be able to find
that this is happening by looking at the symbol table, but that
means that you suspect that it is happening. What you need to
do whenever you use A86 is:
ALWAYS CHECK ALL DATA TO MAKE SURE THAT IT IS INITIALIZED OR
HAS A QUESTION MARK
===== CHAPTER 10
We now come to some actual differences. A86 does not produce a
list file. You can read the justification for this in your
documentation. Does this make a difference? It would be nice to
have one, but we can normally live without it. Just follow what
is happening with the MASM listing.
p94 - ASSUME statements. Both TASM and MASM keep track of how you
want the segments to be referenced. A86 doesn't. It simply
ignores any ASSUME statements. This means that any segment
overrides must be coded into the text file with:
mov cx, ss:variable4
mov cx, es:variable2
mov cx, ds:variable1
mov cx, cs:variable3
A86 assumes that all code uses CS (which it must), and that all
data uses DS unless there is a specific segment override. Is this
a big imposition? Not really. If you use a segment register other
than DS, it is normally for dealing with arrays, and in those
cases you need a segment override anyways. You will find out
about that in the next chapter.
p97 - END statements. END is not necessary in A86. It knows that
the end has come when the file is finished. The default starting
point for an A86 file is the label 'main'. If A86 sees a label
name after an END statement, then it RENAMES that word 'main',
and renames all occurances of that word in the file 'main'. It
does not change the default starting name. This means that if you
The PC Assembler Tutor 4
have a statement like:
and you also have the label 'main' in your file, A86 will change
all occurances of 'start' to 'main', causing multiple use of the
======== Chapter 15
p154 - You do not need PUSHREGS and POPREGS. With A86, PUSH is
exactly the macro PUSHREGS:
PUSHREGS ax, bx, cx, dx, si
PUSH ax, bx, cx, dx, si
These are exactly the same. POP shows the actual order that
things will be popped, while POPREGS has the reverse order so
that you can use a word processor to copy the PUSHREGS part. For
the above PUSH declaration, this is the correct POP:
POP si, dx, cx, bx, ax
POPREGS ax, bx, cx, dx, si
From now on, whenever you see PUSHREGS, change it to PUSH, and
whenever you see POPREGS, change it to POP but reverse the order
of registers so that it is the actual order in which things are
POPped. You can delete the line:
from your template file.
; - - - - - - - - - -
Please read the whole chapter before reading the rest of these
For some reason, A86 makes ALL normal variables and labels PUBLIC
unless you specifically tell it not to. The whole thrust of
programming for the last 20 years (PASCAL, C, and all structured
languages), has been to make NOTHING public unless specifically
requested, so this is an unwelcome default setting. You turn it
off by naming any normal (but not local) variable PUBLIC. In
fact, if you use the word PUBLIC alone:
without any name after it, A86 will turn this off. That is why
you put it in all the template files. Always have this in all
your assembler files.
A86 also assumes that any variable that has no data declaration
is EXTRN. This is a bad policy. What will happen is the
following. You are using the variable 'last_occurance' and you
Using A86 5
misspell it 'last_ocurrance'. A86 sees no data declaration so
assumes that it is an external variable and assembles the file.
Three hours later you link the 6 modules of your program together
and you get a link error. The linker cannot find 'last_ocurrance'
Just as you should need to explicitly name things PUBLIC, you
should need to explicitly name things EXTRN. You do this by
putting +X (forced external declarations) on the command line.
This is the 'X' in the '+DOSX' that you have been using on the
===== CHAPTER 21
You need to change the ORG statement so it is in front of main
main proc near
This is because you are using main as the starting address, so it
must be at 100h. This 100h is optional with A86. If it is making
a .COM file it automatically starts at 100h. A86 is designed to
give you a .COM file directly, so all you need to do with a
single file is:
>a86 +DS myfile.asm
and you will get MYFILE.COM as the output file. In the example
where we make a .COM file from multiple files, these files are
set up to be .OBJ files. If you want to make them into a .COM
file directly, you need to take out all PUBLIC, EXTRN and END
statements (and adjust PUSHREGS and POPREGS) and then do:
>a86 +DS prog1.asm prog2.asm prog3.asm
making sure that prog1.asm is first. The output file should be
===== CHAPTER 26
You need to read all of Chapter 26 before reading any of the
A86 will work fine with any standard segment definitions. It also
has two special segment statements of its own. The first:
will generate the following:
_TEXT SEGMENT PUBLIC 'CODE'
The second statement:
The PC Assembler Tutor 6
is NOT a segment declaration. It generates NO segment, it
allocates NO space and it initializes NO data. What is it? I'll
explain how it operates, but I have no idea why it exists.
The first time you use the 'DATA SEGMENT' instruction in a file
it is followed by ORG:
ORG relocates the counter for where the assembler is allocating
space in memory. From this point on, every time you define
time dw ?
distance dw ?
space dw ?
A86 generates an distinct address for each variable. However, it
ALLOCATES NO SPACE. This is just an address that the code can use
when it refers to the variables. If you have the following
year dw 1990
prime dw 73
cost dw 5167
A86 will generate address for these variables but (1) will
allocate NO space, (2) will do NOTHING with those initializing
values and (3) WILL NOT COMPLAIN that you have tried using
initialized data in a DATA SEGMENT statement. A86 will do the
year dw ?
prime dw ?
cost dw ?
This data is technically in the CODE SEGMENT. If the code is
longer than that initial ORG number, some of the code will be in
the same place as some of the data and if you write to the data
you will overwrite the code. A86 will not complain.
For instance, we had ORG 1000h (4096d). If the code is 6000 bytes
long, the last 2000 bytes of code will share the space with the
data. This leads to either bad data or bad code or both.
Why have this? Well, when DOS loads a .COM file into memory, it
uses ALL of memory. If I have:
INTSCRN.COM 541 07/23/90 17:45
a .COM file that is 541 bytes long, DOS will allocate about
550,000 bytes for it on my computer. 549,459 bytes of this are
wasted space. It is A86's idea to put data in this wasted space.
There is no reason for this, so don't do it. If you have a .COM
file, put all your data in the CODE SEGMENT. If you have an .OBJ
Using A86 7
file you need to create a legitimate SEGMENT for the DATA. Its
name cannot be:
DATA SEGMENT PUBLIC 'DATA'
If I have the following program:
; - - - - - - - - - - - - - - -
DATA SEGMENT PUBLIC
data1 db "This is the output string", 13, 10, "$"
data2 db 100 dup (0)
mov ax, seg DATA
mov ds, ax
mov ah, 09h ; print string
lea dx, data1
mov ax, 4C00h ; exit
; - - - - - - - - - - - - - - -
and I try to make an object file with it, I get the following
mov ax, seg DATA~61 Overlapping Local Not Allowed~
The ability to put the segment starting address in the segment
register is a minimal requirement for doing anything. This
effectively eliminates the possibility of using DATA as the name
for a segment. Therefore, those of you who use Turbo Pascal need
DSEG SEGMENT PUBLIC
as an alternative. This will work with no problems.