home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / DOOG / MD8610.ZIP / MD86.DOC < prev    next >
Text File  |  1990-05-04  |  82KB  |  1,755 lines

  1.  
  2.  
  3.  page 1      Masterful Disassembler - Intel 8086  version 1.00      page 1
  4.  
  5.  
  6.  
  7.  1.0) Introduction
  8.  
  9.  The  MD86 program is a powerful utility for examining and disassembling any
  10.  executable  program  or  any  series  of  machine  instructions (like a ROM
  11.  image). MD86 is designed to run on any IBM PC, XT, or AT or compatible with
  12.  at  least 128k of ram memory. Neither a graphics adaptor or a color monitor
  13.  is required. A hard disk is desirable but MD86 runs fine (actually a trifle
  14.  slower) on floppy based systems.
  15.  
  16.  MD86  was developed with one goal in mind. Produce useable source code from
  17.  an executable program file. By useable, we mean that the resulting assembly
  18.  instructions  should  be understandable. This necessitates meaningful label
  19.  names  and  comments. Normally the disassembly of a large program is a time
  20.  consuming, laborious task. MD86 speeds this up as much as possible.
  21.  
  22.  MD86 produces source files that are compatible with the Microsoft assembler
  23.  MASM  version  4.00  or reasonably compatible with the IBM assembler. While
  24.  this  is  not  the  easiest  assembler  to  use  (in  fact it is down right
  25.  difficult),  it  was  chosen  because  it is more "standard" than any other
  26.  assembler.   Eventhough   the   instruction   syntax   is  compatible,  the
  27.  organization  of  the segments may not be for some programs. After MD86 has
  28.  produced a source file, it is not uncommon that an editor is needed to make
  29.  some  minor  changes before it can be assembled without error. This will be
  30.  especially   true  with  EXE  type  programs  which  have  complex  segment
  31.  structures.
  32.  
  33.  
  34.    1.1) What MD86 Looks Like
  35.  
  36.    MD86's  unique  video  display works very much like a full screen editor;
  37.    allowing  movement  within  the  disassembled source file with single key
  38.    ease.  Most  of  the  difficulties associated with other disassemblers is
  39.    gone.
  40.  
  41.    When  executed,  MD86 presents the user with a full screen of information
  42.    that looks very similar to the printed output from an assembler. Figure I
  43.    shows  a  typical  screen  from  a  freshly disassembled program. This is
  44.    actually the file COMMAND.COM for PCDOS v3.1.
  45.  
  46.    The  bold  line  towards  the  top of the display is the active line. The
  47.    cursor  (shown  as  an underline "_") is at the start of the label field.
  48.    Both the label field and the comment field may be edited.
  49.  
  50.    Note how the display does not seem cluttered. The label field only has an
  51.    entry  if  the  address  is referenced. The comments shown here have been
  52.    automatically  inserted  by MD86  These help you remember the less common
  53.    instructions and MSDOS function calls.
  54.  
  55.  
  56.  page 2      Masterful Disassembler - Intel 8086  version 1.00      page 2
  57.  
  58.  
  59.           Figure I, Typical Display Of Freshly Disassembled Program
  60.  
  61.  
  62.  05DB:51           L05DBH   PUSH  CX            ;
  63.  05DC:1E                    PUSH  DS            ;
  64.  05DD:07                    POP   ES            ;
  65.  05DE:C536610A     _        LDS   SI,[L0A61H]   ;Load DS:reg with 32b pointr
  66.  05E2:57                    PUSH  DI            ;
  67.  05E3:BF5A08                MOV   DI,#L085AH    ;
  68.  05E6:B90B00                MOV   CX,#L000BH    ;
  69.  05E9:FC                    CLD                 ;Set forward direction for
  70.  05EB:F3A4                  REPZ MOVSB          ;Move byt. (SI)+- to (DX)+-
  71.  05EC:5F                    POP   DI            ;
  72.  05ED:06                    PUSH  ES            ;
  73.  05EE:1F                    POP   DS            ;
  74.  05EF:59                    POP   CX            ;
  75.  05F0:BA4708                MOV   DX,#L0847H    ;
  76.  05F3:B409CD21              MSDOS _OUTSTR       ;Display string at (DX)
  77.  05F7:BA9E08       L05F7H   MOV   DX,#L089EH    ;
  78.  05FA:E8A300                CALL  L06A0H        ;
  79.  05FD:F606D30AFF            TEST  [L0AD3H],0FFH ;
  80.  0602:7404                  JZ    SHORT L0683H  ;
  81.  0604:B403                  MOV   AH,#3         ;
  82.  0606:EB7B                  JMP   L0683H        ;
  83.  0608:B8010C       L0608H   MOV   AX,#L0C01H    ;Flush buffer, read keyboard
  84.  060B:CD21                  MSDOS               ;
  85.  060D:E88D00                CALL  L069DH        ;
  86.  CS:: Labels= 185/ 8%, Types=   0/  0%,   0 cmnts  No Edit 10/ 2/87  1:20:35
  87.  
  88.  
  89.    A  note  to  programmers familiar with the Microsoft assembler MASM. MD86
  90.    creates   compatible   data  files,  but  the  screen  display  has  been
  91.    simplified.  In  particular,  the  word  OFFSET  (as required by MASM) is
  92.    replaced  with the pound sign ("#") and all WORD PTR and BYTE PTR phrases
  93.    have  been  removed.  Generated  labels  are  not shown with an appending
  94.    colon.  When  a  source  file  is  generated,  the  source  code  will be
  95.    compatible.
  96.  
  97.    The  line  at the bottom contains status information. This tells you that
  98.    the  code  being  viewed  is in the code segment, 185 address labels have
  99.    been  identified,  no  data  types  have been defined and no user entered
  100.    comment  records  exist. In this case we are not as yet editing any field
  101.    thus  "No  Edit"  is  displayed.  If  we  were,  then  either "INSERT" or
  102.    "REPLACE"  would  show  indicating  how characters are being added to the
  103.    field. At the far right corner, the current time and date are as shown.
  104.  
  105.    The  comment  field  may extend past the right edge of the screen and the
  106.    active  line  scrolls horizontally as necessary to keep the cursor within
  107.    view.
  108. è   The  function  keys  are  used to control MD86. A window "pops up" in the
  109.    upper  left  corner  for instructions. Inadvertently entered commands may
  110.    generally  be  aborted  by  a null response (ie, only pressing the RETURN
  111.  
  112.  
  113.  page 3      Masterful Disassembler - Intel 8086  version 1.00      page 3
  114.  
  115.  
  116.    key) to one of the questions.
  117.  
  118.  
  119.  2.0) Using MD86
  120.  
  121.  
  122.  To  disassemble  a  file it must first exist in the current directory. MD86
  123.  may  be  placed in any other directory as long as the PATH command includes
  124.  that  directory.  The  companion  file, MD86.CMT is only used to supply the
  125.  automatic  comments  and  is only needed when a program is disassembled for
  126.  the  first  time.  If  this  is  not  found,  MD86  will turn off automatic
  127.  commenting.  If  this  is not acceptable, then QUIT (see Section 2.2), move
  128.  MD86.CMT to the current directory and begin again.
  129.  
  130.  To disassemble the program COMMAND.COM, use the following command.
  131.  
  132.  
  133.     C>MD86 COMMAND.COM
  134.  
  135.  
  136.  If MD86 cannot locate the associated data files, then MD86 will create them
  137.  (you  will  be asked for confirmation first just in case you misspelled the
  138.  program  name). MD86 will automatically determine the extent of the program
  139.  and  put the cursor on the first address of the program. Note that COM type
  140.  files  start at 100 (hex) and EXE type files start at 0000. See reference 1
  141.  for  a discussion of the dissection of EXE type files. The Alter Parameters
  142.  command may be used to override the choices made by MD86.
  143.  
  144.  MD86  creates two data files when it disassembles a program. These have the
  145.  same  name  with  the  extensions  of  .001  and  .002 (ie, COMMAND.001 and
  146.  COMMAND.002). The first file contains the symbol table and other parameters
  147.  and the second file contains the comment records. If neither of these files
  148.  are  present,  then  MD86  assumes  this is a disassembly of a file for the
  149.  first  time. If they are both present (and readable) then MD86 will pick up
  150.  right  where  you left off. If only one of these files is present or one is
  151.  unreadable,  then  MD86  issues  an  error message and terminates. Refer to
  152.  Section 7 for a discussion of error causes and cures.
  153.  
  154.  During  the  disassembly  process,  there are three groups of commands that
  155.  MD86  will  recognize.  Commands that require additional input will cause a
  156.  window  to  pop  up  in the upper left corner of the display. User dialogue
  157.  occurs within this window.
  158.  
  159.  The  three  command  groups  consist of 1) editing commands, 2) non-editing
  160.  commands, and 3) general commands. The editing and non-editing commands are
  161.  mutually  exclusive. When editing, the non-editing commands are not allowed
  162.  and visa-versa. General commands are always valid.
  163.  
  164.  MD86  will  "beep"  when an invalid command character is entered. Note that
  165.  some  keys  generate  more than one character and while the first characterè may  be invalid, the others may not. So when you here the beep, examine the
  166.  characters  around  the  cursor  to  be  sure no extraneous characters were
  167.  inserted.
  168.  
  169.  
  170.  page 4      Masterful Disassembler - Intel 8086  version 1.00      page 4
  171.  
  172.  
  173.  
  174.  
  175.    2.1) General Command Keys
  176.  
  177.    The  general  commands  can  be  typed  at  any time. They will always be
  178.    recognized.
  179.  
  180.  
  181.    o Left-Arrow
  182.  
  183.      This  will  move  the cursor one position left within the current field
  184.      (either the label field or the comment field). It the cursor is already
  185.      at the beginning column, then a "beep" will be heard.
  186.  
  187.  
  188.    o Right-Arrow
  189.  
  190.      This  will  move the cursor one position right within the current field
  191.      (either the label field or the comment field). Note that the fields are
  192.      always  filled  with blanks on the right. If the cursor is already past
  193.      the right hand column, then a "beep" is heard.
  194.  
  195.  
  196.    o Insert
  197.  
  198.      This  will change the way editing character keys are entered. They will
  199.      either   replace   existing  characters  or  insert  in  front  of  the
  200.      characters.  In  editing mode, either INSERT or REPLACE is displayed in
  201.      the bottom status line.
  202.  
  203.  
  204.    2.2) Editing Command Keys
  205.  
  206.    The  label  and  comment fields can be edited by moving the cursor to the
  207.    desired  location  and  just  typing;  similar  to a word processor. This
  208.    allows  label names and or comments to be associated with an address. The
  209.    current  line  may  be  in  the  code  segment  or data segment (EXE type
  210.    programs  only).  Once editing has begun, then only the ESCAPE key or the
  211.    RETURN key will revert to non-editing command mode.
  212.  
  213.    When  a  temporary  label  field  is  edited, it is initially blanked out
  214.    eliminating  the  "L1234H" that was present. If the cursor was not at the
  215.    first  column  of  the label, then leading blanks will exist there. Since
  216.    labels must begin with a letter or underscore, this will be rejected when
  217.    a RETURN key is pressed.
  218.  
  219.    Editing  the  automatic  comments causes MD86 to first ask if the comment
  220.    field should be blanked out or not. After this question is answered, your
  221.    key is processed.
  222.  
  223.  
  224.  page 5      Masterful Disassembler - Intel 8086  version 1.00      page 5
  225.  
  226.  
  227.    o Letters, Numbers, and Symbols
  228.  
  229.      These  characters  are  entered  into the field. If the current mode is
  230.      INSERT  then  the  characters  to  the  right  are moved (the rightmost
  231.      character  is  lost)  to  make room. Otherwise, in REPLACE mode the new
  232.      character overwrites the current cursor character. Note that within the
  233.      label  field  only  the  characters  A-Z, a-z, 0-9, $, and _ are valid.
  234.      Other  characters  cause  a "beep" and are ignored. Note that a further
  235.      restriction  that labels not begin with a number is not checked until a
  236.      RETURN key is pressed.
  237.  
  238.  
  239.    o Escape
  240.  
  241.      This  key will cancel any editing on the current field and its original
  242.      contents will be restored. This effectively returns to non-editing mode
  243.      without saving any changes to the current field.
  244.  
  245.  
  246.    o Return
  247.  
  248.      Use  this  key  to tell MD86 that the editing changes you have made are
  249.      correct  and  should  be  remembered. Note that this is not the same as
  250.      saving the data as it is not actually written to the data files yet. If
  251.      the  field  contents are valid, then the cursor will be returned to the
  252.      starting   column  of  the  current  field  and  the  mode  is  set  to
  253.      non-editing.
  254.  
  255.  
  256.    o Backspace
  257.  
  258.      If  the  cursor  is  not  at the left edge already, this will erase the
  259.      character  immediately  to the left of the cursor. The remainder of the
  260.      line  will  be  shifted  left  and  the  rightmost column will be blank
  261.      filled. If at the left, then this just "beeps".
  262.  
  263.  
  264.    o Delete
  265.  
  266.      This  will  erase  the character immediately under the cursor and cause
  267.      the remainder of the line to be shifted left. The rightmost column will
  268.      be blank filled.
  269.  
  270.  
  271.    o End
  272.  
  273.      This moves the cursor to the last column of the field.
  274.  
  275.  
  276.    o Homeè
  277.      This moves the cursor to the leftmost column of the field.
  278.  
  279.  
  280.  page 6      Masterful Disassembler - Intel 8086  version 1.00      page 6
  281.  
  282.  
  283.  
  284.    2.3) Non-editing Command Keys
  285.  
  286.    A  good  portion  of  time spent disassembling a program is spent rooming
  287.    around  various  areas  and other non-editing type functions. The simpler
  288.    cursor movement functions use a single key stroke for this work while the
  289.    more involved commands use the function keys and pop up windows.
  290.  
  291.    The cursor movement keys are as follows.
  292.  
  293.  
  294.    o Down-Arrow
  295.  
  296.      This  moves  the  cursor down one line and to the beginning of the same
  297.      field. You cannot move beyond the end of the current segment.
  298.  
  299.  
  300.    o Up-Arrow
  301.  
  302.      Move  the  cursor  up  one line to the beginning of the same field. You
  303.      cannot move past the beginning of the current segment.
  304.  
  305.  
  306.    o Home
  307.  
  308.      If  the  cursor  is  right of the leftmost column of the comment field,
  309.      then  it  is  moved  to  the  start of the comment field. Otherwise the
  310.      cursor  moves  to  the  first column in the label field within the same
  311.      line.
  312.  
  313.  
  314.    o End
  315.  
  316.      This  moves  the cursor to the beginning of the comment field if it was
  317.      within  the  label  field. Otherwise the cursor moves to the end of the
  318.      comment field.
  319.  
  320.  
  321.    o Page-Up
  322.  
  323.      This moves the cursor up approximately a full page. This may be more or
  324.      less  than  24  lines as this assumes there are three bytes per line on
  325.      the average. Note that no attempt is made to locate the beginning of an
  326.      instruction.  It  is  probable  that  the  first  line  or  so  will be
  327.      disassembled incorrectly. The cursor will be positioned at the start of
  328.      the label field in the top line.
  329.  
  330.  
  331.    o Page-Down
  332. è     This  moves  the  cursor  to the top of the next page. The line that is
  333.      currently  at  the  bottom  of the screen will be at the top after this
  334.      command. The cursor will be positioned at the start of the label field.
  335.  
  336.  
  337.  page 7      Masterful Disassembler - Intel 8086  version 1.00      page 7
  338.  
  339.  
  340.  
  341.  
  342.    The  following  commands  utilize  the  function  keys on the PC keyboard
  343.    either  alone  or  in combination with the shift key. Remember these only
  344.    function in non-editing mode.
  345.  
  346.  
  347.    o F1 - Help Command
  348.  
  349.      This  displays a one screen summary of the function keys. Press any key
  350.      to refresh the screen.
  351.  
  352.  
  353.    o Shift-F1 - Alter System Parameters
  354.  
  355.      This  command  is  use  to  make  changes  (if possible) to the default
  356.      parameters.  For  COM  files, the beginning and ending addresses can be
  357.      modified. EXE files however, have ranges for the data and code segments
  358.      that are defined in the header. These cannot be changed.
  359.  
  360.      For COM files, the following parameters can be changed.
  361.  
  362.  
  363.       o The  Start  Address. Normally this is 100 hex for COM files and 0000
  364.         hex  for EXE files. But for special work, like ROM disassembly, this
  365.         may be set to something else.
  366.  
  367.       o The  End  Address. MD86 sets this to the physical end of the program
  368.         or  FFFE  hex  if  this is more than 64k. If you find that a smaller
  369.         value  is  correct, then change it here. This will prevent MD86 from
  370.         accessing garbage areas and contaminating the label table.
  371.  
  372.  
  373.      The  following  parameters  effect  how  MD86 displays the disassembled
  374.      lines. These are changeable at all times.
  375.  
  376.  
  377.       o Translate  MSDOS  Functions. MD86 normally tries to translate common
  378.         MSDOS functions into a pseudo instruction that has more meaning when
  379.         trying to understand the code. However, if you don't want this done,
  380.         then it can be disabled here.
  381.  
  382.       o Enable  Automatic Comments. When MD86 finds certain instructions, it
  383.         tries  to  add  a comment line explaining the instruction in more or
  384.         less English. If you don't want to see these comments, then they can
  385.         be eliminated.
  386.  
  387.  
  388.    o F2 - Goto a Specified Address
  389. è     This  allows  a quick jump to any valid address to begin disassembly. A
  390.      null  response  (only  the  RETURN  key pressed) causes MD86 to try and
  391.      return  to  the  location  of  the  last Goto command. A stack with the
  392.  
  393.  
  394.  page 8      Masterful Disassembler - Intel 8086  version 1.00      page 8
  395.  
  396.  
  397.      previous  16  locations  is maintained. This is handy in jumping to one
  398.      location and then returning without having to remember where you were.
  399.  
  400.      Valid  destinations  are  anywhere  within the data segment or the code
  401.      segment.  Note  that  for  a COM type file, these are assumed to be the
  402.      same.
  403.  
  404.  
  405.    o Shift-F2 - Follow That Instruction
  406.  
  407.      If  the  current  line contains a direct jump or call instruction, this
  408.      command will do an automatic Goto to the destination address. This does
  409.      not  apply  to  intra-segment  calls  or jumps or any indirect calls or
  410.      jumps.
  411.  
  412.      MD86  saves  the current address on its internal stack so that a return
  413.      can  be made via the F2 command. With this you can conveniently examine
  414.      a subroutine and then continue from where you left off.
  415.  
  416.  
  417.    o F3 - Set Data Type
  418.  
  419.      When  MD86  first  looks  at  a program, it thinks that all of the data
  420.      segment  is  made up of 8-bit data bytes and all of the code segment is
  421.      machine  instructions.  This more than likely is not 100% correct. When
  422.      disassembling a portion of the program, you may notice that the present
  423.      interpretation  does not make sense. Some other data type is necessary.
  424.      MD86 can recognize one of four data types. These are instructions (type
  425.      #0), 8-bit binary data (type #1), 8-bit ascii characters (type #2), and
  426.      16-bit addresses (type #3). See Section 2.6 for more details.
  427.  
  428.      This  command  allows  any range of the program to be set to a specific
  429.      type.  You  will  be  asked  for  the  data type and the first and last
  430.      addresses. Addresses must be in the same segment of course.
  431.  
  432.      The  internal type table has room for 512 entries. This is the total of
  433.      the  data and code segment types. The current total is displayed on the
  434.      bottom status line along with a percent used figure.
  435.  
  436.  
  437.    o F4 - Set Data Type for Unspecified Range
  438.  
  439.      Often  the  extent of a different data type is not known. What is known
  440.      is the initial address and a suspected data type. This command uses the
  441.      current  line  as  the beginning address and will request the suspected
  442.      data  type (0 to 3). Then MD86 temporarily considers all data following
  443.      the  cursor  to  be this type. You would move the cursor down until you
  444.      reach an address that is not of this type and press F4 again to fix the
  445.      range  for the specified type. In this special mode, only one data item
  446.      per line is displayed.è
  447.  
  448.  page 9      Masterful Disassembler - Intel 8086  version 1.00      page 9
  449.  
  450.  
  451.    o F5 - Write Source to Disk
  452.  
  453.      MD86 would be of limited use if you could not generate a disk file with
  454.      the  source  code.  Use this command and specify the file name and MD86
  455.      will  write out the data. If an extension of PRN is used, then the file
  456.      will have the address and binary code along with each instruction line.
  457.      This is the way the screen appears.
  458.  
  459.      Before this file can be used by an assembler, some hand editing will be
  460.      required. Segments may have to be specified differently than MD86.
  461.  
  462.  
  463.    o F6 - Scan Code Segment
  464.  
  465.      MD86  builds  the  label  table  as code is disassembled. At times, the
  466.      disassembly  is  not  correct  and  erroneous address references may be
  467.      entered into the label table. This function cleans this up.
  468.  
  469.      When all of the code segment has been given the correct data type, then
  470.      this function should be used to properly build the label table. It will
  471.      remove  any  temporary  labels  and begin disassembling the entire code
  472.      segment.  When  this has completed, the label table will be correct and
  473.      erroneous references will be removed.
  474.  
  475.  
  476.    o F7 - Dump Program in Hexadecimal and ASCII
  477.  
  478.      It  is  difficult to determine the location of data areas and character
  479.      strings  by  just  looking at a page of disassembled instructions. This
  480.      function  will  begin  in  the data segment (for EXE programs) and then
  481.      dump  the  code  segment.  The  data  is displayed 16 bytes per line in
  482.      hexadecimal and also in ascii (if possible). Pressing any key will halt
  483.      the  display so you can inspect the data and maybe write down addresses
  484.      of  obvious  data  areas.  Pressing  any key other than the ESCAPE will
  485.      continue the display. Press the ESCAPE key to end this segment and dump
  486.      the  next  segment  or  return  to  where  you  when  this  command was
  487.      initiated.
  488.  
  489.  
  490.    o F8 - Set Label Name
  491.  
  492.      If  it is desired to associate a name with a particular address you can
  493.      either move the cursor to that address (if possible) and edit the label
  494.      field or use this command to set the name without having to move there.
  495.      Enter  any  valid  label  name and address to be set. A null label name
  496.      will  delete  a label from the tables. In valid names cause a "beep" to
  497.      be heard and is ignored. Valid names start with a non-digit and have no
  498.      imbedded spaces.
  499.  
  500.      The  label  table  is  limited  to  2048  label  names  which should beè     satisfactory for any reasonable size program.
  501.  
  502.  
  503.  page 10      Masterful Disassembler - Intel 8086  version 1.00      page 10
  504.  
  505.  
  506.    o F9 - Search for Address Reference
  507.  
  508.      This  command  will allow any address to be searched for. Use this when
  509.      it  is  desired to find out how (or if) a particular area is referenced
  510.      within  the  code segment. The initial address to start is requested. A
  511.      null response causes the search to begin at the start address. You will
  512.      see  the  program  disassembled on the screen and it will stop when the
  513.      specified  address  is  referenced. During the search, press any key to
  514.      abort.
  515.  
  516.      Note  that  the  search  is  limited  to the code segment. However, the
  517.      particular  address  may be in any other segment. For example to search
  518.      for  address 1234 within the extra segment, enter ES:1234 as the search
  519.      string.
  520.  
  521.  
  522.    o Shift-F9 - Search for Next Reference
  523.  
  524.      Once  function  F9  has  been  used  to find the first occurrence of an
  525.      address,  use  this  command  to  locate the next. As with function F9,
  526.      press any key to abort the search.
  527.  
  528.  
  529.    o F10 - Save and/or Exit
  530.  
  531.      Use  this command to save your current data tables (often!) and exit or
  532.      quit MD86  You are given the option to save the data or not and to exit
  533.      to MSDOS or not.
  534.  
  535.      If  you wish to quit without saving any of the work you have done, then
  536.      respond No to saving the data and Yes to exiting.
  537.  
  538.  
  539.    2.4) Label Name Specification
  540.  
  541.    MD86  allows,  even  encourages,  you to associate a label name with each
  542.    referenced  address.  Names are far more understandable than numbers. The
  543.    label  field within the display is either blank (the address has not been
  544.    referenced),  contains  a temporary label (the form is LnnnnH for address
  545.    nnnn),  or  contains  a user defined name. Label names can be up to eight
  546.    characters  long and may contain letters, digits, the dollar sign "$", or
  547.    the underscore "_" characters. Labels may not begin with a digit however.
  548.  
  549.    Label  names  may  contain  upper  and lower case letters and the case is
  550.    maintained.  However, when searching for a name, MD86 ignores differences
  551.    in  case. Thus the name "HelpMsg" is perfectly valid and will appear this
  552.    way  in  the  output  file.  You could also jump to address "HELPMSG" and
  553.    "HelpMsg" would be found.
  554.  
  555.    Upper  and  lower  case  letters make reading names easier, but you don'tè   have to remember the exact form to reference the name.
  556.  
  557.  
  558.  page 11      Masterful Disassembler - Intel 8086  version 1.00      page 11
  559.  
  560.  
  561.  2.5) Specification of Addresses
  562.  
  563.    When  MD86  requests an address (like the destination of a Jump command),
  564.    the form the address must be entered as follows.
  565.  
  566.  
  567.       Address ?{ss:}nnnn
  568.  
  569.  
  570.    The  brackets  indicate  optional  qualifiers. If the address is within a
  571.    segment  other  than  the  current segment, then the segment name must be
  572.    included.  The  "ss:"  in  the line above is the segment name and it must
  573.    then  be either "CS:", "DS:", "ES:", or "SS:". The case of the letters is
  574.    not  important, but the segment name must precede the address (or offset)
  575.    portion.
  576.  
  577.    If  the  actual address within the segment is entered as a number then it
  578.    must be in hexadecimal. In place of a number, a label name could be used.
  579.    This name must be resolvable within the segment.
  580.  
  581.    For example, the following are valid addresses.
  582.  
  583.  
  584.       Address ?100
  585.  
  586.       Address ?ds:HelpMsg
  587.  
  588.  
  589.    The  label table is stored internally and has room for 2048 entries. This
  590.    is  generally  enough to disassemble a 10,000 to 15,000 line program. For
  591.    larger  programs  it  is  recommended  that  they be divided into smaller
  592.    sections if at all possible.
  593.  
  594.  
  595.    2.6) Data Type Specification
  596.  
  597.    MD86  initially  thinks the entire code segment contains instructions and
  598.    the data segment (for EXE type files) contains 8-bit binary data. This is
  599.    a  good  place  to start but there will be other data types mixed in with
  600.    these. Functions F3 and F4 can be used to tell MD86 to assume a different
  601.    data  type  for  a  specified address range. The types are specified by a
  602.    numeric code number and the ones recognized are:
  603.  
  604.  
  605.       0 - Machine instructions.
  606.  
  607.       1 - 8-bit binary data.
  608.  
  609.       2 - 8-bit ASCII character data.
  610. è      3 - 16-bit address data.
  611.  
  612.  
  613.  
  614. 1
  615.  
  616.  page 12      Masterful Disassembler - Intel 8086  version 1.00      page 12
  617.  
  618.  
  619.    When  using function F3, MD86 must be told the first address of the newly
  620.    defined  type  and  the  last address with this type. For data types that
  621.    occupy  more  than  one  byte (type 0 or 3), the last address must be the
  622.    address  at  the  end  of  the  field  not the start. Thus if address 100
  623.    contains a single 16 bit address, then MD86 is given the first address as
  624.    100 and the last address as 101 (not 102 as you might think).
  625.  
  626.    Function  F4 works a little differently. The start of the current line is
  627.    taken  as  the first address when this is initiated. When this is pressed
  628.    again,  then  the  start  of  the  now  current  line (if below the first
  629.    address)  is  assumed  to be just passed the type being defined. In other
  630.    words,  if the address range 120 to 140 is being defined as type 2 (ascii
  631.    character  data),  then the current line should be at address 120 when F4
  632.    is  pressed the first time and then moved to address 141 when pressed the
  633.    second time.
  634.  
  635.    A  code  type  table  is  maintained internally by MD86 that contains the
  636.    beginning  and  ending addresses (with segment of course) and the type of
  637.    data  this  address range contains. Instructions are the default type and
  638.    (to  save  memory  space)  are not actually stored in the table. There is
  639.    room for 512 entries which should be plenty for most normal applications.
  640.  
  641.  
  642.    2.7) Output Source File Format
  643.  
  644.    MD86  produces  a  standard  ASCII  text  file  as output. This should be
  645.    suitable  as  input to most any assembler and editor. Note that MD86 does
  646.    not  insert  tab  characters and thus the lines will contain many blanks.
  647.    This  causes the files to be quite large. The judicious insertion of tabs
  648.    would shrink the file size significantly.
  649.  
  650.    When  MD86  disassembles  a  program,  it  remembers  how  addresses  are
  651.    referenced.  As a convenience, the output file will have separating lines
  652.    just  in front of all subroutines. That is, those addresses that were the
  653.    target of near call instructions.
  654.  
  655.  
  656.  3.0) The Inner Details of MD86
  657.  
  658.  In  the  next  few  sections  we  will  describe  in  more  detail how MD86
  659.  functions.  It is not necessary that you remember or understand all of this
  660.  material, but when questions arise this will make a handy reference.
  661.  
  662.  Many  choices  made during the construction of MD86 were ones of programmer
  663.  preference.  There are several ways to tackle the many problems encountered
  664.  in  creating  a  disassembler.  Which  one is better? If the choice was notè obvious, then personal preference would be the deciding factor.
  665.  
  666.  MD86  was  written in TURBO Pascal and owes a lot of its speed to this fine
  667.  compiler.  Some  of the limitations of this compiler necessitated tradeoffs
  668.  in  the  design  of  MD86. In particular, to avoid the use of overlays, the
  669.  program  was  limited  to a 61k code segment. Not all of the "nice" options
  670.  could be included.
  671.  
  672.  
  673.  page 13      Masterful Disassembler - Intel 8086  version 1.00      page 13
  674.  
  675.  
  676.  
  677.  
  678.    3.1) Moving the Cursor Upward
  679.  
  680.    When  MD86  displays a full screen of disassembled lines it remembers the
  681.    exact  starting  address  for  each  line. Thus to move upward within the
  682.    display  screen,  MD86 only has to display the new current line in bright
  683.    characters  again.  However,  when  the  cursor  moves off the top of the
  684.    screen  (either  by an Up Arrow or Up Page command), MD86 has a difficult
  685.    task  in  determining the starting address for the instruction. There are
  686.    times when more than one legitimate starting address is located. For this
  687.    situation, MD86 chooses the longest instruction. This may not be correct.
  688.    The  problem  comes  in  when  MD86  has moved up more than one time (you
  689.    pressed  Up  Arrow  more  than once when at the top of the screen) and it
  690.    finally  comes to a point where it cannot find any legitimate instruction
  691.    to  disassemble.  You here a "beep" and MD86 only backs up one byte. This
  692.    tells  you that the screen is not displaying correct instructions. One or
  693.    more of those at the top (where MD86 backed up) is not correct.
  694.  
  695.    If  the  screen  is  not  correct,  then  how do you make it correct? The
  696.    easiest  way  is  to  back  up  a full page (Up Page command) and then go
  697.    forward  a  full  page  (Down  Page command). More than likely, MD86 will
  698.    correctly  synchronize  somewhere  on  the  screen  when  you  backed  up
  699.    (probably at a labeled instruction) and everything from there on downward
  700.    will be correct.
  701.  
  702.    One  point  of  interest  will  surely  pop up. When a NOP instruction is
  703.    disassembled,  it  is  flaged  as  "questionable"  unless  the previously
  704.    disassembled instruction was a short JMP. However, if the cursor is moved
  705.    upward  to  a NOP instruction, MD86 marks this line incorrectly since the
  706.    instruction   disassembled   prior  to  this  was  actually  a  following
  707.    instruction.
  708.  
  709.    A word of caution. When MD86 incorrectly disassembles a line for whatever
  710.    reason, erroneous address references may be added to the label pool. This
  711.    is  where  the  Scan  command  (F6 key) comes in. It erases all temporary
  712.    labels  (ones  that  have  not  been  given  names  by  you)  and  begins
  713.    disassembling  the  whole  program  from  the starting address. This will
  714.    correctly build the temporary label pool.
  715.  
  716.  
  717.    3.2) Questionable Instructions
  718.  
  719.    When  MD86 disassembles an instruction line, it will check to see whether
  720.    or  not  this instruction makes sense. If it does not, a flag ("?" to the
  721.    left  of  the  label  field)  is  set  but  it  is disassembled anyway if
  722.    possible.  Valid  instructions  are considered "questionable" if they are
  723.    very rarely used or are "meaningless".
  724.  
  725.    In  the  rarely  used catagory are the instructions "LOCK", "ESC", "INT",è   "XLAT",  "WAIT",  "HLT", and far returns within a "COM" file. Further any
  726.    instructions  made  up of the exact same bytes (eg "ADD [BX+SI],AL" which
  727.    is two bytes of 00) is considered questionable.
  728.  
  729.  
  730.  page 14      Masterful Disassembler - Intel 8086  version 1.00      page 14
  731.  
  732.  
  733.  
  734.    Meaningless instructions are "NOP" and "MOV destination,source" where the
  735.    source  and  destinations  are  the  same.  Note  that a "NOP" is allowed
  736.    following a two byte forward jump instruction.
  737.  
  738.    Depending  on  the type of program being disassembled, there may be a few
  739.    or  a  lot of such "questionable" instructions that are actually supposed
  740.    to be there. Thus this "questionable" instruction flag is just a guide to
  741.    help you locate imbedded data areas.
  742.  
  743.  
  744.    3.3) Instructions prefix bytes
  745.  
  746.    Like  the Intel 8086 processor, MD recognizes certain prefix bytes. These
  747.    are  the  segment  override instructions and the repeat instructions. The
  748.    bus  lock  instruction is considered separate as this is very rarely used
  749.    (it  is also flaged as "questionable"). When moving the cursor around, it
  750.    is  possible miss the prefix byte. This will occur most often when moving
  751.    upward.  MD  only  looks  at the previous six bytes to determine where an
  752.    instruction starts. If the seventh byte were a prefix byte, this would be
  753.    missed.  When  a  jump  is made (Function F2) MD does not check to see if
  754.    this is in the middle of an instruction. Here too, a prefix byte could be
  755.    missed.
  756.  
  757.    The  effect  of  missing  a prefix byte could cause label addresses to be
  758.    associated  with  the wrong segment. The scan option (Function F6) can be
  759.    used to clean up this type of misinformation.
  760.  
  761.    While  this  is  not  the  same  as  a  prefix  byte, MD86 checks for NOP
  762.    instructions  that  are preceeded by a short forward jump instruction. If
  763.    this  is  not  the  case,  then the NOP is marked as "questionable". This
  764.    logic  fails  when  the NOP is in the top line of the screen. There is no
  765.    preceeding instruction to check and the NOP is marked "questionable" even
  766.    though  it  may  be  perfectly valid. When moving the cursor upward, MD86
  767.    will  incorrectly  mark  a NOP as questionable. The logic only works when
  768.    moving the cursor downward.
  769.  
  770.  
  771.    3.4) Segment Handling
  772.  
  773.    MD86  recognizes  references  to  the  four  segments  of  the Intel 8086
  774.    processor.  It  keeps  four  separate  tables for the labels within these
  775.    segments.  An  exception  is  with  COM  type  files. For these, the data
  776.    segment  and  the  code  segment are assumed to be the same. Data segment
  777.    references  are  forced  into  the  code segment space. This is generally
  778.    correct,  but  it  is  possible  that the program creates a separate data
  779.    segment.  In  this case the labels generated by MD86 will be put into the
  780.    code  segment  when they belong in the data segment. Not much can be done
  781.    about  this until after a source file has been produced. Use an editor to
  782.    fix these things.è
  783.  
  784.  page 15      Masterful Disassembler - Intel 8086  version 1.00      page 15
  785.  
  786.  
  787.  
  788.    3.5) Known Compatibility Problems With MASM
  789.  
  790.    MD86  was  designed  to  produce  source  files  to be used with the MASM
  791.    assembler  from  Microsoft.  This is the most common assembler and as you
  792.    probably know it is not the easiest assembler to use. MASM tries to guard
  793.    you  against  yourself.  When  variables  are defined as bytes, then MASM
  794.    checks  to  be  sure they are referenced as such. At times this is handy.
  795.    But  mostly  it is an annoyance. When disassembling a program it is often
  796.    times difficult to determine how labels are referenced. At the very least
  797.    it  would  consume  lots  of  time  which  would be better spent on other
  798.    aspects  of the code. To prevent MASM from generating numerous errors due
  799.    to  seemingly  inconsistent references, MD86 inserts WORD PTR or BYTE PTR
  800.    to  force  MASM into accepting these references. This results in the over
  801.    use of these override phrases (and a larger than necessary source file).
  802.  
  803.    When MD86 notices a reference to an item within the data or code segments
  804.    that  is  outside of the limits of the actual program file, it inserts an
  805.    EQU  statement  to equate the label with its value. MD86 is thus assuming
  806.    the  the  reference  is  to  a constant value and not a variable address.
  807.    Under  some  assemblers  there is no difference between a constant and an
  808.    address  (or  offset). But MASM does make the distinction and flags as an
  809.    error  an  inconsistent reference. The following error message is typical
  810.    of this occurrence.
  811.  
  812.  
  813.      CMP.ASM(176) : error 56: No immediate mode
  814.  
  815.  
  816.    This  is MASM's way of telling you that line 176 in file CMP.ASM contains
  817.    a  reference  to a variable where the label has been defined as a number.
  818.    The  solution is to modify the source code file and change the definition
  819.    of this label from an EQU into a DB or DW. Thus the line
  820.  
  821.  
  822.      HELPTXT  EQU   00050H
  823.  
  824.  
  825.    should be change into the following lines.
  826.  
  827.  
  828.               ORG   00050H
  829.      HELPTXT: DB    0
  830.  
  831.  
  832.    You  won't  need  the  ORG statement in front of every definition line as
  833.    long as the data type is consistent.
  834.  
  835.    EXE  programs  pose other problems that must be dealt with. MD86 does not
  836.    resolve  FAR  jumps and calls. You will have to determine the destinationè   address  and  equate  this  to a label. The absolute address is shown but
  837.    MD86 cannot find out where this ends up.
  838.  
  839.  
  840. 1
  841.  
  842.  page 16      Masterful Disassembler - Intel 8086  version 1.00      page 16
  843.  
  844.  
  845.    Returns  from  FAR  procedures  are  flaged  by MD86, but the instruction
  846.    inserted is RET. MASM will determine if this is a NEAR or FAR return from
  847.    the  definition  of  the  procedure.  Thus,  you  will have to define the
  848.    procedure  containing  the  FAR  return as a FAR procedure. If you don't,
  849.    then  MASM will assume a NEAR return is to be generated. No error message
  850.    is displayed but this will not execute the same as a FAR return.
  851.  
  852.    Another  problem  with  EXE  type  files concerns segment definition. The
  853.    output  file generated by MD86 should assemble and even link okay, but it
  854.    probably  won't execute correctly without being changed. You will need to
  855.    look  into  adding  ASSUME  and  GROUP  statements in the various segment
  856.    blocks.
  857.  
  858.    EXE  files  can  be  constructed  in  many,  many ways. It will take some
  859.    persistence to resolve these differences.
  860.  
  861.  
  862.  4.0) A Short Course In Generating Source Code
  863.  
  864.  The  process  of disassembling a program and recreating source code is more
  865.  art  than science. The more practice you have the easier this becomes. MD86
  866.  (as  well as other programs) have been written to make this process as easy
  867.  as  possible. As "smart" as they are, there is a long way to go before this
  868.  can be considered "automated".
  869.  
  870.  Prior  to  starting  to  disassemble that super new program, there are some
  871.  questions you must ask your self.
  872.  
  873.  
  874.     o Do I really need the source code for this program?
  875.  
  876.     o Is the program small enough for me to handle?
  877.  
  878.     o Was the program written in a lower level language (C or assembler)?
  879.  
  880.     o Do I really know how this program functions and all of what it does?
  881.  
  882.  
  883.  These  questions  are  important  as  the  answers  can give you an idea of
  884.  whether  you  can  finish  the  job once you start it. There is no point in
  885.  "cheating" on the answers either. You only have yourself to convenience.
  886.  
  887.  Source code generation is a three step process.
  888.  
  889.  There  are  three  distinct phases users go through when they disassemble a
  890.  program.  The  first  phase  is to identify the type of data the program isè composed  of.  Programs consist of machine instructions and data. But which
  891.  is  which? You must follow the logic to tell. The only technical difference
  892.  is  that  machine instructions are executed while data is referenced. It is
  893.  quite  possible  for  instructions  in  one part of a program to be data to
  894.  another  part.  With  the  different segments of the Intel 8086 this is not
  895.  very common. But it is certainly possible.
  896.  
  897.  
  898.  page 17      Masterful Disassembler - Intel 8086  version 1.00      page 17
  899.  
  900.  
  901.  Once  the  program  has  been  divided into instruction and data areas, the
  902.  second  phase  begins.  This  is  the  process of identifying the different
  903.  logical  parts. This is usually the most difficult and time consuming part.
  904.  It  is  not easy to understand what purpose a sequence of instructions has,
  905.  but with persistence this can be done.
  906.  
  907.  The third stage involves generating an assembler source file and getting it
  908.  to  re-assemble  properly. Disassemblers are only "human". Their output may
  909.  assemble without error but it probably won't be a byte-for-byte copy of the
  910.  original  file.  Some "touch-up" will be required to rectify such things as
  911.  long  and short jumps. While you are at it, you could clean up the comments
  912.  and "pretty up" the source file.
  913.  
  914.  
  915.    4.1) Identifying Data Types
  916.  
  917.    There  is  a  real knack to separating the code into data and instruction
  918.    areas. MD86 goes a long way my marking "questionable" instructions with a
  919.    question  mark  to  the left of the label field. This mark will appear on
  920.    the  screen  as  well  as  in  a  PRN type output source file. It will be
  921.    removed when a non-PRN output file is generated.
  922.  
  923.    Initially  MD86  sees  the  entire  code  segment as instructions and the
  924.    entire  data  segment  (EXE  type  programs  only)  as 8-bit binary data.
  925.    However, most of the time this is not the case. It is very common to find
  926.    character  strings imbedded within the code as well as normal data areas.
  927.    When  MD86 marks an instruction line as "questionable", examine the lines
  928.    above  and below to determine where the instructions end and data begins.
  929.    Of course it is possible that MD86 was wrong in it judgement and the line
  930.    is correct.
  931.  
  932.    MD86  assumes  that  memory  is made up of either machine instructions or
  933.    data.  The  data may be either 8-bit binary (numbers in the range 0-255),
  934.    8-bit  character  data,  or 16-bit address (or offset) data. As mentioned
  935.    above,  the  Intel 8086 processor sees instructions as data that it is to
  936.    execute  and other data is just referenced. In the sections below we will
  937.    assume  that  instruction  areas  are  sequences of instructions that are
  938.    executed in order and everything else is data.
  939.  
  940.    There are five basic rules that can be used to determine data area types.
  941.    When  you identify data areas, make sure these rules have been satisfied.
  942.    If not, be very suspicious.
  943.  
  944.  
  945.      o rule 1
  946.  
  947.      The  instruction preceeding a data area must be a transfer (jump, call,
  948.      interupt, or return). Conditional jumps would not be allowed unless the
  949.      condition was ALWAYS met.
  950.  
  951.  
  952.  page 18      Masterful Disassembler - Intel 8086  version 1.00      page 18
  953.  
  954.  
  955.      o rule 2
  956.  
  957.      The  first  instruction in an instruction area must have a label unless
  958.      the  preceeding  data  area  was  an  argument  to  a  call or interupt
  959.      instruction.
  960.  
  961.  
  962.      o rule 3
  963.  
  964.      An  absolute  transfer of control (jump or return) may be followed only
  965.      by a labeled instruction or a labeled data area.
  966.  
  967.  
  968.      o rule 4
  969.  
  970.      For the type of data to change (from instructions to data or from ASCII
  971.      data  to  16-bit  address  data etc.), the first line of the newer type
  972.      must have a label.
  973.  
  974.  
  975.      o rule 5
  976.  
  977.      ASCII  character  data  (including  carriage returns, line feeds, etc.)
  978.      must  either begin with a character count byte (or word) or it must end
  979.      with  with  a  special  (generally non-ASCII) byte. Is is common within
  980.      MSDOS  applications that character strings end with a dollar sign. This
  981.      is the way the console output and printer output functions know the end
  982.      of  a  string.  Assembly  programmers  also like to use null characters
  983.      (value  of zero) as an end of string mark. The Intel 8086 processor can
  984.      easily detect these.
  985.  
  986.  
  987.    For purposes of an example, Figures IIa through IIc will be used. This is
  988.    fairly typical of the kind of code you will encounter. But be forewarned,
  989.    by  its  very nature assembly code can be very obscure. If the programmer
  990.    wishes, it could be extremely difficult to decipher.
  991.  
  992.    Refering  to  Figure  IIa,  note  how  several  lines have been marked as
  993.    "questionable".  Here  it  is  obvious  that the lines following the jump
  994.    instruction  at address 1283 cannot be instructions. The PUSH instruction
  995.    at  address  1286 is erroneous because of rule #1. Notice how most of the
  996.    bytes following address 1283 have a value in the range 20 to 7E (hex). It
  997.    is quite possible that this area consists mainly of ASCII characters. But
  998.    where  does this area end? Rule #2 says we should look for the next valid
  999.    instruction  line  containing  a  label.  In this example we find this at
  1000.    address  12A2. A word of caution here. Since we may not have disassembled
  1001.    the entire program, the label pool may be incomplete. It is then possible
  1002.    that  at  this  time  an instruction does not have a label. We need to be
  1003.    cautious in the application of rule #2.
  1004.  
  1005.  
  1006.  page 19      Masterful Disassembler - Intel 8086  version 1.00      page 19
  1007.  
  1008.  
  1009.           Figure IIa, Typical Display Of Partially Disassembled Program
  1010.  
  1011.  
  1012.  127D:BE5011      _         MOV   SI,#L1150H    ;
  1013.  1280:E822FC                CALL  L0EA5H        ;
  1014.  1283:E9DB1B                JMP   L2E61H        ;
  1015.  1286:55           L1286H   PUSH  BP            ;
  1016.  1287:6E          ?         DB    06EH          ;
  1017.  1288:6B          ?         DB    06BH          ;
  1018.  1289:6E          ?         DB    06EH          ;
  1019.  128A:6F          ?         DB    06FH          ;
  1020.  128B:776E                  JA    L12FBH        ;
  1021.  128D:207665                AND   [BP]+65H,DH   ;
  1022.  1290:7273                  JC    L1305H        ;
  1023.  1292:69          ?         DB    069H          ;
  1024.  1293:6F          ?         DB    06FH          ;
  1025.  1294:6E          ?         DB    06EH          ;
  1026.  1295:206F66                AND   [BX]+66H,CH   ;
  1027.  1298:205475                AND   [SI]+75H,DL   ;
  1028.  129B:7262                  JC    L12FFH        ;
  1029.  129D:6F          ?         DB    06FH          ;
  1030.  129E:0D0A00                OR    AX,#L000AH    ;
  1031.  12A1:FF          ?L12A1H   DB    0FFH          ;
  1032.  12A2:9C           L12A2H   CBW                 ;Convert byte (AL) to word
  1033.  12A3:2E803EA112FF          CMP   CS:[L12A1H],0FFH;
  1034.  12A9:7404                  JZ    L12AFH        ;
  1035.  12AB:9D                    CWD                 ;Convert word (AX) to dbl w
  1036.  CS:: Labels= 492/23%, Types=  21/  4%,   0 cmnts  No Edit 10/ 3/87 10:20:35
  1037.  
  1038.  
  1039.    As a first step, we use Function key F3 to set the area from 1286 to 12A1
  1040.    as  characters (type #2). The code now makes more sense (see Figure IIb).
  1041.    But  now  notice address 12B4. This instruction does not have a label and
  1042.    yet  it  follows  an unconditional transfer (return) instruction. Rule #3
  1043.    says  this  is  not correct. Now it could be that there should be a label
  1044.    here  and  we  have  just  not  disassembled  the  section  of  code that
  1045.    references  it,  but  the  instructions don't look right do they? The hex
  1046.    sequences  06, 07, 08, 09, and C3, C4, C5, C6, C7, C8 would not likely be
  1047.    instructions (although obviously possible). It looks more like numbers or
  1048.    data.  In  fact the whole area from address 12AD up to 12B8 does not look
  1049.    like  instructions  at  all.  Most  probably  this  is  just  a data area
  1050.    containing  numerical  values.  And  8-bit  values  at that. If they were
  1051.    16-bit  values (or addresses), they would be way beyond the bounds of our
  1052.    code.
  1053.  
  1054.    So  again  using  Function  key F3, we set this area to 8-bit binary data
  1055.    (type  #1). Figure IIc shows what the screen looks like now. Compare this
  1056.    with Figure IIa and you can see the improvement. In this way areas of the
  1057.    program  are  disassembled one section at a time. Progress at first seems
  1058.    slow  I  realize,  but after a while the pieces start to fit together. Asè   you begin to understand these small portions the remainder of the program
  1059.    becomes  that  much  easier.  You are well on your way to a useful source
  1060.    file.
  1061.  
  1062.  
  1063.  page 20      Masterful Disassembler - Intel 8086  version 1.00      page 20
  1064.  
  1065.  
  1066.  
  1067.  
  1068.           Figure IIb, Typical Display Of Partially Disassembled Program
  1069.  
  1070.  
  1071.  127D:BE5011      _         MOV   SI,#L1150H    ;
  1072.  1280:E822FC                CALL  L0EA5H        ;
  1073.  1283:E9DB1B                JMP   L2E61H        ;
  1074.  1286:556E6B6E6F77 L1286H   DB    'Unknown version ';
  1075.  1296:6F6620547572          DB    'of Turbo',CR,LF,0;
  1076.  12A1:FF           L12A1    DB    0FFH          ;
  1077.  12A2:9C           L12A2H   CBW                 ;Convert byte (AL) to word
  1078.  12A3:2E803EA112FF          CMP   CS:[L12A1H],0FFH;
  1079.  12A9:7404                  JZ    L12ACH        ;
  1080.  12AB:9D                    CWD                 ;Convert (AX) to dbl word
  1081.  12AC:C3           L12ACH   RET                 ;
  1082.  12AD:2EC606070809 L12ADH   MOV   CS:[L0807H],#09;
  1083.  12B3:C3                    RET                 ;
  1084.  12B4:C4C5                  LES   AX,BP         ;
  1085.  12B6:C6C7C8                MOV   BH,C8         ;
  1086.  12B9:E8C6FC       L12B8H   CALL  L0F82H        ;
  1087.  12BE:8B4616                MOV   AX,[BP]+16H   ;
  1088.  12C1:A38A01                MOV   [L018AH],AX   ;
  1089.  12C4:8B4604                MOV   AX,[BP]+4     ;
  1090.  12C7:A38C01                MOV   [L018CH],AX   ;
  1091.  12CA:1E                    PUSH  DS            ;
  1092.  12CB:C516AA11              LDS   DX,[L11AAH]   ;Load DS:DX with 32b pointe
  1093.  12CF:B010                  MOV   AL,#10H       ;
  1094.  12D1:B425CD21              MSDOS _SIVEC        ;Set vector.
  1095.  CS:: Labels= 492/23%, Types=  21/  4%,   0 cmnts  No Edit 10/ 3/87 10:20:35
  1096.  
  1097.  
  1098.    For  EXE  type programs, there is a separate data segment to worry about.
  1099.    While  this probably does not contain instructions, it is still necessary
  1100.    to  determine  if  there are any address references stored here. If there
  1101.    are,  then  they should be identified as such so they can be entered into
  1102.    the label pool.
  1103.  
  1104.    In  some  cases tables of addresses can be spotted easily. If most of the
  1105.    addresses  are  close  (within  a  few  pages)  then you will see similar
  1106.    hexadecimal values every other byte. For example:
  1107.  
  1108.  
  1109.  1234:017F097F0F7F L1234H   DB    1,7FH,9,7FH,0FH,7FH;
  1110.  123A:137F4F7F1080          DB    13H,7FH,4FH,7FH,10H,80H;
  1111.  
  1112.  
  1113.    When  these  areas  are  changed  into 16-bit address (type #3) then they
  1114.    appear as follows.
  1115. è
  1116.  1234:017F097F0F7F L1234H   DW    7F01H,7F09H,7F0FH;
  1117.  123A:137F4F7F1080          DW    7F13H,7F4FH,8010H;
  1118.  
  1119.  
  1120.  page 21      Masterful Disassembler - Intel 8086  version 1.00      page 21
  1121.  
  1122.  
  1123.  
  1124.  
  1125.           Figure IIc, Typical Display Of Partially Disassembled Program
  1126.  
  1127.  
  1128.  127D:BE5011      _         MOV   SI,#L1150H    ;
  1129.  1280:E822FC                CALL  L0EA5H        ;
  1130.  1283:E9DB1B                JMP   L2E61H        ;
  1131.  1286:556E6B6E6F77 L1286H   DB    'Unknown version ';
  1132.  1296:6F6620547572          DB    'of Turbo',CR,LF,0;
  1133.  12A1:FF           L12A1    DB    0FFH          ;
  1134.  12A2:9C           L12A2H   CBW                 ;Convert byte (AL) to word
  1135.  12A3:2E803EA112FF          CMP   CS:[L12A1H],0FFH;
  1136.  12A9:7404                  JZ    L12ACH        ;
  1137.  12AB:9D                    CWD                 ;Convert (AX) to dbl word
  1138.  12AC:C3           L12ACH   RET                 ;
  1139.  12AD:2EC606070809 L12ADH   DB    2EH,0C6H,6,7,8,9,0C3H;
  1140.  12B4:C4C5C6C7              DB    0C4H,0C5H,0C6H,0C7H;
  1141.  12B8:C8                    DB    0C8H          ;
  1142.  12B9:E8C6FC       L12B8H   CALL  L0F82H        ;
  1143.  12BC:8B4616                MOV   AX,[BP]+16H   ;
  1144.  12BF:A38A01                MOV   [L018AH],AX   ;
  1145.  12C2:8B4604                MOV   AX,[BP]+4     ;
  1146.  12C5:A38C01                MOV   [L018CH],AX   ;
  1147.  12C8:1E                    PUSH  DS            ;
  1148.  12C9:C516AA11              LDS   DX,[L11AAH]   ;Load DS:DX with 32b pointe
  1149.  12CD:B010                  MOV   AL,#10H       ;
  1150.  12CF:B425CD21              MSDOS _SIVEC        ;Set vector.
  1151.  12D3:1F                    POP   DS            ;
  1152.  CS:: Labels= 492/23%, Types=  21/  4%,   0 cmnts  No Edit 10/ 3/87 10:20:35
  1153.  
  1154.  
  1155.    The  contents  of  these  areas are then added to the address label pool.
  1156.    When  disassembled,  these  areas  will have a label to let you know that
  1157.    they are referenced somewhere.
  1158.  
  1159.    Notice  how  the  first  address  of  this  table has a reference. Rule 4
  1160.    indicates that this is required. However this is not strictly true. It is
  1161.    possible  that  the  beginning  of this area is implied by the end of the
  1162.    previous  structure.  One  common  approach is to have a sequence of flag
  1163.    bytes  that  is  followed  by  a corresponding address table. Because the
  1164.    program  "knows"  how  long  the leading byte table is, is then knows the
  1165.    start of the address table.
  1166.  
  1167.    MD86  assumes  that  any  address  references present in the data segment
  1168.    refer  to  offsets within the code segment. While this is generally true,
  1169.    at  times  this  is  incorrect.  If  it  is  known  to  be  incorrect (by
  1170.    examination  of  the  code that refers to the table of addresses), then a
  1171.    choice  has  to  be  made.  Either these addresses must not be defined as
  1172.    16-bit  addresses  (change  this  to 8-bit binary data), or the erroreousè   references  to  the  code segment must be tolerated. It is suggested that
  1173.    these  be  changed into 8-bit binary data. You could then add label names
  1174.    to these references within the data segment to keep this correct.
  1175.  
  1176.  
  1177.  page 22      Masterful Disassembler - Intel 8086  version 1.00      page 22
  1178.  
  1179.  
  1180.  
  1181.  
  1182.    4.2) Understanding the Code
  1183.  
  1184.    This is the part you have been waiting for. The real guts of the job! You
  1185.    have   now   separated  all  data  from  instructions  but  what  do  the
  1186.    instructions mean?
  1187.  
  1188.    The Intel 8086 executes instructions in a logical order; the order chosen
  1189.    by  the  programmer. To truly understand the function of the instructions
  1190.    you  must  know  how  they  are  executed.  For example, just knowing the
  1191.    instruction
  1192.  
  1193.  
  1194.      123A:2C07                  SUB   AL,7
  1195.  
  1196.  
  1197.    will  subtract  7  from  the contents of register AL is not very helpful.
  1198.    However, if the surrounding instructions were
  1199.  
  1200.  
  1201.      1234:8A07                  MOV   AL,[BX]       ;
  1202.      1236:3C3A                  CMP   AL,':'        ;
  1203.      1238:7202                  JC    L123BH        ;
  1204.      123A:2C07                  SUB   AL,7          ;
  1205.      123B:2C30          L123BH  SUB   AL,'0'        ;
  1206.      123D:8807                  MOV [BX],AL         ;
  1207.  
  1208.  
  1209.    you  then  have  the  feeling that register BX is pointing to one or more
  1210.    bytes. And if these bytes are greater than the digit 9 (the character ":"
  1211.    is  just  passed  the  digit  "9"  in  the ASCII character set) then 7 is
  1212.    subtracted.  Looking  7  passed  the  "9"  digit  in  the  table of ASCII
  1213.    characters  you find the letter "A". Then in either case the value of the
  1214.    digit  "0" is subtracted. In other words, if register BX were pointing to
  1215.    an  "8",  then  this  would  be  replaced with the binary value of 8. If,
  1216.    however,  BX points to the letter "C", it will be replaced with the value
  1217.    12.  So  this is just converting a hexadecimal digit or digits from ASCII
  1218.    to  binary.  Well  of course! We "know" this program asks for hexadecimal
  1219.    values and has to interpret them because in this case we are looking at a
  1220.    DEBUG.
  1221.  
  1222.    Because  the  processor executes instructions in a certain order, we must
  1223.    examine  them  in  that  order. This might seem obvious (and in the above
  1224.    example  it  is) but in many cases it is not easy to determine the way in
  1225.    which instructions are executed. Consider the following code.
  1226.  
  1227.  
  1228.      1234:E83033                CALL  L4567H       ;
  1229.      1237:0130                  ADD   [BX+SI],SI   ;è     1239:337200                XOR   SI,[BP+SI]+0 ;
  1230.  
  1231.  
  1232.  page 23      Masterful Disassembler - Intel 8086  version 1.00      page 23
  1233.  
  1234.  
  1235.    The  ADD  instruction following the CALL is not actually executed at all.
  1236.    By looking at the routine at address 4567 we find that the byte following
  1237.    the  initial CALL is just a parameter. This byte gets used and the return
  1238.    will  be  to the following address (1238). We would not have been able to
  1239.    tell  this  if we hadn't looked at the instructions in the same order the
  1240.    processor does.
  1241.  
  1242.    When  you  pick apart even a small section of code you should enter a few
  1243.    comments and add a label name if you can. Then you won't have to reinvent
  1244.    the  wheel  the  next time you look at this code (and you will look at it
  1245.    more than once!).
  1246.  
  1247.    This process is going to be very laborious. It takes many instructions in
  1248.    assembly  language  to  accomplish  seemingly trivial functions. Like the
  1249.    simple   BASIC   statement  "LET  A(1,2)=B+C^2"  may  take  thousands  of
  1250.    instructions  and  involve many subroutines. But all is not lost. Because
  1251.    you  know  how the program executes (at least in a gross sense), you will
  1252.    be able to tackle small portions of it at a time.
  1253.  
  1254.    Any  information  you  can  get  your  hands  on will help. User manuals,
  1255.    especially  reference  manuals are a valuable source of information. Some
  1256.    go  so  far  as  to include memory maps and descriptions of internal data
  1257.    types. Take TURBO Pascal for example, the manual is a real gold mine!
  1258.  
  1259.    A bottoms up approach has proven to be the most useful when disassembling
  1260.    a  program.  Start  from  the lowest level. Look for the operating system
  1261.    interface.  The reason is that these are well defined and have a specific
  1262.    calling sequence. MD86 recognizes many of the MSDOS system calls and uses
  1263.    more meaningful representations. For example the instructions
  1264.  
  1265.  
  1266.      1234:B409                  MOV   AL,9      ;
  1267.      1236:CD21                  INT   21H       ;
  1268.  
  1269.  
  1270.    is replaced with a single macro instruction
  1271.  
  1272.  
  1273.      1234:B409CD21              MSDOS _OUTSTR   ;Display string at (DX)
  1274.  
  1275.  
  1276.    In  this way you can identify the lowest level routines. Those that write
  1277.    characters  to  the  screen  or  read the keyboard. How about opening and
  1278.    closing  files  and  input  and  output  from  the  communications ports?
  1279.    Generally   these  are  short  subroutines  (<100  lines)  that  you  can
  1280.    comprehend.  Try  to  find as many of these routines as possible and give
  1281.    each one a name that will help you to remember what it does. Also toss in
  1282.    as many comments as you can.
  1283.  
  1284.    Once  the  lowest  routines  have  been  worked on, the next higher levelè   becomes  easier.  Now  you can find those routines that read and write to
  1285.    files  buffers  without worrying about all those instructions required to
  1286.    actually get the data out to the disk.
  1287.  
  1288.  
  1289.  page 24      Masterful Disassembler - Intel 8086  version 1.00      page 24
  1290.  
  1291.  
  1292.  
  1293.    In  this  way the program gradually starts to unravel and before you know
  1294.    it you will actually understand how the programmer was able to write it.
  1295.  
  1296.    Execute  files  (those  with  the extension EXE) introduce a whole set of
  1297.    additional  problems.  Not  the  least  of  which  is  determining actual
  1298.    physical address for instructions. You see, the Intel 8086 constructs the
  1299.    physical  address  at run time from a segment register and an offset. The
  1300.    relationship is:
  1301.  
  1302.  
  1303.      physical address = segment*16 + offset
  1304.  
  1305.  
  1306.    Because  each  register  is  16  bits  long,  there is the possibility of
  1307.    tremendous  overlap.  An  offset  of 100 into segment 1234 is the same as
  1308.    offset  110 into segment 1233. To further complicate matters, the segment
  1309.    registers  can  be changed at will. Thus when an instruction is executed,
  1310.    the  contents  of  the segment registers (which may have been defined who
  1311.    knows  where)  are  of  vital  importance. The more segment registers are
  1312.    modified within a program, the tougher the job of disassembly is.
  1313.  
  1314.    As  an  example  of  a typical execute program, lets look at EXE2BIN.EXE.
  1315.    Within the first few instructions we see the following code.
  1316.  
  1317.  
  1318.      0000:1E          PUSH  DS
  1319.      0001:33C0        XOR   AX,AX
  1320.      0003:50          PUSH  AX
  1321.      0004:B430CD21    MSDOS _GETVER
  1322.      0008:3C02        CMP   AL,2
  1323.      000A:7D13        JGE   L001FH
  1324.      000C:BB3900      MOV   BX,#L0039H
  1325.      000F:8EDB        MOV   DS,BX
  1326.      0011:BA5B01      MOV   DX,#L015BH
  1327.      0014:0E          PUSH  CS
  1328.      0015:1F          POP   DS
  1329.      0016:B409CD21    MSDOS _OUTST
  1330.      001A:06          PUSH  ES
  1331.      001B:33C0        XOR   AX,AX
  1332.      001D:50          PUSH  AX
  1333.      001E:CB          RET
  1334.      001F:BE8100      MOV   SI,#L0081H
  1335.      0022:BB3900      MOV   BX,#L0039H
  1336.      0025:8EC3        MOV   ES,BX
  1337.  
  1338.  
  1339.    Lets  look at this code for a second. We see that almost the first action
  1340.    of this is to call MSDOS and find out what its version number is. If this
  1341.    number  is  greater than or equal to 2 then this jumps to offset 001F. Soè   the  code between 000C and 001E is only executed if the version number is
  1342.    less  than  2.  Following the jump instruction, the next two instructions
  1343.    initialize  the  data  segment  register  (DS) to 39 hex. That means that
  1344.  
  1345.  
  1346.  page 25      Masterful Disassembler - Intel 8086  version 1.00      page 25
  1347.  
  1348.  
  1349.    further references into the data segment will get to physical address 390
  1350.    hex  +  offset. The next instruction loads the DX register with the value
  1351.    15B  hex. Now if we take a quick look at address 4EB hex (390+15B=4EB) in
  1352.    our  code  we  will  find  the  start of the ascii message "Incorrect DOS
  1353.    version$".  A  quick  note,  normally  these  addresses  (ie 4EB) will be
  1354.    relative  to  the  start  of the data segment within the EXE file and the
  1355.    code  segment  follows  this  immediately.  Thus we have to look at 4EB -
  1356.    data_segment_size  within our code. But for EXE2BIN.EXE, the data segment
  1357.    size  was  zero  so  we  can  look  directly  at address 4EB. Now the two
  1358.    following instructions are very curious. By executing the PUSH CS and POP
  1359.    DS  we  will  effectively  reset  the  data  segment register to the code
  1360.    segment  register,  or  zero  within  our  file.  Thus  the call to MSDOS
  1361.    function  to  display  an  ascii  character  string  will  try to get the
  1362.    characters  from  offset  15B  instead  of 4EB. This is a definite bug in
  1363.    EXE2BIN.EXE!  The PUSH and POP instructions should not be there. Even the
  1364.    best  programs  can  contain bugs. Don't be too alarmed when you run into
  1365.    one.
  1366.  
  1367.    Moving  on, at addresses 22 and 25 we see that the extra segment register
  1368.    (ES)  is being set to 39 hex just like the data segment register was set.
  1369.    This  should  give us a real strong indication that address 390 hex (or a
  1370.    few  bytes beyond) we will find the start of a data area within our code.
  1371.    This will help us later on.
  1372.  
  1373.    One further note, when MSDOS executes an EXE type program, it initializes
  1374.    the  data  segment and extra segment registers to point to an area called
  1375.    the  Program  Segment  Prefix (PSP). This area contains many useful items
  1376.    that  the  program  will  need. So prior to changing these registers, the
  1377.    program will examine this area for those items it needs. Figure III lists
  1378.    those  items  that are of most interest to us. Refer to reference 1 for a
  1379.    more complete discussion of this area.
  1380.  
  1381.  
  1382.  page 26      Masterful Disassembler - Intel 8086  version 1.00      page 26
  1383.  
  1384.  
  1385.  
  1386.                 Figure III, The Program Segment Prefix Summary
  1387.  
  1388.  
  1389.      Offset  |                           Contents
  1390.      ------  | ------------------------------------------------------------
  1391.       0002   | System memory size in paragraphs (16 byte blocks). This is a
  1392.              | 16 bit integer.
  1393.              |
  1394.       000E   | Control-C exit address. First 2 bytes are offset and second
  1395.              | 2 bytes are the segment.
  1396.              |
  1397.       0012   | Hard error exit. 2 byte offset and 2 byte segment.
  1398.              |
  1399.       005C   | Unopened file control block for first file specified after
  1400.              | command. Only valid if a path is not specified.
  1401.              |
  1402.       006C   | Unopened file control block for second file specified after
  1403.              | command. Only valid if a path is not specified.
  1404.              |
  1405.       0080   | Entire text string the follows the command. The first byte
  1406.              | is a character count. Note redirection information is not
  1407.              | passed on to the program (it is stripped first).
  1408.  
  1409.  
  1410.    4.3) Polishing the Source Code
  1411.  
  1412.    Sooner  or  later  you  will come to the point where you must abandon the
  1413.    disassembler.  It  has  done  its  job  but now an editor would be better
  1414.    suited to working on the files.
  1415.  
  1416.    Once  you  get  a source file out of MD86 then you can try assembling it.
  1417.    There  will  undoubtedly be many areas where MASM will complain. Segments
  1418.    may  be  defined  in  the wrong order or some external references are not
  1419.    defined at all.
  1420.  
  1421.    Get  yourself  a  good  screen  oriented  editor. One with virtual memory
  1422.    support  is vital. Assembly programs tend to be very large and it will be
  1423.    a real pain if you have to break it into small pieces because your editor
  1424.    limits  the  code  to 64k. You are going to especially need global search
  1425.    and replace functions. WordStar, although rather slow, does work fine for
  1426.    this type of work as long as you don't use document mode.
  1427.  
  1428.    MD86  always  inserts  data type pointer override instructions. These are
  1429.    the WORD PTR and BYTE PTR sequences you see all over the place. MASM does
  1430.    not  require  an override if the types already match. That is, a value is
  1431.    referenced  as  a  16-bit word and it has previously been defined as this
  1432.    type,  then  an override is not required. Since MD86 does not know enough
  1433.    to be sure these conditions have been met, WORD PTR will be inserted. One
  1434.    of  the first things you will want to do is to remove these phrases whereè   they are not needed. They just clutter the code.
  1435.  
  1436.    EXE type files pose the biggest challenge to MD86 and MASM will certainly
  1437.  
  1438.  
  1439.  page 27      Masterful Disassembler - Intel 8086  version 1.00      page 27
  1440.  
  1441.  
  1442.    complain about some aspect of the way the different segments are handled.
  1443.  
  1444.    MD86  rather  simplemindedly inserts tables for each segment that has any
  1445.    labels  defined at the start of the program. Although careful use of MD86
  1446.    will limit the number of erroneous labels, some extra ones will exits and
  1447.    these tables will end up being quite long.
  1448.  
  1449.    When  MD86 encounters an instruction that references a 16-bit quantity it
  1450.    assumes  that  this  is  an  address  (or  more properly an offset into a
  1451.    segment).  This address is put into the label pool. It is not possible to
  1452.    distinguish  an address reference from a pure constant. Thus you will see
  1453.    many  labels  in the segment tables (mainly the data segment) with values
  1454.    line  0,  1, 2, 7, etc. Now these may be valid addresses, but most likely
  1455.    they  are  just constants. A worth while exercise is to eliminate as many
  1456.    of  these  as possible. Change the address reference into a constant (ie,
  1457.    change  "MOV  AX,OFFSET  L03E8H"  into  MOV  AX,OFFSET  1000") so you can
  1458.    eliminate the "L03E8H:" definition from the data segment table.
  1459.  
  1460.  
  1461.    4.4) Deciphering More Obscure Code
  1462.  
  1463.    In  the  good  old  days  when  memory was expensive and processors had a
  1464.    limited  address range, assembly programmers delighted in seeing how much
  1465.    they could squeeze into small spaces. This tendency has lessened somewhat
  1466.    with  the  newer processors and cheap memory but you will still find some
  1467.    real funny looking code.
  1468.  
  1469.    Consider  the  following which was found at the start of a disk input and
  1470.    output routine.
  1471.  
  1472.  
  1473.       1234:F9                  STC
  1474.       1235:73F8                JNC   L122FH
  1475.       1237:B80100              MOV   AX,1
  1476.       123A:7304                JNC   L4567H
  1477.       123B:7304                JC    L7654H
  1478.  
  1479.  
  1480.    Wait  a  minute,  you say. How can you have a set carry instruction (STC)
  1481.    immediately  followed  by  a  jump  on  no  carry  (JNC)?.  There must be
  1482.    something  wrong.  No  one  writes  code like that! Actually this code is
  1483.    correct.  Since  the  jump on no carry is never executed, the destination
  1484.    byte  is  always  skipped  if  the instructions are executed in the order
  1485.    shown.  However,  the programmer sometimes jumps directly to address 1236
  1486.    which  is  in  the  middle  of  the  jump  instruction. In this case, the
  1487.    displacement  is executed and this becomes a clear carry instruction (the
  1488.    F8  byte).  What  happens  is that the routine has two functions that are
  1489.    very similar (like keyboard input with and without echo) and the state of
  1490.    the  carry flag is used to determine which function is desired. A jump to
  1491.    address  1234  does  one  thing  and  a jump to 1236 does the other. Veryè   sneaky!
  1492.  
  1493.    Or how about this piece of code.
  1494.  
  1495.  
  1496.  page 28      Masterful Disassembler - Intel 8086  version 1.00      page 28
  1497.  
  1498.  
  1499.  
  1500.  
  1501.       1234:40                  INC   AX
  1502.       1235:40                  INC   AX
  1503.       1236:40                  INC   AX
  1504.       1237:40                  INC   AX
  1505.       1238:40                  INC   AX
  1506.       1239:E82B33              CALL  L4567H
  1507.  
  1508.  
  1509.    Surely  it doesn't make sense to have that many increment instructions in
  1510.    a  row.  Or  does it? Actually this is part of an error handling routine.
  1511.    The  idea  is  to  load the AX register with an error number and call the
  1512.    routine  at  4567  to  print  out a message based on the error number. To
  1513.    display error number 1, then the programmers writes the code
  1514.  
  1515.  
  1516.       2345:31C0                XOR   AX,AX
  1517.       2347:E8EEEE              CALL  L1238H
  1518.  
  1519.  
  1520.    To  display  error  message  number 4, then the call goes to address 1235
  1521.    instead. For this particular procedure, the AX register always contains a
  1522.    zero  (it  is used as an error flag) and so the XOR AX,AX instruction can
  1523.    be  eliminated.  Then this requires only a three byte call instruction to
  1524.    flag  an  error  condition  (instead  of  the  usual  five  bytes).  Some
  1525.    programmers go to great lengths to save a few bytes of code!
  1526.  
  1527.  
  1528.  5.0) Examples
  1529.  
  1530.  A   couple   of  example  disassembly  files  have  been  included  on  the
  1531.  distribution  disk.  These  give  you an idea of how a typical (if there is
  1532.  such a thing) disassembly proceeds.
  1533.  
  1534.  The  first  example  is  the complete disassembly of a disk file comparison
  1535.  utility  program  called  CMP.COM. This is a short (1/2k) program that took
  1536.  about an hour or so to disassemble. Using MD86 to examine the progress, you
  1537.  will  note  that  all  labels  have been given names that more or less make
  1538.  sense.  In  addition,  numerous comments have been entered. You can write a
  1539.  source file to the disk and try to assemble it or print it. If you use MASM
  1540.  to assemble this file, you will run into error 56 (No immediate mode) a few
  1541.  times. Refer to section 3.5 as to why this happens and how to correct it.
  1542.  
  1543.  The second example was included to show the results of a basic disassembly.
  1544.  Here  the program EXE2BIN.EXE has been disassembled but only the first step
  1545.  has been completed. Only the data areas have been separated. Note that this
  1546.  EXE  program  does  not  have  a separate data segment. When MD86 reaches a
  1547.  statement like "MOV DX,L0582H" it notes that offset 582 hex within the data
  1548.  segment  has  been  referenced.  Since  there isn't any data segment in theè file,  an equate statement is inserted when a source file is generated. But
  1549.  note  that  the  code internally sets the data segment address to be within
  1550.  the  code  segment. Thus the reference to DS:582 is really somewhere within
  1551.  
  1552.  
  1553.  page 29      Masterful Disassembler - Intel 8086  version 1.00      page 29
  1554.  
  1555.  
  1556.  the  code  segment.  MD86  does not know this and the corresponding address
  1557.  within  the  code segment does not appear to be referenced. This is all too
  1558.  typical of EXE programs. They are a real bear to disassemble.
  1559.  
  1560.  
  1561.  6.0) MD86 Limitations
  1562.  
  1563.  MD86 is designed to provide as much functionality as is reasonably possible
  1564.  without  requiring  any  special  equipment.  There  are  some restrictions
  1565.  imposed on the user although the disassembly of a normal file should not be
  1566.  hampered. These are:
  1567.  
  1568.  
  1569.    o 2048 Address References.
  1570.  
  1571.    o 512 Entries in the Data Type Tables.
  1572.  
  1573.    o 2048 Comment Strings.
  1574.  
  1575.    o 64k Maximum Data Segment Size.
  1576.  
  1577.    o 64k Maximum Code Segment Size.
  1578.  
  1579.  
  1580.  These  parameters  have  been  chosen  such that a program up to 30k can be
  1581.  disassembled  as a single file. A 30k program would result in a 15,000 line
  1582.  assembly  file.  When  disassembling a larger file, it should be broken up.
  1583.  This  can  be  very  difficult  for  EXE  type programs. Even if MD86 could
  1584.  process  larger  files,  MASM  has its own restrictions which would require
  1585.  smaller sections.
  1586.  
  1587.  
  1588.  7.0) MD86 Error Messages
  1589.  
  1590.  During  the  process  of initializing its internal tables, MD86 may display
  1591.  one  of  a  few error messages. At other times, MD86 just beeps to indicate
  1592.  that  some  process  could  not be completed properly. After the beep, MD86
  1593.  just waits for a "correct" response or the error to be corrected.
  1594.  
  1595.  The error messages that may appear are:
  1596.  
  1597.  
  1598.    o Help, file filename does not exist.
  1599.  
  1600.      MD86  tried  to locate the file with the name "filename" and it did not
  1601.      exist.  You are requested to enter another filename. A leading path may
  1602.      be included if the file is under another directory or on another drive.
  1603.  
  1604.  
  1605.    o Help, error reading the auto comment file. Cannot continue.è
  1606.      While  reading  the  file  MD86.CMT  (which  did exist), MSDOS or TURBO
  1607.      Pascal  returned an error code. Try again. If this error persists, then
  1608.  
  1609.  
  1610.  page 30      Masterful Disassembler - Intel 8086  version 1.00      page 30
  1611.  
  1612.  
  1613.      re-copy  this  file from the master distribution disk. If this does not
  1614.      help,  then  send  a  copy  of MD86.CMT and MD86.COM to CC Software for
  1615.      analysis. You will be contacted with the solution as soon as possible.
  1616.  
  1617.  
  1618.    o Help,  auto  comment  file  MD86.CMT  cannot  be  found  on the current
  1619.      directory.
  1620.      Automatic comment generation is disabled.
  1621.  
  1622.      The  file MD86.CMT, which contains the automatic comment strings, could
  1623.      not  be located. MD86 looks only at the current drive and directory. It
  1624.      does  not  use  the PATH variable. Under most circumstances, you should
  1625.      quit (F10) without saving the data. Then copy this file from the master
  1626.      distribution  disk  over  to the correct directory. Re-execute MD86 and
  1627.      this error message should not appear.
  1628.  
  1629.      In  the  event  that  you do not need these comments, you may continue.
  1630.      MD86 will just ignore attempts to insert the comment strings.
  1631.  
  1632.  
  1633.    o Help, data file filename.001 does not exist!
  1634.      Help, Data file filename.002 does not exist!
  1635.  
  1636.      One  or  both  of  the  required data files could not be found. Both of
  1637.      these  files  are  used  by  MD86  for  label and comment storage. When
  1638.      disassembling  file  "filename",  MD86 creates files "filename.001" and
  1639.      "filename.002"  to  store  related  parameters. These files are created
  1640.      under  the  same  directory  as  "filename.com"  or  "filename.exe" was
  1641.      located. More than likely you are trying to disassemble another copy of
  1642.      this  program  under a different directory. Another possibility is that
  1643.      the  filename  was  not  in  a correct form (ie C>MD86 MYFILE..COM). If
  1644.      neither of these situations are the cause, then contact CC Software for
  1645.      additional help.
  1646.  
  1647.  
  1648.    o Help, one or more data files cannot be read properly.
  1649.  
  1650.      One  of the data files (either filename.001 or filename.002) was not in
  1651.      the  correct form for MD86 to read. This can occur when an I/O error or
  1652.      Run-time  error  aborts  the  writing of these files. Also one of these
  1653.      files  could just have a bad block. If there has not been a lot of work
  1654.      already  invested in these files, the safest procedure is to erase them
  1655.      and  start  over. Or use DEBUG to read these files into memory to check
  1656.      that they are at least readable. If they are, then send copies of these
  1657.      files to CC Software for analysis.
  1658.  
  1659.  
  1660.    7.1) Error Beep While Editing a Field
  1661.  
  1662.    If  you hear a beep while you are editing a field MD86 is saying that theè   last  command  could  not  be completed or it was an illegal command. The
  1663.    status  line  at  the  bottom  of  the display will show either INSERT or
  1664.    REPLACE  if  you  are  editing.  The following are the sources of editing
  1665.  
  1666.  
  1667.  page 31      Masterful Disassembler - Intel 8086  version 1.00      page 31
  1668.  
  1669.  
  1670.    errors.
  1671.  
  1672.  
  1673.      o Trying  to  move  the cursor beyond the edges of the field. Left and
  1674.        right arrow keys.
  1675.  
  1676.      o Entering  a  non-editing  command  (a  function key or an up or down
  1677.        arrow).
  1678.  
  1679.      o Trying  to  update  a  field  that  contains an illegal character. In
  1680.        particular,  labels  are  restricted  to a leading alphabetic key and
  1681.        imbedded spaces are not allowed.
  1682.  
  1683.  
  1684.    If  you  are  editing,  the  ESCAPE  key can always be used to cancel and
  1685.    restore  the  field to its original content. Often times a key is pressed
  1686.    by  mistake  which  causes edit mode to be entered but is itself illegal.
  1687.    For  example,  pressing  the  backspace key (<X) at the first column of a
  1688.    field. MD86 enters edit mode but rejects the key because there is nothing
  1689.    to  delete.  However,  MD86 remains in edit mode. Press the ESCAPE key to
  1690.    cancel.
  1691.  
  1692.  
  1693.    7.2) Error Beep While Not Editing a Field
  1694.  
  1695.    If  the  last  line  of the displays contains "No Edit", then you are not
  1696.    editing  a  field.  In  this  case  MD86 beeps when an illegal command is
  1697.    entered.  This could be an unbound function key, one of the key pad keys,
  1698.    or the ESCAPE key. MD86 ignores these keys. No harm is done.
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  References
  1705.  
  1706.  1) "MS-DOS  Developer's Guide", John Angermeyer and Kevin Jaeger, Howard W.
  1707.     Sams & Co, 1986
  1708.  
  1709.  2) "Peter Norton's Assembly Language Book for the IBM PC", Peter Norton and
  1710.     John Socha, Prentice Hall Press, 1986
  1711.  
  1712.  
  1713.  page 32      Masterful Disassembler - Intel 8086  version 1.00      page 32
  1714.  
  1715.  
  1716.                    C O M M A N D   K E Y   S U M M A R Y
  1717.  
  1718.     Key     Mode                  Description
  1719.  ---------- ---- -----------------------------------------------------------
  1720.  Left-Arrow   3  Move left one space.
  1721.  Right-Arrow  3  Move right one space.
  1722.  Up-Arrow     2  Move up one line.
  1723.  Down-Arrow   2  Move down one line.
  1724.  Page-Up      2  Move up about one page.
  1725.  Page-Down    2  Move down one page.
  1726.  Home         1  Move to beginning of field.
  1727.  Home         2  Move to beginning of label field.
  1728.  End          1  Move to end of field.
  1729.  End          2  Move to beginning of comment field.
  1730.  
  1731.  Insert       3  Switch between insert and replace modes for editing.
  1732.  Delete       1  Delete character under the cursor.
  1733.  Backspace    1  Delete the character to the left of the cursor.
  1734.  Escape       1  Cancel editing changes and return cursor to start of field.
  1735.  Return/Enter 1  Make editing changes permanent.
  1736.  Return/Enter 2  Move down one line (same as Down-Arrow).
  1737.  
  1738.  F1           2  Display a one page help summary.
  1739.  Shift-F1     2  Alter system parameters.
  1740.  F2           2  Goto a specified address or return from previous Goto.
  1741.  Shift-F2     2  Follow current instruction (jump or call only).
  1742.  F3           2  Set data type for given address range.
  1743.  F4           2  Set data type for unspecified address range.
  1744.  F5           2  Write source file to disk.
  1745.  F6           2  Scan code segment to build label table.
  1746.  F7           2  Dump program in hex and ascii.
  1747.  F8           2  Set label name for specified address.
  1748.  F9           2  Search for an address reference.
  1749.  Shift-F9     2  Search for next reference.
  1750.  F10          2  Save and/or exit.
  1751.  
  1752.  
  1753.  
  1754.      Modes: 1= Editing, 2=Non-editing, 3=Either editing or non-editing.
  1755.