home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / a86cnvrt.zip / CONVERT.DOC next >
Text File  |  1987-06-16  |  10KB  |  181 lines

  1. AN EXAMPLE OF CONVERTING A PROGRAM WRITTEN FOR MASM INTO ONE WRITTEN FOR A86
  2. by Eric Isaacson
  3.  
  4.  
  5. Recently a user sent me the file SETUP.ASM, a program written to assemble 
  6. under Microsoft's MASM assembler.  He wanted to know why A86 wouldn't assemble 
  7. it, and why he should choose A86 over MASM, in view of the fact that there are 
  8. hundreds of programs out there written for MASM.  This paper is a response to 
  9. that question.  In it, I show the minimum alterations necessary to produce an 
  10. A86 source file that assembles to an equivalent functioning program.  I go on 
  11. from there, to show how the language extension features of A86 can let you 
  12. make the program simpler and clearer.  Finally, I do an extensive reworking of 
  13. the program, rewriting portions of code, renaming variables and procedures, 
  14. and adding more comments.  By carefully studying the source program at each 
  15. stage of the transformation process, you'll learn not only about the 
  16. differences between A86 and MASM, but about how to transform an ordinary 
  17. assembly-language program into a well-written one. 
  18.  
  19.  
  20. STEP 1.  CONVERTING THE PROGRAM
  21.  
  22. The program that the user sent me is in the file SETUP.ASM.  To make a COM 
  23. program file from this source file using MASM, you must assemble it with MASM,
  24. link the resulting OBJ file using LINK (ignoring the 1 error message that LINK 
  25. always gives you when you use MASM to create a COM file), feed the resulting 
  26. EXE file to EXE2BIN, and finally rename the resulting BIN file to SETUP.COM.
  27. The resulting file is 3129 bytes long.
  28.  
  29. If you attempt to assemble SETUP.ASM using A86 version 3.04, you'll get four 
  30. errors.  The first three are all of the same type-- an attempt to MOV a symbol 
  31. into a general register, where the symbol is a segment name defined with a 
  32. SEGMENT AT directive.  I corrected this by replacing the SEGMENT AT directives 
  33. (all three are together at the top of the program) with EQU directives, 
  34. EQUated to the AT-value.  Similarly, the single symbol defined within each of 
  35. the SEGMENTS was converted to a definition via EQU. 
  36.  
  37. The fourth error is the END BEGIN at the end of the program.  Since A86 treats
  38. this as equivalent to MAIN EQU BEGIN, and since the program already has a 
  39. symbol MAIN defined elsewhere, this was a multiple definition.  I corrected 
  40. this simply by deleting the END BEGIN line, since A86 doesn't need the END 
  41. directive.
  42.  
  43. These modifications took me five minutes to find and make, and I had a program 
  44. that A86 accepted.  But the program didn't work.  A glance at the code 
  45. contents revealed that interrupt drivers were involved, in which the DS, ES,
  46. and SS registers didn't have the same values as the CS register.  Some of the 
  47. memory accesses needed explicit CS override bytes coded for them, since A86 
  48. doesn't act on ASSUME directives.  I scanned through the code and found four 
  49. places where CS overrides were needed.  Diagnosing and solving this problem 
  50. took about twenty minutes; so I had a working A86 program within a half hour.
  51. I would guess this to be worse than average, since most assembly-language COM 
  52. programs don't use multiple-segments the way interrupt drivers do.
  53.  
  54. *** I have made enhancements so that starting with Version 3.05, my assembler
  55.     will assemble SETUP.ASM without modification.  I added interpretation of
  56.     SEGMENT AT to be an EQU of the segment name to the AT value, followed by
  57.     entry into STRUC mode for assembly of declarations within the structure.
  58.     V3.05 also completely ignores the END directive in non-OBJ mode.
  59.  
  60. The source for the minimal changes I have described is the file S1.8.  The 
  61. command A86 S1.8 makes an S1.COM file directly, that is functionally 
  62. equivalent to the SETUP.COM file produced by MASM, LINK, EXE2BIN, and REN.  
  63. The S1.COM file is 3105 bytes long, which is 24 bytes shorter than SETUP.COM.  
  64. The difference comes from 19 unnecessary segment-override bytes produced by 
  65. MASM, plus 5 LEA instructions coded in situations where an equivalent MOV 
  66. instruction would have been more efficient.  A86 automatically generates the 
  67. more efficient MOV instruction, and MASM doesn't.
  68.  
  69.  
  70.  
  71. STEP 2.   INTRODUCING A86 LANGUAGE FEATURES THAT DON'T CHANGE THE PROGRAM
  72.  
  73. Of course, I could have stopped with step 1.  But I wanted to explore the 
  74. possibilities for improving the program, so I continued.  The next step was to 
  75. add A86 language features, to make the program clearer.  The first part of 
  76. this transformation was to eliminate all unnecessary red-tape directives, and 
  77. to replace all the place-marker symbols with A86 local labels (L0 through L9).  
  78. The symbols were easy to find, since the author of the program followed the 
  79. reasonable MASM practice of ending place-marker symbols with digits.  Because 
  80. the local names are only two characters long, it becomes reasonable to indent 
  81. instructions by only two spaces, leaving room for longer comments.  Next, I 
  82. found places to incorporate A86 language features into individual instruction 
  83. sequences: multiple operands to PUSH POP INC DEC, conditional returns, MOV 
  84. segreg,segreg, and IF cond stmt.  The resulting program, S2.8, produces a 
  85. virtually identical 3105-byte COM file to S1.8, but the source code appearance 
  86. is considerably changed for the better. 
  87.  
  88.  
  89. STEP 3.  MAKING MINOR CODE OPTIMIZATIONS
  90.  
  91. Next, I started making changes to improve the code itself.  Among the changes:
  92.  
  93. 1. I renamed many variables and procedures, to make the program easier to 
  94.    follow.  Same of the renaming was simple unabbreviation: for example, 
  95.    VIDEO2MEM to VIDEO_TO_MEM, and PAGE_NO to PAGE_NUMBER.  Other renaming 
  96.    involved making a completely different, clearer choice of name: for 
  97.    example, SETUP_STATUS to WINDOW_ACTIVE?, and MAIN to OUR_HANDLER.
  98.  
  99. 2. I combined that three original SEGMENT ATs and the variables they contained 
  100.    into three DD constants, to be loaded into pointers with LDS or LES 
  101.    instructions, followed by indirect memory instructions to access the 
  102.    variables. 
  103.    
  104. 3. I rearranged the main interactive loop to make the flow of control clearer.
  105.    The exit-code executed when the ESC key is pressed is separated from the 
  106.    main flow, and clearly labelled ESC_SEEN.  The rest of the main loop was 
  107.    consolidated and arranged to clearly show its loop structure.
  108.  
  109. 4. I performed code optimizations based on 86 instruction set features the 
  110.    original author didn't take advantage of.  For example, the sequence
  111.  
  112.         L1:
  113.           MOVSW
  114.           LOOP L1
  115.  
  116.    was replaced by a simple REP MOVSW instruction.  The preceding CLD 
  117.    instruction was moved to the start of interrupt processing, reducing the 
  118.    procedure WRITELN to the single REP MOVSW line.  So I eliminated WRITELN 
  119.    and replaced the instances of CALL WRITELN with REP MOVSW.  I could have 
  120.    treated MEM2MEM similarly, except that MEM2MEM is never called so it can be 
  121.    eliminated outright.  Finally, the sequence
  122.  
  123.          SUB BX,2
  124.          MOV AL,DISPLAY_TABLE[BX]
  125.  
  126.    was replaced by MOV AL,DISPLAY_TABLE[BX-2] .
  127.  
  128. In addition to the coding changes, I converted all non-comment code to all-
  129. caps, to complete the conversion of the program to my formatting conventions.  
  130. The resulting program, S3.8, assembles to a 3065-byte COM file, 40 bytes less 
  131. than the previous version due to the optimizations.
  132.  
  133.  
  134. STEP 4.  MAKING MAJOR CODE OPTIMIZATIONS
  135.  
  136. For the final revision of the program I made major code optimizations:
  137.  
  138. 1. I completely overhauled the usage of memory variables.  Some variables, 
  139.    such as ATTRIBUTE1, were eliminated, their values kept in registers.  The 
  140.    tables VIDEO and DISPLAY_TABLE were replaced by the more directly useful 
  141.    ENABLE_VALUE and VIDEO_SEG.
  142.  
  143. 2. I redesigned the parameterization of VIDEO_TO_MEM and MEM_TO_VIDEO, that 
  144.    defines the size and location of the pop-up window.  It had previously been 
  145.    a run-time parameterization, always called with the same values.  I 
  146.    introduced a set of EQUs for the parameters, defining the window at 
  147.    assembly time.  VIDEO_OFFSET was transformed from a run-time procedure to 
  148.    an assembly-time expression EQUate.  All constant references depending on 
  149.    window size were recast in terms of the parameter-symbols.  Assertion-
  150.    checking was also introduced to insure that the declaration of the window 
  151.    contents contains the proper number of bytes.
  152.  
  153. 3. The program was rearranged to save space.  The buffer used for storing the 
  154.    contents of the screen beneath the pop-up window was moved to the start of 
  155.    the program, so that the 256-byte PSP buffer could be a part of the storage 
  156.    buffer.  The initialization code and window source code was moved there 
  157.    also, to save space.  The buffer containing the constructed window image 
  158.    was moved to beyond the area of the COM file, reducing the size of the COM 
  159.    file by 1064 bytes in one stroke.
  160.  
  161. 4. The array CODE_TABLE was converted from fixed-length records to delimited 
  162.    variable-length records, saving more program space.
  163.  
  164. 5. The pushing of all registers except AX was deferred until after the hot-key 
  165.    check, to reduce keystroke computational overhead time when the program is 
  166.    not in effect.
  167.  
  168. 6. More changes were made to improve program readability.  The installation 
  169.    code was broken up into procedures, for clarity.  The keycode values FUNC 
  170.    and SHIFT_F were declared and used, to make the key-scanning code easier to 
  171.    follow.  The program itself was renamed to the more descriptive EPSONSET, 
  172.    and an explanatory paragraph was added to the top of the source code.  The 
  173.    instruction-level comments were improved.
  174.  
  175. The resulting final source program is S4.8, which assembles to a COM file of 
  176. only 1237 bytes, less than 40% of the original program size.  I retained the 
  177. original copyright notice, although it might be argued that I transformed the 
  178. program enough to call it my own.
  179.  
  180.  
  181.