home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / DIS86.DOC < prev    next >
Text File  |  1987-12-15  |  34KB  |  942 lines

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