home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / sharew / a86 / asm_doc / a12.doc < prev    next >
Encoding:
Text File  |  1988-02-08  |  13.2 KB  |  298 lines

  1. CHAPTER 12   COMPATIBILITY WITH OTHER ASSEMBLERS
  2.  
  3.  
  4. I gave heavy priority to compatibility when I designed A86; a
  5. priority just a shade behind the higher priorities of
  6. reliability, speed, convenience, and power.  For those of you who
  7. feel that "close, but incompatible" is like saying "a little bit
  8. pregnant", I'm sorry to report that A86 will not assemble all
  9. Intel/IBM/MASM programs, unmodified. But I do think that a vast
  10. majority of programs can, with surprisingly little massaging, be
  11. made to assemble under A86.  Furthermore, the massaging can be
  12. done in such a way as to make the programs still acceptable to
  13. that old, behemoth assembler.
  14.  
  15. Version 3.00 of A86 has many compatibility features not present
  16. on earlier versions.  Among the features added since A86 was
  17. first released are:  more general forward references, double
  18. quotes for strings, "=" as a synonym for EQU, the RADIX
  19. directive, and the COMMENT directive.  If you tried feeding an
  20. old source file to a previous A86 and were dismayed by the number
  21. of error messages you got, try again: things might be more
  22. manageable now.
  23.  
  24.  
  25. Conversion of MASM programs to A86
  26.  
  27. Following is a list of the things you should watch out for when
  28. converting from MASM to A86:
  29.  
  30. 1. You need to determine whether the program was coded as a COM
  31.    program or as an EXE program.  All COM programs coded for MASM
  32.    will contain an ORG 100H directive somewhere before the start
  33.    of the code.  EXE programs will contain no such ORG, and will
  34.    often contain statements that load named segments into
  35.    registers.  If the program was coded as EXE, you must either
  36.    assemble it (using the +O option) to an OBJ file to be fed to
  37.    LINK, or you must eliminate the instructions that load segment
  38.    registers-- in a COM program they often aren't necessary
  39.    anyway, since COM programs are started with all segment
  40.    registers already pointing to the same value.
  41.  
  42.    A good general rule is: when it doubt, try assembling to an
  43.    OBJ file.
  44.  
  45. 2. You need to determine whether the program is executing with
  46.    all segment registers pointing to the same value.  Simple COM
  47.    programs that fit into 64K will typically fall into this
  48.    category.  Most EXE programs, programs that use huge amounts
  49.    of memory, and programs (such as memory-resident programs)
  50.    that take over interrupts typically have different values in
  51.    segment registers.
  52.                                                              12-2
  53.  
  54.    If there are different values in the segment registers, then
  55.    there may be instructions in the program for which the old
  56.    assembler generates segment override prefixes "behind your
  57.    back".  You will need to find such references, and generate
  58.    explicit overrides for them.  If there are data tables within
  59.    the program itself, a CS-override is needed.    If there are
  60.    data structures in the stack segment not accessed via a BP-
  61.    index, an SS-override is needed. If ES points to its own
  62.    segment, then an ES-override is needed for accesses (other
  63.    than STOS and MOVS destinations) to that segment.  In the
  64.    interrupt handlers to memory-resident programs, the "normal"
  65.    handler is often invoked via an indirect CALL or JMP
  66.    instruction that fetches the doubleword address of the normal
  67.    handler from memory, where it was stored by the initialization
  68.    code.  That CALL or JMP often requires a CS-override-- watch
  69.    out!
  70.  
  71.    If you want to remain compatible with the old assembler, then
  72.    code the overrides by placing the segment register name, with
  73.    a colon, before the memory-access operand in the instruction.
  74.    If you do not need further compatibility, you can place the
  75.    segment register name before the instruction mnemonic.  For
  76.    example:
  77.  
  78.     MOV AL,CS:TABLE[SI]   ; if you want compatibility do this
  79.     CS MOV AL,TABLE[SI]   ; if not you can do it this way
  80.  
  81. 2. A86 is a bit more restrictive with respect to forward
  82.    references than MASM, but not as much as it used to be. You'll
  83.    probably need to resolve just a few ambiguous references by
  84.    appending " B" or " W" to the forward reference name.  One
  85.    common reference that needs a bit more recoding is the
  86.    difference of two forward references, often used to refer to
  87.    the size of a block of allocated memory.  You handle this by
  88.    defining a new symbol representing the size, using an EQU
  89.    right after the block is declared, and then replacing the
  90.    forward-reference difference with the size symbol.
  91.  
  92. 3. A86 has the feature, not seen in MASM, that the default base
  93.    for numbers with leading digit 0 is hexadecimal, not decimal.
  94.    This means that you must remove any leading zeroes from
  95.    decimal numbers in your old programs.  Note that all constants
  96.    other than those without leading zeroes and without trailing
  97.    base-specifiers are handled identically by A86 and by MASM.
  98.    The ONLY thing you need to worry about is decimal numbers with
  99.    leading zeroes.  Example: the old code line MOV AX,00100,
  100.    meaning decimal 100, should be recoded MOV AX,100, without the
  101.    leading zeroes.
  102.  
  103.    Alternatively, I have added the RADIX command, for
  104.    compatibility with the .RADIX command of IBM's assembler.  If
  105.    the program has a .RADIX command at the top of it, then my
  106.    assembler will handle constants identically to the IBM
  107.    assembler; if it does not, you can add a .RADIX 10 to the top
  108.    of the program, for complete compatibility.
  109.                                                              12-3
  110.  
  111.    For even greater convenience, I have added the +D switch,
  112.    which you can put into your A86 environment variable, to
  113.    achieve decimal functionality without a RADIX 10 command.
  114.  
  115. 4. A86's macro definition and conditional assembly language is
  116.    different than MASM's. Most macros can be translated by
  117.    replacing the named parameters of the old macros with the
  118.    dedicated names #n of the A86 macro language; and by replacing
  119.    ENDM with #EM.  Other constructs have straightforward
  120.    translations, as illustrated by the following examples:
  121.  
  122.    MASM construct              Equivalent A86 construct
  123.  
  124.    IFE expr                     #IF ! expr
  125.    IFB <PARM3>                  #IF !#S3
  126.    IFNB <PARM4>                 #IF #S4
  127.    IFIDN <PARM1>,<CX>           #IF "#1" EQ "CX"
  128.    IFDIF <PARM2>,<SI>           #IF "#2" NE "SI"
  129.    .ERR                         (any undefined symbol)
  130.    .ERRcond                     TRUE EQU 0FFFF
  131.                                 TRUE EQU cond
  132.    EXITM                        #EM
  133.    IRP ... ENDM                 #RX1L ... #ER
  134.    REPT 100 ...ENDM             #RX1(100) ... #ER
  135.    IRPC ... ENDM                #CX ... #EC
  136.  
  137.    The last three constructs, IRP, REPT, and IRPC, usually occur
  138.    within macros; but in MASM they don't have to.  The A86
  139.    equivalents are valid only within macros-- if they occur in
  140.    the MASM program outside of a macro, you duplicate them by
  141.    defining an enclosing macro on the spot, and calling that
  142.    macro once, right after it is defined.
  143.  
  144.    To retain compatibility, you isolate the old macro definitions
  145.    in an INCLUDE file (A86 will ignore the INCLUDE directive),
  146.    and isolate the A86 macro definitions in a separate file, not
  147.    used in an MASM assembly of the program.
  148.  
  149. 5. A86 supports the STRUC directive, with named structure
  150.    elements, just like MASM, with one exception: A86 does not
  151.    save initial values declared in the STRUC definition, and A86
  152.    does not allow assembly of instances of structure elements.
  153.  
  154.    For example, the MASM construct
  155.  
  156.    PAYREC STRUC
  157.       PNAME  DB 'no name given'
  158.       PKEY   DW ?
  159.    ENDS
  160.  
  161.    PAYREC 3 DUP (?)
  162.    PAYREC <'Eric',1811>
  163.                                                              12-4
  164.  
  165.    causes A86 to accept the STRUC definition, and define the
  166.    structure elements PNAME and PKEY correctly; but the PAYREC
  167.    initializations need to be recoded.  If it isn't vital to
  168.    initialize the memory with the specific definition values, you
  169.    could recode the first PAYREC as:
  170.  
  171.    DB  ((TYPE PAYREC) * 3) DUP ?
  172.  
  173.    If you must initialize values, you do so line by line:
  174.  
  175.    DB 'Eric         '
  176.    DW ?
  177.  
  178.    If there are many such initializations, you could define a
  179.    macro INIT_PAYREC containing the DB and DW lines.
  180.  
  181. 6. A86 does not support a couple of the more exotic features of
  182.    MASM assembly language: the RECORD directive and its
  183.    associated operators WIDTH and MASK; and the usage of angle-
  184.    brackets to initialize structure records.  These features
  185.    would have added much complication to the internal structure
  186.    of symbol tables in A86; degrading the speed and the
  187.    reliability of the assembler.  I felt that their use was
  188.    sufficiently rare that it was not worth including them for
  189.    compatibility.  I would like to hear some feedback on this.
  190.    Does anybody out there use these features heavily?  Will they
  191.    be missed in A86?
  192.  
  193.    If your old program does use these features, you will have to
  194.    re-work the areas that use them.  Macros can be used to
  195.    duplicate the record and structure initializations.  Explicit
  196.    symbol declarations can replace the usage of the WIDTH and
  197.    MASK operators.
  198.  
  199.  
  200. Compatibility symbols recognized by A86
  201.  
  202. A86 has been programmed to ignore a variety of lines that have
  203. meaning to Intel/IBM/MASM assemblers; but which do nothing for
  204. A86.  These include lines beginning with a period (except .RADIX,
  205. which is acted upon), percent sign, or dollar sign; and lines
  206. beginning with ASSUME, INCLUDE, PAGE, SUBTTL, and TITLE. If you
  207. are porting your program to A86, and you wish to retain the
  208. option of returning to the other assembler, you may leave those
  209. lines in your program.  If you decide to stay with A86, you can
  210. remove those lines at your leisure.
  211.  
  212. In addition, there is a class of symbols now recognized by A86 in
  213. its .OBJ mode, but still ignored in .COM mode.  This includes
  214. NAME, END, and PUBLIC.
  215.  
  216. Named SEGMENT and ENDS directives written for other assemblers
  217. are, of course, recognized by A86's .OBJ mode.  In non-OBJ mode,
  218. A86 treats these as CODE SEGMENT directives.  A special exception
  219. to this is the directive
  220.  
  221.     segname SEGMENT AT atvalue
  222.                                                              12-5
  223.  
  224. which is treated by A86 as if it were the following sequence:
  225.  
  226.     segname EQU atvalue
  227.     STRUC
  228.  
  229. This will accomplish what is usually intended when SEGMENT AT is
  230. used in a program intended to be a COM file.
  231.  
  232.  
  233.  
  234. Conversion of A86 Programs to Intel/IBM/MASM
  235.  
  236. I consider this section a bit of a blasphemy, since it's a little
  237. silly to port programs from a superior assembler, to run on an
  238. inferior one.  However, I myself have been motivated to do so
  239. upon occasion, when programming for a client not familiar with
  240. A86; or whose computer doesn't run A86; who therefore wants the
  241. final version to assemble on Intel's assembler.  Since my
  242. assembler/debugger environment is so vastly superior to any other
  243. environment, I develop the program using my assembler, and port
  244. it to the client's environment at the end.
  245.  
  246. The main key to success in following the above scenarios is to
  247. exercise supreme will power, and not use any of the wonderful
  248. language features that exist on A86, but not on MASM. This is
  249. often not easy; and I have devised some methods for porting my
  250. features to other assemblers:
  251.  
  252. 1. I hate giving long sequences of PUSHes and POPs on separate
  253.    lines.  If the program is to be ported to a lesser assembler,
  254.    then I put the following lines into a file that only A86 will
  255.    see:
  256.  
  257.       PUSH2 EQU PUSH
  258.       PUSH3 EQU PUSH
  259.       POP2 EQU POP
  260.       POP3 EQU POP
  261.  
  262.    I define macros PUSH2, PUSH3, POP2, POP3 for the lesser
  263.    assembler, that PUSH or POP the appropriate number of
  264.    operands.  Then, everywhere in the program where I would
  265.    ordinarily use A86's multiple PUSH/POP feature, I use one or
  266.    more of the PUSHn/POPn mnemonics instead.
  267.  
  268. 2. I refrain from using the feature of A86 whereby constants with
  269.    a leading zero are default-hexadecimal.  All my hex constants
  270.    end with H.
  271.  
  272. 3. I will usually go ahead and use my local labels L0 through L9;
  273.    then at the last minute convert them to a long set of labels
  274.    in sequence: Z100, Z101, Z102, etc.  I take care to remove all
  275.    the ">" forward reference specifiers when I make the
  276.    conversion.  The "Z" is used to isolate the local labels at
  277.    the end of the lesser assembler's symbol table listing. This
  278.    improves the quality of the final program so much that it is
  279.    worth the extra effort needed to convert L0--L9's to Z100--
  280.    Zxxx's.
  281.                                                              12-6
  282.  
  283. 4. I will place declarations B EQU DS:BYTE PTR 0 and W EQU
  284.    DS:WORD PTR 0 at the top of the program.  Recall that A86 has
  285.    a "duplicate definition" feature whereby you can EQU an
  286.    already-existing symbol, as long as it is equated to the value
  287.    it already has.  This feature extends to the built in symbols
  288.    B and W, so A86 will look at those equates and essentially
  289.    ignore them.  On the old assembler, the effect of the
  290.    declarations is to add A86's notation to the old language.
  291.    Example:
  292.  
  293.      B EQU DS:BYTE PTR 0
  294.      W EQU DS:WORD PTR 0
  295.      MOV AX,W[0100]       ; replaces MOV AX, DS:WORD PTR 0100
  296.      MOV AL,B[BX]         ; replaces MOV AL, DS:BYTE PTR [BX]
  297.  
  298.