home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / A86V402.ZIP / A12.DOC < prev    next >
Text File  |  1994-12-21  |  13KB  |  294 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
  10. majority of programs can, with a little massaging, be made to
  11. assemble under A86.  Furthermore, the massaging can be done in
  12. such a way as to make the programs still acceptable to that old,
  13. behemoth assembler.
  14.  
  15. I have been adding compatibility features with almost every new
  16. version of A86.  Among the features added since A86 was first
  17. released are: more general forward references, double quotes for
  18. strings, "=" as a synonym for EQU, the RADIX directive, the
  19. COMMENT directive, and the COMPAT.8 file containing macros for a
  20. number of segmentation-model directives.  If you tried feeding an
  21. old source file to a previous A86 and were dismayed by the number
  22. of error messages you got, try again: things might be more
  23. manageable now.
  24.  
  25.  
  26. Conversion of MASM programs to A86
  27.  
  28. Following is a list of the things you should watch out for when
  29. converting from MASM to A86:
  30.  
  31. 1. You need to determine whether the program was coded as a COM
  32.    program or as an EXE program.  All COM programs coded for MASM
  33.    will contain an ORG 100H directive somewhere before the start
  34.    of the code.  EXE programs will contain no such ORG, and will
  35.    often contain statements that load named segments into
  36.    registers.  If the program was coded as EXE, you must either
  37.    assemble it (using the +O option) to an OBJ file to be fed to
  38.    LINK, or you must eliminate the instructions that load segment
  39.    registers-- in a COM program they often aren't necessary
  40.    anyway, since COM programs are started with all segment
  41.    registers already pointing to the same value.
  42.  
  43.    A good general rule is: when it doubt, try assembling to an
  44.    OBJ file.
  45.  
  46. 2. You need to determine whether the program is executing with
  47.    all segment registers pointing to the same value.  Simple COM
  48.    programs that fit into 64K will typically fall into this
  49.    category.  Most EXE programs, programs that use huge amounts
  50.    of memory, and programs (such as memory-resident programs)
  51.    that take over interrupts typically have different values in
  52.    segment registers.
  53.                                                              12-2
  54.  
  55.    If there are different values in the segment registers, then
  56.    there may be instructions in the program for which the old
  57.    assembler generates segment-override prefixes "behind your
  58.    back".  You will need to find such references, and to generate
  59.    explicit overrides for them.  If there are data tables within
  60.    the program itself, a CS-override is needed.    If there are
  61.    data structures in the stack segment not accessed via a
  62.    BP-index, an SS-override is needed. If ES points to its own
  63.    segment, then an ES-override is needed for accesses (other
  64.    than STOS and MOVS destinations) to that segment.  In the
  65.    interrupt handlers to memory-resident programs, the "normal"
  66.    handler is often invoked via an indirect CALL or JMP
  67.    instruction that fetches the doubleword address of the normal
  68.    handler from memory, where it was stored by the initialization
  69.    code.  That CALL or JMP often requires a CS-override-- watch
  70.    out!
  71.  
  72.    If you want to remain compatible with the old assembler, then
  73.    code the overrides by placing the segment-register name, with
  74.    a colon, before the memory-access operand in the instruction.
  75.    If you do not need further compatibility, you can place the
  76.    segment register name before the instruction mnemonic.  For
  77.    example:
  78.  
  79.     MOV AL,CS:TABLE[SI]   ; if you want compatibility do this
  80.     CS MOV AL,TABLE[SI]   ; if not you can do it this way
  81.  
  82. 3. A86 is distributed with a file called COMPAT.8, containing a
  83.    set of macros that implement some of the directives seen in
  84.    recent versions of MASM.  If you would like A86 to recognize
  85.    these directives, make sure copies of COMPAT.8 and A86.LIB are
  86.    in either the current directory, or a directory named by the
  87.    A86LIB environment variable.  When you do so, the file
  88.    COMPAT.8 will automatically be included in your assembly
  89.    whenever you use one of the MASM directives.  See Chapter 13
  90.    for more details about A86LIB.
  91.  
  92. 4. You should use a couple of A86's switches to maximize
  93.    compatibility with MASM.  I've already mentioned the +O switch
  94.    to produce .OBJ files.  You should also assemble with the +D
  95.    switch, which disables A86's unique parsing of constants with
  96.    leading zeroes as hexidecimal.  The RADIX command in your
  97.    program will also do this. And you should use the +G15 switch,
  98.    that disables a few other A86 features that might have reduced
  99.    compatibility. See Chapter 3 for a detailed explanation of
  100.    these switches.
  101.  
  102. 5. A86 is a bit more restrictive with respect to forward
  103.    references than MASM, but not as much as it used to be. You'll
  104.    probably need to resolve just a few ambiguous references by
  105.    appending " B" or " W" to the forward reference name.
  106.  
  107. 6. A86's macro-definition and conditional-assembly language is
  108.    different from MASM's.  Most macros can be translated by
  109.    replacing the named parameters of the old macros with the
  110.    dedicated names #n of the A86 macro language; and by replacing
  111.    ENDM with #EM.  For example, the following MASM macro:
  112.                                                              12-3
  113.  
  114.         MOVM MACRO DEST,SRC
  115.         MOV AL,DEST
  116.         MOV SRC,AL
  117.         ENDM
  118.  
  119.    would be translated by eliminating the DEST,SRC declarations
  120.    on the first line, replacing DEST with #1 and SRC with #2 in
  121.    the body of the definiation, and replacing ENDM by #EM -- the
  122.    result is the MOVM macro that I presented at the beginning of
  123.    Chapter 11.
  124.  
  125.    Other constructs have straightforward translations, as
  126.    illustrated by the following examples.  Note that examples
  127.    involving macro parameters have double hash signs, since the
  128.    condition will be tested when the macro is expanded, not when
  129.    it is defined.
  130.  
  131.    MASM construct              Equivalent A86 construct
  132.  
  133.    IFE expr                     #IF ! expr
  134.    IFB <PARM3>                  ##IF !#S3
  135.    IFNB <PARM4>                 ##IF #S4
  136.    IFIDN <PARM1>,<CX>           ##IF "#1" EQ "CX"
  137.    IFDIF <PARM2>,<SI>           ##IF "#2" NE "SI"
  138.    IFDEF symbol                 #IF DEF symbol
  139.    IFNDEF symbol                #IF ! DEF symbol
  140.    .ERR                         (any undefined symbol)
  141.    .ERRcond                     TRUE EQU 0FFFF
  142.                                 TRUE EQU cond
  143.    EXITM                        #EX
  144.    IRP ... ENDM                 #RX1L ... #ER
  145.    REPT 100 ...ENDM             #RX1(100) ... #ER
  146.    IRPC ... ENDM                #CX ... #EC
  147.  
  148.    The last three constructs, IRP, REPT, and IRPC, usually occur
  149.    within macros; but in MASM they don't have to.  The A86
  150.    equivalents are valid only within macros-- if they occur in
  151.    the MASM program outside of a macro, you duplicate them by
  152.    defining an enclosing macro on the spot, and calling that
  153.    macro once, right after it is defined.
  154.                                                              12-4
  155.  
  156. 7. Later versions of MASM have expanded the syntax of the PROC
  157.    directive, to support interfacing to languages such as Pascal
  158.    and C.  The USES clause lists registers to be pushed at the
  159.    beginning of the procedure, and popped just before the RET
  160.    instruction for that procedure.  In A86, you need to
  161.    explicitly provide such pushes and pops.  MASM also allows the
  162.    declaration of parameters as local variables within the
  163.    procedure.  Such parameters are passed by the calling program
  164.    on the stack, and are addressed using the BP register.  The
  165.    precise offsets from the BP register depend on the particular
  166.    language of the calling program, and on whether the calls are
  167.    NEAR or FAR.  In A86, you can either define the parameter
  168.    names as offsets from BP (the based STRUC feature of A86
  169.    assists in this), or replace usages of the local names with
  170.    explicit BP-index references.  If you define parameter names,
  171.    keep in mind that A86 does not have local scoping of symbols:
  172.    if names are duplicated in different PROCs, you will need to
  173.    change the names to eliminate the duplications.
  174.  
  175. 8. Later versions of MASM have block-structure mechanisms to
  176.    simulate the look and feel of a high-level language.  A86 does
  177.    not yet support these mechanisms: you need to replace them
  178.    with the equivalent conditional-jump and LOOP instructions.
  179.  
  180. 9. A86 supports the STRUC directive, with named structure
  181.    elements, just like MASM, with one exception: A86 does not
  182.    save initial values declared in the STRUC definition, and A86
  183.    does not allow assembly of instances of structure elements.
  184.  
  185.    For example, the MASM construct
  186.  
  187.    PAYREC STRUC
  188.       PNAME  DB 'no name given'
  189.       PKEY   DW ?
  190.    ENDS
  191.  
  192.    PAYREC 3 DUP (?)
  193.    PAYREC <'Eric',1811>
  194.  
  195.    causes A86 to accept the STRUC definition, and to define the
  196.    structure elements PNAME and PKEY correctly; but the PAYREC
  197.    initializations need to be recoded.  If it isn't vital to
  198.    initialize the memory with the specific definition values, you
  199.    could recode the first PAYREC as:
  200.  
  201.    DB  ((TYPE PAYREC) * 3) DUP ?
  202.  
  203.    If you must initialize values, you do so line by line:
  204.  
  205.    DB 'Eric         '
  206.    DW ?
  207.  
  208.    If there are many such initializations, you could define a
  209.    macro INIT_PAYREC containing the DB and DW lines.
  210.                                                              12-5
  211.  
  212. Compatibility symbols recognized by A86
  213.  
  214. A86 has been programmed to ignore a variety of lines that have
  215. meaning to Intel/IBM/MASM assemblers; but which do nothing for
  216. A86.  These include lines beginning with a percent sign, lines
  217. beginning with ASSUME, and lines beginning with any unrecognized
  218. symbol that begins with a period.  If you are porting your
  219. program to A86, and you wish to retain the option of returning to
  220. the other assembler, you may leave those lines in your program.
  221. If you decide to stay with A86, you can remove those lines at
  222. your leisure.
  223.  
  224. In addition, there is a class of symbols now recognized by A86 in
  225. its .OBJ mode, but still ignored in .COM mode.  This includes
  226. NAME, END, and PUBLIC.
  227.  
  228. Named SEGMENT and ENDS directives written for other assemblers
  229. are, of course, recognized by A86's .OBJ mode.  In non-OBJ mode,
  230. A86 treats these as CODE SEGMENT directives.  A special exception
  231. to this is the directive
  232.  
  233.     segname SEGMENT AT atvalue
  234.  
  235. which is treated by A86 as if it were the following sequence:
  236.  
  237.     segname EQU atvalue
  238.     STRUC
  239.  
  240. This will accomplish what is usually intended when SEGMENT AT is
  241. used in a program intended to be a COM file.
  242.  
  243.  
  244.  
  245. Conversion of A86 Programs to Intel/IBM/MASM
  246.  
  247. I consider this section a bit of a blasphemy, since it's a little
  248. silly to port programs from a superior assembler, to run on an
  249. inferior one.  However, I myself have been motivated to do so
  250. upon occasion, when programming for a client not familiar with
  251. A86; or whose computer doesn't run A86, and who therefore wants
  252. the final version to assemble on Intel's assembler.  Since my
  253. assembler/debugger environment is so vastly superior to any other
  254. environment, I develop the program using my assembler, and port
  255. it to the client's environment at the end.
  256.  
  257. The main key to success in following the above scenarios is to
  258. exercise supreme will power, and not use any of the wonderful
  259. language features that exist on A86, but not on MASM. This is
  260. often not easy; and I have devised some methods for porting my
  261. features to other assemblers:
  262.  
  263. 1. I hate giving long sequences of PUSHes and POPs on separate
  264.    lines.  If the program is to be ported to a lesser assembler,
  265.    then I put the following lines into a file that only A86 will
  266.    see:
  267.                                                              12-6
  268.  
  269.       PUSH2 EQU PUSH
  270.       PUSH3 EQU PUSH
  271.       POP2 EQU POP
  272.       POP3 EQU POP
  273.  
  274.    I define macros PUSH2, PUSH3, POP2, POP3 for the lesser
  275.    assembler, that PUSH or POP the appropriate number of
  276.    operands.  Then, everywhere in the program where I would
  277.    ordinarily use A86's multiple PUSH/POP feature, I use one or
  278.    more of the PUSHn/POPn mnemonics instead.
  279.  
  280. 2. I refrain from using the feature of A86 whereby constants with
  281.    a leading zero are default-hexadecimal.  All my hex constants
  282.    end with H.
  283.  
  284. 3. I will usually go ahead and use my local labels L0 through L9;
  285.    then at the last minute convert them to a long set of labels
  286.    in sequence: Z100, Z101, Z102, etc.  I take care to remove all
  287.    the ">" forward reference specifiers when I make the
  288.    conversion.  The "Z" is used to isolate the local labels at
  289.    the end of the lesser assembler's symbol table listing. This
  290.    improves the quality of the final program so much that it is
  291.    worth the extra effort needed to convert L0--L9's to Z100--
  292.    Zxxx's.
  293.  
  294.