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