home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / ASSEMBLY / DIS86212.ZIP / DIS86.DOC next >
Encoding:
Text File  |  1989-10-28  |  41.8 KB  |  1,125 lines

  1.  
  2.                     dis86 - Interactive 8086 Disassembler
  3.  
  4.   (C) COPYRIGHT 1985 - 88 by James R. Van Zandt,  ALL RIGHTS RESERVED
  5.  
  6.  
  7.  
  8.  
  9. You are encouraged to copy and distribute this program freely, provided:
  10.  
  11.     1)    No fee is charged beyond the actual cost for such copying and
  12.         distribution.
  13.  
  14.     2)    It is distributed ONLY in its original, unmodified state
  15.         (including documentation).
  16.  
  17. If you like this program, and find it of use, then your contribution of
  18. $25 will be appreciated.  For installation on a network file server
  19. with any number of users, a contribution of $125 is requested.  A
  20. current version program disk is available for $50.  Send contributions
  21. to:
  22.  
  23.             James R. Van Zandt
  24.             27 Spencer Dr.
  25.             Nashua NH 03062
  26.             603-888-2272
  27.  
  28. If you find bugs (byte sequences which are incorrectly disassembled),
  29. please let me know.  I am also willing to listen to suggestions for
  30. improvements.  I can be reached at the above address or via e-mail
  31. as follows...
  32.  
  33.     MILNET:          jrv@mbunix.mitre.org
  34.     CompuServe:      internet:jrv@mbunix.mitre.org
  35.     
  36. Please indicate which version you have and where you downloaded it.
  37.  
  38. SYNOPSIS
  39.  
  40. Dis86 is a full-screen, interactive disassembler of object code for
  41. the 8086, 8087, 8088, 80186, 80286, and 80386 (products of Intel), and 
  42. the V20 and V30 (products of NEC).  The 80386 disassemblies include 32 
  43. bit operands and addresses.  Dis86 implements the concept of a "current 
  44. location" and allows use of the cursor keys to change it.  Code can come 
  45. from a .EXE file (in which case the file header is properly
  46. interpreted), any other file (assumed to have no header), or anywhere
  47. in main memory (0000:0000 - F000:FFFF).  It can also read and write
  48. using absolute disk addresses (in which case the disk organization is
  49. shown).  Dis86 can install changes, even in a .EXE file, making it a
  50. convenient way to install patches.  The program runs on the IBM PC (and
  51. clones) and the Zenith Z-100.
  52.  
  53.  
  54. REVISION HISTORY
  55.  
  56. 1.00   First publically released version.
  57. 1.10   Implemented s-i-b byte for 80386 code (previously omitted due to
  58.        oversight).
  59. 1.11   Reversed bx+disp and bp+disp codes.
  60. 1.12   Installed F format.
  61. 1.13   Fixed several small disassembly errors, installed V command.
  62.        Reversed bx+disp and bp+disp codes again...NOTE: description in
  63.        preliminary 80386 manual is WRONG.
  64. 1.14   Follows interrupts if disassembling from memory.
  65. 1.15   Minor style changes, V command copies its expression to reply line.
  66. 1.20   Absolute disk address mode installed.
  67. 1.21   Eliminating trailing blanks in printout.
  68. 1.22   Following FAT entries.
  69. 1.23   Foreground and background colors may be set in IBM version.
  70. 1.24   Cloning - can write optional parameters into object code.
  71. 1.25   Foreground and background colors work in Z-100 version.  ESC and ^C 
  72.        abort commands that request keyboard input.  Correctly shows
  73.        last cluster on disk.
  74. 1.26   Segment register menu pops up in corner rather than clearing
  75.        entire screen.  Beeps eliminated.
  76. 1.27   12-bit FAT entries can be entered as well as displayed.
  77. 1.28   The file header pops up in the bottom half of the screen.
  78. 1.29   pg up and pg dn page through the help display pages.
  79. 1.30   gets pathname from system if run under DOS 3.xx
  80. 1.31   Follows short calls either forward or backward.
  81. 1.32   hardware screen I/O on IBM - much faster
  82. 1.33   Using sensing I/O library: works on either IBM or Z-100.
  83. 1.34   Fixed disassembly of instructions with both immediate data and offsets.
  84.  
  85. 2.00   Symbol table, Lotus-style menubar, immediate screen format change, 
  86.        accepts start address on command line.
  87. 2.02   Revised 32-bit MOD/RM and s-i-b byte decoding (Intel's "Advance 
  88.        Information" was wrong).  Searches continue to end of file.
  89. 2.03   Fixed reference searches to work with jumps or calls
  90.        that wrap around to the beginning of the segment.
  91. 2.10   Fixed mov instructions involving CR, DR, and TR.
  92.        Printing always stops at the end of the code buffer.
  93. 2.11   Fixed op codes for mov instructions involving CR 
  94.        (another error in the "Advance Information")
  95. 2.12   Fixed file writing (switched from fopen/fseek/fwrite to
  96.        open/lseek/write due to new C library).
  97.  
  98.  
  99. SUMMARY OF CHANGES FROM VERSIONS BEFORE 2.00
  100.  
  101. Aside from added features, present users will note two significant
  102. changes in the user interface.
  103.  
  104. The S command now starts a search.  The segment register is chosen by
  105. selecting the corresponding item in the R menu.
  106.  
  107. Before version 2.00, the screen format commands (Ascii, Byte, Code,
  108. Data, Font, clUster) optionally accepted addresses.  It was necessary
  109. to follow them with a carriage return to indicate the absence of an
  110. address.  I found that I rarely needed to enter an address, and the
  111. extra keypress was annoying.  Now, screen format commands take effect
  112. immediately.  Moving to a new disassembly address requires a separate
  113. Go command.  If you prefer the option to change the format and address
  114. in a single command, you may indicate this in the Option menu.
  115.  
  116.  
  117. STARTING THE DISASSEMBLER
  118.  
  119. To disassemble a file, give the file name (optionally preceded by a path 
  120. name) on the command line:
  121.  
  122.         A>dis86 foo.exe
  123.  
  124. To disassemble from RAM, use an empty command line:
  125.  
  126.         A>dis86
  127.  
  128. To disassemble using absolute disk addresses, specify only the disk on
  129. the command line:
  130.  
  131.         A>dis86 b:
  132.  
  133. You can also indicate the screen format and starting address on the
  134. command line.  To disassemble from memory starting at ffff:0 (the boot
  135. address), type:
  136.  
  137.         A>dis86  -c ffff:0
  138.  
  139. You can use on the command line any of the expression operators that
  140. would be legal within the program.  For example, to examine the start
  141. of the stack segment, you could type:
  142.  
  143.         A>dis86  dis86.exe  -b ss:0
  144.  
  145. DISPLAY SCREEN
  146.  
  147. During disassembly, the screen will resemble the following:
  148.  
  149.         0000:0100      e9 01 90            jmp            9104
  150.         0000:0103      55                  push           bp       
  151.         0000:0104      8b ec               mov            bp,sp    
  152.         0000:0106      83 ec 0e            sub            sp,0e    
  153.         
  154.                                   ...
  155.         
  156.         0000:012C      50                  push           ax         
  157.         0000:012D      b8 69 00            mov            ax,0069    
  158.         0000:0130      50                  push           ax         
  159.         0000:0131      e8 e9 5c            call           5e1d       
  160.         dis86 1.00 - A SHAREWARE software product  (c) 1986, James R. Van Zandt
  161.         >
  162.         ... 0000:0100  0000:0100  0000:0100  
  163.  
  164. Lines 1 through 21 are the disassembled code.  Each line starts with
  165. the current address, followed by the actual bytes being disassembled. 
  166. The rest of the line is the assembly language equivalent, if any, of
  167. the code.  The display for A (ASCII), B (byte), D (data), F (font), and
  168. U (File Allocation Table) formats is similar.  All numbers are shown in
  169. hexadecimal.  
  170.  
  171. Line 22 is a message and prompt line showing, for example, the
  172. arguments needed for some commands.  Line 23 has the prompt.  Typed
  173. characters are echoed here.  Line 24 displays three addresses, which
  174. are the top three entries in the stack (see the 'cursor right' and
  175. 'cursor left' commands below).
  176.  
  177.  
  178. CURSOR KEYS
  179.  
  180. The "current location" is the address displayed on the first line
  181. of disassembly.  The cursor keys are used to adjust the current 
  182. location.
  183.  
  184. The up and down cursor keys (8 and 2 on the numeric pad) are used to
  185. move the current location a small amount.  <up> moves by one line
  186. except in C (code) format, when it moves up by one byte. (Note that <up>
  187. and <down> are not inverses in this case.):
  188.  
  189.         <up>     moves up by one line or byte (lower address)
  190.         <down>   moves down by one line (higher address)
  191.  
  192.  
  193. The <pg up> and <pg dn> keys (9 and 3 on the numeric pad) move the
  194. current location by larger amounts.  In C (code) format, they move by
  195. 32 bytes.  In the other formats, they move by 11 lines on the screen. 
  196. They will not move the cursor out of the disassembly buffer. 
  197. Otherwise, they are inverses.:
  198.  
  199.         <pg up>   moves up by 32 bytes (lower address)
  200.         <pg dn>   moves down by 32 bytes (higher address)
  201.  
  202.  
  203. The above keys change only the current location.  Other commands change 
  204. the current location by potentially large amounts, but first save it in 
  205. a stack.  The top three addresses in the stack are shown in the command
  206. area at the bottom of the screen.
  207.  
  208. If the instruction at the current location is a jump, call, or a
  209. reference to a data location, the cursor right key (6 on the numeric
  210. pad) will push the current location on the stack and go to the
  211. referenced location.  If the disassembly is from memory, interrupts can
  212. also be followed.  For a data reference, the disassembly format is
  213. changed to D (hex and ASCII).  If disassembly is from disk using
  214. absolute disk references and the disassembly format is U (display File
  215. Allocation Table, or FAT), then the next FAT entry is followed.
  216.  
  217.         <right>   follows a jump, call, interrupt, 
  218.                   data reference, or FAT entry
  219.  
  220. If disassembling a FAT, the next entry is followed, staying within the
  221. same FAT.  If disassembling from an address above the last FAT, the
  222. disassembler assumes a directory entry is being displayed, finds the
  223. next FAT reference (displacement 1A from the beginning of the current
  224. directory entry, which begins on a 32 byte boundary), and follows it
  225. into the first FAT.  Note that the disassembly format must be U before
  226. the disassembler will attempt to follow a FAT entry.  The natural
  227. format for displaying a directory entry would be D or A.  The
  228. appropriate command sequence would then be U <right>.
  229.  
  230. The cursor left or left arrow key (4 on the numeric pad) will pop the
  231. last address off the stack.  Note that right arrow followed by left
  232. arrow will return you to the same address, whereas left arrow
  233. (returning, let us say, to address X) followed by right arrow will only
  234. return you to the same address if there is an appropriate jump, call,
  235. or data reference at X.
  236.  
  237.         <left>    pops address stack
  238.  
  239. After using the right arrow or the G command (in the next section) to
  240. go to a new address, then using the left arrow key to pop the stack,
  241. you will sometimes want to return to the previous address.  The stack
  242. no longer holds the address.  However, the left arrow key saves the
  243. current location in a special "previous state" before popping the
  244. stack.
  245.  
  246. To return to the address stored in the "previous state", type shift
  247. right arrow on a Z-100, or control right arrow on an IBM PC.
  248.  
  249.         <ctrl><right>    returns to "previous state"   (IBM)
  250.         <shift><right>   returns to "previous state"   (Z-100)
  251.  
  252.  
  253. In summary, the unshifted keys on the numeric pad are:
  254.  
  255. <home> top of file          ^   up 1 line         <pg up>  up 32 bytes 
  256.                             |         
  257.  
  258. <--    pop addr stack                             -->      follow jump/call
  259.  
  260.                             |         
  261. <end>  end of file          v  down 1 line        <pg dn>  down 32 bytes  
  262.  
  263.  
  264. <ins>  setup options 
  265.  
  266. On the Z-100, the four keys with arrows on them may be used in addition
  267. to the 2, 4, 6, and 8 on the numeric pad.
  268.  
  269.  
  270. MOVING THE CURSOR
  271.  
  272. The command for moving the cursor to a specific address is
  273.  
  274.     G <expression> <ret>
  275.  
  276. The 'S' command starts a search.  It may be followed by three kinds of
  277. search patterns:
  278.  
  279.     S <expression> <expression> <expression> <ret>
  280.             The disassembler searches starting at the
  281.             current address for the specified sequence of
  282.             hex bytes.  If an expression has a segment
  283.             specified using the ':' operator (below), the
  284.             segment is ignored.
  285.  
  286.     S T [string] <ret>
  287.             The disassembler searches from the current
  288.             address for the specified ASCII string.  Cases
  289.             are not distinct, and the high order bit is
  290.             ignored.  The string can also be introduced by
  291.             a double quote.
  292.  
  293.     S R <expression> <ret>
  294.             The disassembler searches from the current
  295.             address for a reference (load, store, jump or
  296.             call) to the specified address.
  297.  
  298. Searches will continue to the end of the file, disk, or system memory. 
  299. Most searches should take a few seconds or less.  Long searches, such
  300. as those on the disk, can be interrupted with control-C.
  301.  
  302. An <expression> can involve any of these items:
  303.  
  304.     hex numbers    (either upper or lower case letters)
  305.     cs, ds, es, ss, fs, gs
  306.             currently assumed segment register values
  307.     $        current location
  308.     @        offset of top address on the stack
  309.     'x'        single characters
  310.     "jkl;"        multiple character strings
  311.     main            predefined symbols
  312.  
  313. ...and any of these operators:
  314.  
  315.     + - * /        add, subtract, multiply, divide
  316.     :        separate segment and offset
  317.  
  318. Note that G with no address is a noop.  
  319.  
  320. There are two ways to ask for a text string search.  For example,
  321.  
  322.     S T jones
  323.  
  324.     S "Jones"
  325.  
  326. In the first search, cases are not distinct and the high order bit
  327. is ignored.  In the second search, the high order bit must be 0 and
  328. the cases must match.  The second form can be intermixed with other
  329. expressions:
  330.  
  331.     S "Jones" 0d 0a 00
  332.  
  333. The reference search looks for three kinds of instructions:  far
  334. jumps and calls, short jumps and calls, and moves to or from the
  335. accumulator (al, ax, or eax).  
  336.  
  337. Jumps and calls having two byte displacements may be misinterpreted if
  338. the assumed code segment register value is incorrect.  In these
  339. instructions, the displacement is relative to the address of the
  340. following instruction, so it is relocatable (i.e., the entire program
  341. is still correct if it is moved to a new location).  However, the
  342. destination must be in the same 64K code segment.  If a jump has a
  343. displacement which is larger than the address difference from the jump
  344. to the end of the segment then the destination wraps around to the
  345. beginning of the segment.  If the assumed value of the code segment
  346. register is incorrect, this wrap around point may be incorrect so that
  347. the destination is incorrect by 64K (10000 hex).
  348.  
  349. Similarly, moves between the accumulator and memory may be
  350. misinterpreted if the assumed value of the data segment register is
  351. incorrect.
  352.  
  353.  
  354. CHANGING DISPLAY FORMAT
  355.  
  356. There are six letter commands to change the display format:
  357.  
  358.     A    ASCII data
  359.     B    byte data (hex)
  360.     D    data (both hex bytes and ASCII)
  361.     C    code
  362.     F    font
  363.     U    File Allocation Table entry
  364.  
  365. These commands, as with all letter commands, may be in upper or lower
  366. case.  In previous versions of the disassembler, these commands also
  367. accepted addresses.  In order to change display format without changing
  368. the address, it was necessary to add <ret>.  In this version, the
  369. format change takes place immediately.  If you prefer the previous
  370. method, you may select that option on the first option menu.
  371.  
  372. The number of bytes per line in A, B, or D formats can be changed using
  373. the W command or the width entry in the second option menu (see below).
  374.  
  375. In F format, one byte is shown per line, and each bit in that byte is
  376. represented by an astrisk.  This is suitable for displaying fonts for
  377. video displays, which are uniformly 8 bits wide.
  378.  
  379. In U (clUster number) format, bytes are displayed as File Allocation
  380. Table, or FAT entries.  This format is ordinarily useful only when
  381. disassembling using absolute disk addresses.  In that case, the
  382. disassembler will have determined how many clusters there are on the
  383. disk.  If there are fewer than 4097, then 12 bit FAT entries are
  384. assumed.  If there are 4097 or more, then 16 bit FAT entries are
  385. assumed.  Each pair of 12 bit FAT entries occupies three bytes.  If the
  386. cursor is set on the third byte of a pair of 12 bit entries, or the
  387. second byte of a 16 bit entry, the disassembler displays some dashes to
  388. signal that it is skipping that byte.  Otherwise, it starts by
  389. displaying the FAT entry that begins with that byte.
  390.  
  391. There are many explanations of how File Allocation Tables work.  One
  392. good one is in Ray Duncan's book "Advanced MSDOS" (Microsoft Press,
  393. 1986).
  394.  
  395. MISCELLANEOUS COMMANDS
  396.  
  397. The 'E' command allows the user to modify the program being
  398. disassembled.  Changes are initially made only in the disassembly
  399. buffer.  Before the buffer is overwritten or the disassembler
  400. terminates, the user is asked whether the changes are to be written to
  401. the file or RAM area being disassembled.  The values entered may be
  402. given in hex expressions or ASCII.  Values too large to fit into a byte
  403. are assumed to be words or double words.  Here are some examples:
  404.  
  405.     45 67 'A'            =>  45 67 41
  406.  
  407.     2ea+3                =>  ed 02
  408.  
  409.     9c/3                 =>  34
  410.  
  411.     "Alpha Beta" 0d 0a   =>  41 6c 70 68 61 20 42 65 74 61 0d 0a
  412.  
  413.  
  414. The 'P' command is used to print a disassembly listing to a file.  The
  415. first time this command is used, it prompts for a file name.  The
  416. default file name is "printout".  To actually send the listing to a
  417. printer, specify the filename "prn".  If the file already exists the
  418. new information will be appended.  The file is automatically closed
  419. before the disassembler exits.  The command also prompts for the
  420. beginning and end addresses of the code to be printed.  The default
  421. addresses print the current screen.  When the printing is finished, the
  422. current address is advanced to the first byte not printed.  Thus, you
  423. can repeat the sequence
  424.  
  425.         P <ret> <ret>
  426.  
  427. to print a large section.
  428.  
  429. The 'V' command requests an expression and displays its value.
  430.  
  431. The 'W' command is used to set the number of bytes displayed on each
  432. line for the A, B, and D formats.  This is useful for displaying
  433. tables.  For example, when dis86 is executed without a file, it
  434. displays bytes starting at address 0000:0000 and the width is set to
  435. four so each interrupt vector is shown on a separate line.
  436.  
  437.  
  438. MENUBAR COMMANDS
  439.  
  440. Entering '/' or <space> brings up the main menubar, which has six
  441. choices.  One choice is highlighted.  An explanation for that choice,
  442. or a preview of a lower level menu, appears on the next line.  The left
  443. and right cursor keys will move the highlight.  You may execute the
  444. highlighted choice by typing <ret> or <down>, or any choice by typing
  445. its first letter.  You may leave a menubar without making a choice by
  446. typing <esc> or <up>.
  447.  
  448. At first, you will probably use the cursor keys and read the
  449. explanations for confirmation.  As you get more familiar with the
  450. commands, you will start typing sequences automatically.  For example,
  451. the sequence /FQ will exit the disassembler.
  452.  
  453. Here is the whole hierarchy of menubar commands:
  454.  
  455.         File
  456.            Clone     /FC   write current parameters into object file
  457.            Save      /FS   save symbol table to file
  458.            Load      /FL   load symbol table from file
  459.            Quit      /FQ   quit to DOS
  460.         Header       /H    display file header or disk parameters
  461.         Options      /O    change setup options
  462.         Colors
  463.            Normal    /CN   display colors for normal text
  464.            Highlight /CH   display colors for highlighted text
  465.            Windows   /CW   display colors for text in windows
  466.         Registers    /R    reset/select segment registers
  467.         Symbols            symbolic labels for addresses
  468.            Insert    /SI   insert new symbols
  469.            Delete    /SD   delete existing symbols
  470.            Edit      /SE   change names and/or addresses of symbols
  471.            List      /SL   list the symbols in the symbol table
  472.         ?            /?    display help screens
  473.  
  474. In this version, the Header, Options, Registers, and ? commands can
  475. also be executed as single letter immediate commands.
  476.  
  477. The Clone command is used to write the current values of these
  478. parameters into the disassembler object code:
  479.  
  480.         wild card byte in search pattern
  481.         data bytes per line for A, B, and D formats
  482.         processor code
  483.         bit mode (for 80386 code)
  484.         display colors 
  485.         immediate/delayed display format changes
  486.  
  487. This will make the current parameter values the default values for
  488. subsequent executions.  (One exception: when disassembling from memory,
  489. the bytes per line is always set to four so that the interrupt vectors
  490. in low memory are displayed one per line.) This command prompts for the
  491. name of the object code file, which should include the drive and
  492. directory unless the file is in the current directory or somewhere in
  493. the path.  Under DOS 3.0 or later, the disassembler determines its own
  494. path name and offers it as the default.
  495.  
  496. The Quit subcommand returns control to DOS.  If a change has been made to
  497. the disassembler buffer, the user is asked whether to write out the
  498. changes.
  499.  
  500. The Header command displays the .EXE file header information, or the
  501. organization of the disk in absolute disk address mode.  This
  502. information is also displayed on the initial program screen.
  503.  
  504. The Options command or <ins> (0 on the numeric pad) bring up menus for
  505. changing setup options and allow the user to reset the disassembly
  506. window.  Use <space> or <ins> to move to the next screen, or <esc> to
  507. return to disassembly.  To save options for the next disassembly, use
  508. the clone command (above).
  509.  
  510. In the first options menu, use the right and left cursor keys or <ret>
  511. to change the entries.  The first item shows the processor which is
  512. supposed to execute the code being disassembled.  There is some
  513. conflict in op codes between the V20 and V30 on one hand and the 80286
  514. and 80386 on the other.  That is, the two families use the same op
  515. codes for different instructions.  The processor you indicate on this
  516. menu will determine which instruction Dis86 shows.  In addition, it
  517. will flag instructions not implemented by the indicated chip.
  518.  
  519. The next item lets the user specify 16 or 32 bit mode for the 80386. 
  520. In the 16 bit mode the 80386 is similar to the 8086.  In the 32 bit
  521. mode arithmetic is performed in 32 bit registers and all address
  522. offsets are 32 bits.  The 80386 itself selects the mode based on a bit
  523. in the segment table entry for the code segment.  The program may also
  524. include prefix bytes which change the assumed operand size or address
  525. size for one instruction (66H and 67H respectively).  The disassembler
  526. recognizes these prefixes.
  527.  
  528. The last item indicates whether display format changes take effect
  529. immediately, or allow the user to enter an address as well.
  530.  
  531. In the second options menu, change an entry by typing over it.  The
  532. first item is the byte value which matches anything in a byte or
  533. character search (the "wild card" byte).  The second is the number of
  534. bytes displayed on each line for the A, B, or D formats.  The latter
  535. value can also be set using the W command.  The last item is the
  536. assumed load address (see below).
  537.  
  538. By using the <ins> key to enter the options menu and to step from one
  539. menu to the next, you can leave your right hand on the numeric pad.
  540.  
  541. The Colors command sets the display colors for three classes of text:
  542. normal text, highlighted text (used in the menubar itself), and text in
  543. the Options, Registers, or Header windows.  Foreground and background
  544. colors can be set independently.
  545.  
  546. The Registers command is used to display and/or change the assumed
  547. segment register values.  Entries may be full expressions.  For
  548. example, to copy the value from SS into DS, enter
  549.  
  550.         /R
  551.         
  552. use the cursor keys to select the DS register and type
  553.  
  554.         ss <ret> <esc>
  555.  
  556. This menu also selects the current segment register: The segment
  557. register indicated by the cursor when you type <esc> will be used to
  558. calculate the displayed addresses.
  559.  
  560. The Symbol command allows you to enter symbolic names for addresses. 
  561. These names will be used in place of the numeric values both in the
  562. address column along the left side of the display and to indicate the
  563. destinations of jumps or calls.  Symbols are also displayed for some
  564. data references.  Unfortunately, many data references use index
  565. registers, and symbols will not be shown for these.  
  566.  
  567. A symbol longer than 40 characters will be silently truncated.  A
  568. symbol must consist of alphanumeric characters, and must start with an
  569. alphabetic character.  An underscore is treated as alphabetic.  
  570.  
  571. You can use symbols within expressions.  For example, if "boot" is
  572. defined as "ffff:0000", you can type
  573.  
  574.     G boot <ret>
  575.  
  576. to move the cursor there.  
  577.  
  578. It is a good idea to included at least one character in each symbol
  579. that cannot occur in a hexadecimal number.  If a token can be
  580. interpreted as either a symbol or a number, its definition as a symbol
  581. will take precedence.  If you were to define "a" as "3", then the
  582. expression "a-1" would have the value "2".  To enter the hexadecimal
  583. number "a" you would have to type "0a" or an expression like "9+1".
  584.  
  585. Use the Save subcommand under the File command to save the symbol table
  586. to a disk file, and the Load subcommand to read it back during some
  587. future disassembly.  The symbol table file is straight ASCII and can
  588. be edited.  You may add comments: any line beginning with a semicolon
  589. ';' will be ignored by the disassembler.
  590.  
  591. Type '?' to get a series of help screens.  Type <esc> to return to the
  592. disassembly, <pg up> or <pg dn> to select a screen, or any other key to
  593. advance to the next screen
  594.  
  595.  
  596. TYPING REQUESTED DATA
  597.  
  598. Many commands supply default entries for requested data.  If you decide
  599. to accept the default, just enter <ret>.  For editing entries, you can
  600. position the cursor using the left and right cursor keys to move by one
  601. character, <home> (7 on the numeric pad) to move to the left end of the
  602. string, or <end> (1 on the numeric pad) to move to the right end.  Use
  603. the <del> or <backspace> keys to delete incorrect characters, or just
  604. type characters to be inserted.  Type <ins> to toggle between insert
  605. and replace modes.
  606.  
  607. In every case but one, you can also edit the default entry by making
  608. <right>, <end>, or <del> your first keystroke.  The exception is the
  609. default for the byte search function.
  610.  
  611. In edit mode, the five active unshifted keys on the numeric pad are:
  612.  
  613. <home> start of string
  614.  
  615.  
  616. <--    left one char                              -->      right one char
  617.  
  618.  
  619. <end>  end of string 
  620.  
  621.  
  622.  <ins> insert/delete
  623.  
  624.  
  625. In addition, the shifted cursor keys move by word.  On the IBM:
  626.  
  627.         <ctrl><right>    next word
  628.         <ctrl><left>     previous word
  629.  
  630. On the Z-100:
  631.  
  632.         <shift><right>   next word
  633.         <shift><left>    previous word
  634.  
  635.  
  636. DISASSEMBLY WINDOW
  637.  
  638. The disassembler uses a buffer to hold the code being disassembled. 
  639. For most purposes, this disassembly window is transparent to the user. 
  640. If the user requests an address within the file but outside the
  641. disassembly window, the appropriate code is automatically read in.  The
  642. existence of the window is apparent in only two cases: 
  643.  
  644.     1.    If the disassembler is started near the end of the window 
  645.         and reaches the end before it fills the screen, the
  646.         rest of the screen will be left blank.
  647.  
  648.     2.    If the contents of the buffer has been changed (see 'E'
  649.         command) the user is asked whether they should be
  650.         written out before the buffer is overwritten or control 
  651.         is returned to DOS.
  652.  
  653.  
  654. LOAD ADDRESS
  655.  
  656. Code from a .COM file is displayed as though its Program Segment Prefix
  657. were at 0000:0000 and its load address were 0000:0100.
  658.  
  659. Code from a .EXE file is displayed as though its load address were
  660. 0000:0000.  This puts its Program Segment Prefix is 10 paragraphs or
  661. 100 (hex) bytes lower.  This is somewhat awkward, because the DS and ES
  662. registers are initialized to point to the PSP.  The disassembler
  663. displays this segment value as -10.  The advantage of a load address of
  664. 0000:0000 is that no relocation is necessary.  The bytes displayed are
  665. exactly the same as those in the file.  This also means that the code
  666. can be modified (see below for the 'E' command) and written back to the
  667. file without being "unrelocated".
  668.  
  669.  
  670. SEGMENTATION
  671.  
  672. Addresses are displayed in segment:offset form, using the current
  673. assumed value of the current segment register.  The current segment
  674. register can be selected using the 'S' command to step among the
  675. available registers (CS, SS, DS, ES, FS, and GS - the last two only
  676. with 80386 code).  Changing segment registers or their values does not
  677. move the disassembler cursor.  Only the displayed segment and offset
  678. values will change to reflect the new assumptions.  An appropriate
  679. segment value (that is, between 0 and 65535 bytes before the address
  680. being disassembled) will result in a legal offset which will be
  681. displayed as a four digit hex number (0000 to FFFF).  An inappropriate
  682. segment value will result in an offset outside this range (negative, or
  683. greater than 64K).  Such offsets will be calculated and displayed,
  684. although they are illegal on the 8086.  Illegal offsets will have more
  685. than four digits.
  686.  
  687. The segment register values are initialized as indicated in the file 
  688. header (for .EXE files) or to zero (for other files or RAM).  The 
  689. disassembler has no way of determining the values which may be set 
  690. during execution.  For example, the initialization code for DeSmet C 
  691. programs reset DS to the same value as the initial SS before executing 
  692. main().
  693.  
  694. The assumed segment register values can be altered in two ways.  When
  695. the right arrow key is used to follow a far call or jump, the new code
  696. segment value is loaded into the CS register.  In addition, any segment
  697. register can be changed using the register menu reached by the 'R'
  698. command.  (The same menu is used to indicate which register should be
  699. used for the disassembly display: leave the cursor pointing to the
  700. desired register before leaving the menu with <space> or <esc>.) When
  701. the user specifies a new segment value on a G command, that value is
  702. used for subsequent displays but none of the assumed segment register
  703. values is changed.
  704.  
  705. The segmentation models of the protected modes of the 80286 and 80386 
  706. are not supported.
  707.  
  708.  
  709. ALIGNMENT
  710.  
  711. Dis86 will correctly disassemble code if started on the first byte of an 
  712. instruction.  If started in the middle of an instruction, it will 
  713. disassemble that instruction and perhaps several more incorrectly.  In 
  714. this case the disassembler is said to be out of alignment with the 
  715. object code.  The disassembler will tend to correct its alignment if it 
  716. continues long enough.  8086 instructions tend to be longer than, for 
  717. example, those for the 8080, so the disassembler will tend to stay out 
  718. of alignment for more bytes.  Generally speaking, the alignment will be 
  719. correct after the first half dozen lines.
  720.  
  721.  
  722. SUMMARY
  723.  
  724. Here are all the single letter commands:
  725.  
  726. A           ASCII data
  727. B           byte date (hex)
  728. C           code (disassembly)
  729. D           data (hex and ASCII)
  730. E           enter new data (follow with a series of hex expressions)
  731. F           font
  732.  
  733. G nnnn      goto address nnnn
  734. H           display file header information (for .EXE files only)
  735. O           change setup options
  736. P           print disassembly listing to file
  737.  
  738. R           change segment register values
  739. S           start a search
  740. U           display as FAT entries
  741. V           evaluate an expression
  742.  
  743. W           width: set bytes of data per line for A, B, and D formats
  744. X           exchange current address (at top of screen) with top of stack
  745. ?           display help screens
  746. /           display the main menubar
  747.  
  748.  
  749. EXAMPLE 1
  750.  
  751. In the examples, <left>, <right>, <up>, and <down> refer to the four
  752. cursor keys (4, 6, 8, and 2 on the numeric pad, plus the four arrow
  753. keys on the Z-100 keyboard).  <pg up> and <pg dn> refer to the 9 and 3
  754. on the numeric pad.
  755.  
  756. To investigate the bootstrap code, type
  757.  
  758.     A>dis86 <ret>
  759.  
  760. and press
  761.  
  762.     <space>
  763.  
  764. to advance to the disassembly display, which will be a D (data) format 
  765. display of the interrupt vectors.  Next type
  766.  
  767.     C G ffff:0000 <ret>
  768.  
  769. (for Code format at the Address ffff:0000).  On an IBM, the ROM release 
  770. date and machine ID appear in the last 16 bytes of the ROM.  To see
  771. them, type
  772.  
  773.     D
  774.  
  775. The release data is at addresses ffff:0005 - ffff:000c in ASCII.  The 
  776. machine ID is at ffff:000e.  Some of the possible values are:
  777.  
  778.     ff    IBM PC
  779.     fe    IBM XT and Portable IBM PC
  780.     fd    IBM PCjr
  781.     fc    IBM AT
  782.     2d    Compaq
  783.     9a    Compaq-Plus
  784.  
  785. Return to code format by typing
  786.  
  787.     C
  788.  
  789. One of the instructions displayed should be a jump.  If so, press
  790.  
  791.     <down>
  792.  
  793. enough times to bring the jump to the top line, then
  794.  
  795.     <right>
  796.  
  797. to follow the jump.  Note that the previous addresses were pushed onto 
  798. the stack, as shown on the bottom line.  To return to the most recent 
  799. address, press
  800.  
  801.     <left>
  802.  
  803. To leave the disassembler, press
  804.  
  805.     /FQ
  806.  
  807.  
  808. EXAMPLE 2
  809.  
  810. For a second example, let us disassemble the disassembler itself.  Begin 
  811. by typing
  812.  
  813.     A>dis86 dis86.exe <ret>
  814.  
  815. Note the header information, including the entry point of 0000:0000 and 
  816. the initial stack location of approximately 09e0:9eb8.  Proceed to the 
  817. disassembly screen by typing
  818.  
  819.     <space>
  820.  
  821. The disassembler starts in C (code) format at the entry point, which is 
  822. a jump to the initialization code.  To follow the jump, type
  823.  
  824.     <right>
  825.  
  826. One of the early instructions in the initialization code refers to the 
  827. first location in the stack segment.  Bring this location to the top of 
  828. the screen by typing
  829.  
  830.     <pg dn> <down> <down>
  831.  
  832. and follow the reference by typing
  833.  
  834.     <right>
  835.  
  836. Since it was a data reference, the disassembler automatically switched 
  837. to D (data) format.  Also, the addresses are displayed using the value 
  838. of segment register SS.  Note that the two previous addresses have been 
  839. pushed onto the stack, as shown at the bottom of the screen.  Return to 
  840. the initializing code by typing
  841.  
  842.     <left>
  843.  
  844. The initialization code gets rather involved, but one of its functions
  845. is to initialize DS to the same value as SS.  To reflect this, use the
  846. R command:
  847.  
  848.     R
  849.  
  850. DS is the first register in the list.  You need only move the cursor to
  851. that register and enter the appropriate value:
  852.  
  853.     ss <ret>
  854.  
  855. We will be disassembling code, so CS should be used to generate the
  856. displayed adresses.  To ensure this, leave the cursor pointing to CS
  857. before leaving the menu with
  858.  
  859.     <esc>
  860.  
  861. The code for the main program immediately followed the jump at 
  862. 0000:0000.  To return there, type
  863.  
  864.     <left>
  865.  
  866. Send a copy of this screen to the file "printout" by typing
  867.  
  868.     P <ret> <ret> <ret>
  869.  
  870. To inspect the data segment, type
  871.  
  872.     A G ds:0 <ret>
  873.  
  874. To display more characters on each line, use the W command:
  875.  
  876.     W 60 <ret>
  877.  
  878. Use the search command to find one of the messages:
  879.  
  880.     S T hime <ret>
  881.  
  882. This string won't be found.  To correct the spelling to "home" and try 
  883. again, type
  884.  
  885.     S T <right> o <ret>
  886.  
  887. Once again, leave the disassembler by pressing
  888.  
  889.     /FQ
  890.  
  891.  
  892. EXAMPLE 3
  893.  
  894. The third example will show how the disassembler can be used to
  895. undelete a disk file.  Begin by creating and deleting a short text file
  896. using redirection from the DOS prompt:
  897.  
  898.     A>type con >patriot.1
  899.     Now is the time for all good men to come to the aid of their country.<ret>
  900.     <ctrl-Z> <ret>
  901.  
  902.     A>copy patriot.1 patriot.2
  903.     A>erase patriot.1
  904.  
  905. Now, start the disassembler by typing
  906.  
  907.     A>dis86 a:
  908.  
  909. The disassembler first shows the disk header information, which for a
  910. 360 K floppy disk looks like this:
  911.  
  912.  
  913. Drive information for A:
  914.                FD media descriptor byte
  915.       200H =  512 bytes/sector
  916.       400H = 1024 bytes/cluster
  917.               354 clusters, or 362496 bytes, for disk files
  918. Sector    Offset (hex)    Length (sectors)
  919.     0           0                 1           BIOS parameters and boot code
  920.     1         200                 2           FAT 1
  921.     3         600                 2           FAT 2
  922.     5         a00                 7           root directory with 112 entries
  923.    12        1800                 2           cluster 2
  924.   718       59c00                 2           cluster 355 (last)
  925.  
  926.  
  927. Note in particular the byte offsets of 200 to the first FAT and a00 to
  928. the root directory, and the cluster size of 400.  Proceed to the first
  929. disassembly screen by typing
  930.  
  931.     <space>
  932.  
  933. The disassembler starts in D (data) mode at the first sector, which is
  934. the boot sector.  Now type
  935.  
  936.     D G a00
  937.  
  938. to show the disk directory and
  939.  
  940.     W 8
  941.  
  942. to set the display width to 8.  Each directory entry takes four
  943. lines:
  944.  
  945. 0000:0CA0      47 4c 49 20 20 20 20 20 |GLI     |
  946. 0000:0CA8      43 20 20 20 00 00 00 00 |C   ....|
  947. 0000:0CB0      00 00 00 00 00 00 65 79 |......ey|
  948. 0000:0CB8      5b 0f 6d 00 cd 2f 00 00 |[.m.M/..|
  949.  
  950. The fields in each entry are as follows:
  951.  
  952.                47 4c 49 20 20 20 20 20 |GLI     |
  953.      file name ^^^^^^^^^^^^^^^^^^^^^^^ 
  954.  
  955.                43 20 20 20 00 00 00 00 |C   ....|
  956.      extension ^^^^^^^^
  957.               attribute ^^
  958.                   reserved ^^^^^^^^^^^
  959.  
  960.                00 00 00 00 00 00 65 79 |......ey|
  961.       reserved ^^^^^^^^^^^^^^^^^
  962.                             time ^^^^^
  963.  
  964.                5b 0f 6d 00 cd 2f 00 00 |[.m.M/..|
  965.           date ^^^^^ 
  966.     starting cluster ^^^^^
  967.         file size in bytes ^^^^^^^^^^^
  968.  
  969. It's the file name and the last two fields we'll be concerned with.
  970. Search for the files we just created using a wild card as the first search
  971. byte:
  972.  
  973.     G S ff "ATRIOT" <ret>
  974.  
  975. Here, the text string must be typed in upper case.  The display should
  976. resemble this:
  977.  
  978.     0000:0B00      e5 41 54 52 49 4f 54 20 |eATRIOT |
  979.     0000:0B08      31 20 20 20 00 00 00 00 |1   ....|
  980.     0000:0B10      00 00 00 00 00 00 0d a4 |.......$|
  981.     0000:0B18      8c 0f a2 00 47 00 00 00 |..".G...|
  982.     0000:0B20      50 41 54 52 49 4f 54 20 |PATRIOT |
  983.     0000:0B28      32 20 20 20 00 00 00 00 |2   ....|
  984.     0000:0B30      00 00 00 00 00 00 0d a4 |.......$|
  985.     0000:0B38      8c 0f a3 00 47 00 00 00 |..#.G...|
  986.     0000:0B40      00 e5 e5 e5 e5 e5 e5 e5 |.eeeeeee|
  987.     0000:0B48      e5 e5 e5 e5 e5 e5 e5 e5 |eeeeeeee|
  988.     0000:0B50      e5 e5 e5 e5 e5 e5 e5 e5 |eeeeeeee|
  989.  
  990.  
  991. In deleting PATRIOT.1, the ONLY change DOS made to the directory entry
  992. was to replace the first byte of the file name by hex e5 (a lower case
  993. 'e' with the high order bit set).  Looking at the third and fourth
  994. bytes of the last line, we see that the file started at cluster a2. 
  995. From the next four bytes, we learn that the file had length 47 (hex)
  996. bytes.  This is less than the cluster size of 400, so the file had only
  997. one cluster.  Note that PATRIOT.2 has the same length, and starts at
  998. cluster a3.
  999.  
  1000. To examine the initial cluster of the file, type
  1001.  
  1002.     H
  1003.  
  1004. to display the header information.  Note that clusters have length 400
  1005. and that cluster 2 starts at offset 1800.  Switch to ASCII format and
  1006. go to the beginning of the file by typing
  1007.  
  1008.     <ret>
  1009.     A G 1800+(a2-2)*400
  1010.  
  1011. The display should look like this
  1012.  
  1013.     0000:29800     |Now is t|
  1014.     0000:29808     |he time |
  1015.     0000:29810     |for all |
  1016.     0000:29818     |good men|
  1017.     0000:29820     | to come|
  1018.     0000:29828     | to the |
  1019.     0000:29830     |aid of t|
  1020.     0000:29838     |heir cou|
  1021.     0000:29840     |ntry... |
  1022.     0000:29848     |DOC ....|
  1023.     0000:29850     |.......5|
  1024.     0000:29858     |..:.Og..|
  1025.     0000:29860     |DIS86Z  |
  1026.  
  1027. The file information is present, although there appears to be some
  1028. garbage following it.
  1029.  
  1030. Each cluster has an entry in the File Allocation Table, or FAT.  When a
  1031. file is deleted, its clusters are marked as "free" by zeroing the
  1032. corresponding entries in the FAT.  Display the beginning of the FAT by
  1033. typing
  1034.  
  1035.     U G 200
  1036.  
  1037. To move to the FAT entry for cluster a2, type
  1038.  
  1039.     G A $+(a2*3)/2
  1040.  
  1041. (Recall that '$' stands for the current location.) In my case, the
  1042. display starts
  1043.  
  1044.     0000:02F3      000 fff 000 000
  1045.     0000:02F9      000 000 000 000
  1046.  
  1047. The second entry, which corresponds to cluster a3 of PATRIOT.2, has the
  1048. code for "last cluster".  The first entry, which corresponds to cluster
  1049. a2, is still zero so that file can be "undeleted".  To do that, we
  1050. change the entry to the value for "last cluster":
  1051.  
  1052.     E fff <ret>
  1053.  
  1054. We have to make the same change in the other copy of the FAT.  Recall
  1055. that each FAT is 400 (hex) bytes long:
  1056.  
  1057.     G $+400 <ret>
  1058.     E fff <ret>
  1059.  
  1060. To return to the directory entry type
  1061.  
  1062.     <left> <left> <left> 
  1063.  
  1064. At this point the disassembler must move its window so it asks our
  1065. permission to write the changes to the disk:
  1066.  
  1067.     Y <ret>
  1068.     <left> 
  1069.  
  1070. Now, restore the first byte of the filename:
  1071.  
  1072.     E 'P' <ret>
  1073.  
  1074. To leave the disassembler (and agree to write the directory change
  1075. out), type
  1076.  
  1077.     /FQ Y <ret>
  1078.  
  1079. To confirm that both files exist, ask for a directory listing
  1080.  
  1081.     A>dir pa*
  1082.  
  1083.  
  1084. NOTES
  1085.  
  1086. When there is more than one cluster in a file, the directory entry
  1087. contains the number of the first cluster.  The FAT entry corresponding
  1088. to the first cluster contains the number of the second cluster.  This
  1089. chain of cluster numbers continues, with the FAT entry for the last
  1090. cluster containing fff.  DOS often allocates all the clusters together
  1091. (making the file contiguous).  For example, in this fragment of a FAT
  1092.  
  1093.     0000:03CE      135 136 137 fff
  1094.     0000:03D4      139 fff 13b 13c
  1095.     0000:03DA      fff 13e 13f 143
  1096.  
  1097. there seems to be a file occupying the two clusters 138 and 139, and a
  1098. second file occupying the three clusters 13a, 13b, and 13c.  I say
  1099. "seems" because it is not obvious from just this printout that cluster
  1100. 138 (whose entry at 03d4 contains the pointer to 139) is actually the
  1101. first cluster of a file.  Only LAST clusters are explicitly marked in
  1102. the FAT.  To confirm that it is indeed the first cluster of a file, we
  1103. could search the rest of the FAT and verify that there was no pointer
  1104. to 138, or we could find the pointer to 138 in some directory entry.
  1105.  
  1106. Longer files are more trouble to unerase, but of course are also more
  1107. valuable.  To calculate the length in clusters for a longer file we
  1108. would use the V (evaluate) function.  For example, for a 1345 byte file
  1109. type:
  1110.  
  1111.     V 1345/400 <ret>
  1112.  
  1113. The answer, 3, is the number of full clusters.  Remember to add one for
  1114. the partially filled cluster at the end.  If there were four clusters
  1115. in the file in the file you want to undelete, then there will be zeros
  1116. in the four corresponding entries in the FAT.  The directory tells you
  1117. only where the first entry is.  The other three entries could be
  1118. literally anywhere else in the FAT, but since DOS assigns the next
  1119. available cluster to a growing file, they can probably be found shortly
  1120. after the first entry.  Even if you find four zero entries in a row
  1121. starting there, some of those free clusters could have belonged to some
  1122. other deleted file.  You still need to check the data in the clusters
  1123. to be sure.
  1124.  
  1125.