


                                                                             1

                                      USING  A86


             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:

                 END start

             You may either eliminate the line or change it to:

                 END main

             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
             Chapter 10.

             You should also insert the word PUBLIC just before the line with
             ASSUME. Do this in all the template files.

                 PUBLIC
                 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:

                 >qasm myprog

             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
             table. 


             ===== 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:

                 0847d

             This is 847, right?  No. It is 0847Dh = 34,637. In Chapter 7 we
             will use these binary numbers:

                 01001011b
                 00000100b

             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:

                 RADIX 10

             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):

                 weight    dw    




             Using A86                                                       3
             _________

                 cost      dw    
                 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:

                 END start

             and you also have the label 'main' in your file, A86 will change
             all occurances of 'start' to 'main', causing multiple use of the
             same label.


             ======== 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:

                 include \pushregs.mac

             from your template file.

             ; - - - - - - - - - -

             Please read the whole chapter before reading the rest of these
             comments.

             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:

                 PUBLIC

             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'
             anywhere. 

             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
             command line.


             ===== CHAPTER 21

             You need to change the ORG statement so it is in front of main

                 ORG 100h
                 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
             prog1.com.


             ===== CHAPTER 26

             You need to read all of Chapter 26 before reading any of the
             following.

             A86 will work fine with any standard segment definitions. It also
             has two special segment statements of its own. The first:

                 CODE SEGMENT

             will generate the following:

                 _TEXT SEGMENT PUBLIC 'CODE'

             The second statement:

                 DATA SEGMENT




             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:

                 DATA SEGMENT
                 ORG 1000h

             ORG relocates the counter for where the assembler is allocating
             space in memory. From this point on, every time you define
             variables:

                 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
             variables:

                 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
             equivalent of:

                 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) 
                 ENDS 

                 CODE SEGMENT 

                 main: 
                         mov     ax, seg DATA
                         mov     ds, ax 
              
                         mov     ah, 09h         ; print string 
                         lea     dx, data1 
                         int     21h 

                         mov     ax, 4C00h       ; exit 
                         int     21h 
                 ; - - - - - - - - - - - - - - - 

             and I try to make an object file with it, I get the following
             error:

                      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
             to use:

                 DSEG  SEGMENT PUBLIC

             as an alternative. This will work with no problems.

