home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / GRDBDL17.ZIP / DIS.ASM < prev    next >
Encoding:
Assembly Source File  |  1998-10-26  |  10.7 KB  |  325 lines

  1. ;
  2. ; GRDB
  3. ;
  4. ; Copyright(c) LADsoft
  5. ;
  6. ; David Lindauer, camille@bluegrass.net
  7. ;
  8. ;
  9. ; dis.asm
  10. ;
  11. ; Function: patch the dissassembly code together, display the output
  12. ;    handle disassembler commands
  13. ;
  14.     ;MASM MODE
  15.     .model small
  16.     .386
  17.  
  18. include  eprints.inc 
  19. include  ioperand.inc
  20. include  eoperand.inc 
  21. include  iopcodes.inc
  22. include  eopcodes.inc 
  23. include  emtrap.inc 
  24. include  einput.inc 
  25. include  eoptions.inc
  26.  
  27.     PUBLIC    diss,DisOneLine
  28.  
  29. DEFAULTBYTES = 32        ; max number of bytes/line (should be 16)
  30.  
  31.     .data
  32.  
  33. startingDisAddr    dw    0    ;current disassembly address
  34. endningDisAddr    dw    ?    ;end of disassembly
  35. extraBytes    dw    0    ;number of overflow bytes, e.g. if instruction
  36.                 ;was more than five bytes we need more lines
  37. DisassemblySeg    dw    0    ;disassembly segment
  38.  
  39.     .code
  40.     oldposition EQU bp - 4    ;beginning of bytes for line
  41.     put    EQU bp -6    ;unused
  42.     bytestomove EQU bp - 8    ;number of bytes to put in hex dump portion
  43.                 ;of line
  44. ;    .code
  45.  
  46. isNewLine    EQU    [bp-2]    ;set to true if we are doing an overflow line
  47. oldposition    EQU    [bp-4]    ;beginning of bytes for line
  48. put        EQU    [bp-6]    ;unused
  49. bytestomove    EQU    [bp-8]    ;number of bytes to put in hex dump portion
  50.                 ;of line
  51.  
  52. ;
  53. ; Get a dissassembled line of code
  54. ; INPUT: DI points to 256-byte buffer in caller's stack frame
  55. ;    Remember that DS=SS during this process
  56. ;    SI appears to point to the code to disassemble
  57. ;
  58. GetCodeLine    PROC    
  59.     ENTER    8,0                   ;8 bytes of automatic space
  60.     mov    WORD PTR isNewLine,TRUE ; Assume it has an opcode
  61.     mov    BYTE PTR [di],0        ; Clear output buffer
  62.     mov    oldposition,si        ; Current position
  63.     test    extrabytes,0FFh        ; See if still printing bytes
  64.     jz    short notextra        ; from last instruction
  65.  
  66. ;Only 5 code bytes fit on a line before the mnemonics, so if this instruction
  67. ;had >5 bytes, we need to stick them on another line by themselves. In this
  68. ;case, we already snagged them, and I guess DI points to them.  So we add
  69. ;the number of additional bytes to our pointer to the input, then exchange
  70. ;this with the buffer pointer
  71. ;  The implication here is that the entire opcode has been disassembled
  72. ;and converted to mnemonics, but defninitely not clear yet just exactly
  73. ;where the extra opcode bytes get displayed.  Right here, we tab over to
  74. ;a new position and zero out the buffer beyond those bytes.
  75.  
  76.     add    si,extrabytes        ; New position to edi
  77.     xchg    si,di            ;
  78.  
  79. ;Now, SI points into the buffer at a location just past the extra bytes. We
  80. ;put a 0 into the buffer for reasons unknown right now, then call TabTo.
  81. ;AHA, TabTo calls strlen, which will return a string length of 0 since SI
  82. ;points to a 0, and therefore we get a full tab. TabTo stuffed the
  83. ;intervening positions with spaces, and terminated them with 0. But we
  84. ;overwrite that and the next 15 buffer positions with 0 anyway.
  85.  
  86.     mov    BYTE PTR [si],0        ; Clear buffer
  87.     mov    al,10            ; Tab to pos 14
  88.     call    TabTo            ; by stuffing spaces into the buffer
  89.     xchg    si,di            ; edi = buffer again now
  90.     push    di            ;save buffer position
  91.     mov    cx,4            ; next four DWORDS = 0;
  92.     sub    ax,ax            ;
  93.     rep    stosd            ; Store the dwords
  94.     pop    di            ;and point at 16 0's
  95.     mov    WORD PTR isNewLine,False; Doesn't have an opcode
  96.     jmp    btm
  97.  
  98. ;OK, we aren't doing leftover stuff from the prior call.
  99.  
  100. notextra:
  101.     mov    ax,code_address        ; Get code address
  102.     cmp    ax,endningDisAddr            ; See if done
  103.     jnc    endcodeline        ; Quit if nothing left
  104.     xchg    si,di            ; esi = buffer now
  105.     push    esi            ;save buffer address
  106.     mov    ax,fs            ;get segment
  107.     call    putword            ;build that into buffer
  108.     mov    BYTE PTR [si],':'    ; Print ':' in buffer
  109.     inc    si            ;go past the colon
  110.     mov    ax,code_Address        ; Get code address
  111.     call    putword            ; Print it out in buffer
  112.     mov    BYTE PTR [si],' '    ; Put a space
  113.     inc    si            ;go past the space
  114.     mov    BYTE PTR [si],0        ; Put an end-of-buffer
  115.     pop    eax            ;restore the buffer address into EAX
  116.     xchg    esi,eax            ;now put it into ESI, EAX has new ptr
  117.     push    eax            ;save new pointer
  118.     mov    al,25                   ; Tab to pos 29
  119.     call    TabTo            ;stuff with spaces
  120.  
  121. ;XCHG always gives me headaches.  Lets see... TabTo bumped SI up, while EAX
  122. ;still holds the buffer position before the spaces TabTo put in there.
  123. ;More important, the prior position is on the stack, since we are about to
  124. ;blow EAX at ReadOverrides. This old position (just after the offset) will
  125. ;eventually be popped into EDI.
  126. ;  Now DI points to the post-spaces position, and SI points to whatever DI
  127. ;pointed to.  This requires a careful trace, so:
  128. ;1) DI entered this routine pointing to the 256-byte buffer on the stack
  129. ;2) Then, it was exchanged, so DI pointed to the code to disassemble
  130. ;3) Now, di points back into the buffer and SI points to the code to dis
  131.  
  132.     xchg    si,di            ; edi = buffer beyond spaces
  133.     call    ReadOverrides        ; Read any overrides
  134.     call    FindOpcode        ; Find the opcode table
  135.  
  136. ;The prior two calls moved SI past this opcode, which was consumed and
  137. ;translated. NOW we point SI back into the buffer and DI at the code
  138. ;to disassemble.
  139.  
  140.     xchg    si,di            ; esi = buffer, di=code
  141.     jnc    short gotopcode        ; Got opcode, go format the text
  142.  
  143. ;If the opcode was unrecognised, we need to just DB this byte and try again
  144. ;to find the start of an opcode on the next byte until we are back into
  145. ;some kind of sync again.
  146.  
  147.     push    si            ; Else just put a DB
  148.     mov    ax,"db"            ;opcode not in table, could be new
  149.     call    put2            ; CPU type
  150.     pop    si            ;restore position before 'db'
  151.     mov    al,TAB_ARGPOS        ; Tab to the arguments=12+4?
  152.     call    TabTo            ;stuff with spaces
  153.     mov    al,fs:[di]        ;Get next code byte into AL
  154.     inc    di            ;bump code pointer
  155.     call    putbyte            ;cvt to ASCII and stick in bufer
  156.     mov    BYTE PTR [si],0        ; End the buffer
  157.     xchg    si,di            ;DI=buffer, SI=code
  158.     pop    edi            ;address just past offset of address
  159.     jmp    short btm        ; Go do the byte dump
  160.  
  161. ;If we got here, the opcode was recognized.  Right here:
  162. ;SI=buffer pointer, DI=code pointer
  163.  
  164. gotopcode:
  165.     push    si            ;save buffer pointer
  166.     mov    si,di            ;point SI at the code
  167.     sub    ax,ax            ; assume 16-bit disassembly
  168.     call    DispatchOperands    ;this probably bumps SI past them
  169.     mov    di,si            ;so DI is now the code pointer
  170.     pop    si            ;restore the buffer pointer
  171.     push    di            ;save the code pointer
  172.     call    FormatDisassembly    ;Use the operand parse to format output
  173.     pop    di            ;restore code pointer
  174.     xchg    si,di            ;SI now code, DI now bufer
  175.  
  176. ;EAX, pushed far above, contained a pointer into the buffer just past the
  177. ;offset part of the address plus 1 space, and points at the 0 following
  178. ;that space.
  179.  
  180.     pop    edi            ;but so what, since DI now restored
  181. btm:
  182.  
  183. ;We already put a 0 in this location way up above, but I guess it won't
  184. ;hurt to do it twice, just to make sure...
  185.  
  186.     mov    BYTE PTR [di],0        ; End the buffer
  187.  
  188. ;Ouch. Let's see... SI points to the code we are disassembling whether we
  189. ;found a valid opcode or not.  Probably coincidence.
  190.  
  191.     mov    ax,si            ; Calculate number of bytes to dump
  192.     sub    ax,oldposition        ;by subtracting old from new offset
  193.     mov    bytestomove,ax        ;and set variable with result
  194.     mov    extrabytes,0        ; Bytes for next round = 0
  195.     cmp    WORD PTR bytestomove,5    ; See if > 5
  196.     jbe    short notmultiline    ; No, not multiline
  197.     mov    ax,bytestomove        ; Else calculate bytes left
  198.     sub    al,5            ;and save result for next time
  199.     mov    extrabytes,ax    
  200.     mov    WORD PTR bytestomove,5    ; Dumping 5 bytes - our max
  201. notmultiline:
  202.  
  203. ;Ouch again. Lets see... SI points to the code, and DI to the buffer, so
  204. ;we switch them, DI=code and SI=buffer
  205.  
  206.     xchg    si,di            ; esi = buffer
  207.     push    di            ; Save code pointer
  208.      mov    di,oldposition        ; Get original code position
  209.     mov    cx,bytestomove        ; Get bytes to move
  210. putlp:
  211.     mov    al,fs:[di]        ; Get a byte
  212.     call    putbyte            ; Expand to ASCII
  213.     mov    BYTE PTR [si],' '    ; Put in a space
  214.     inc    si            ; Next buffer pos
  215.     inc    di            ; Next code pos
  216.     LOOP    putlp            ; Loop till done
  217.     xchg    si,di            ; Restore regs DI=buf, SI=code
  218.     mov    ax,bytestomove        ; Codeaddress+=bytes dumped
  219.     add    code_address,ax    
  220. endcodeline:
  221.     mov    ax,isNewLine        ; Return new line flag
  222.     LEAVE                
  223.     ret
  224. GetCodeLine    ENDP    
  225. ;
  226. ; Main disassembler
  227. ; The user pressed the U command key, followed by ???, then CR.  We are going 
  228. ; to disassemble from either where we are, or from the address provided.
  229. ;    My guess is that SI points to the input line at the character
  230. ; following the U.
  231. ;  
  232. ;
  233. diss    PROC    
  234.     ENTER    256,0            ; Buffer = 256 bytes long
  235.     call    crlf            ; start on new line
  236.     call    WadeSpace        ; See if any parms
  237.     jz    short atindex        ; No disassemble at index
  238.     call    ReadAddress        ; Else read start address into BX
  239.     jc    badargs            ; Get out bad args
  240.     mov    ax,DEFAULTBYTES        ; Number of bytes to disassemble=32
  241.     add    ax,bx            ; Find end of disassembly
  242.     jnc    okadd            ; Seems to be a segment limit
  243.           mov    ax,0FFFFh        ; goto end of segment?
  244. okadd:
  245.     mov    endningDisAddr,ax    ; Save count? as default
  246.     call    WadeSpace        ; See if any more args
  247.     jz    short gotargs        ; No, got args
  248.     call    ReadNumber        ; Read the end address
  249.     jc    short badargs           ; Out if bad args
  250.     mov    endningDisAddr,ax            ; Save end
  251.     jmp    short gotargs        ; We have args
  252. badargs:
  253.     stc                ; Error
  254.     LEAVE
  255.     ret
  256. atindex:
  257.     mov    bx,startingDisAddr    ; Get the next address to disassemble
  258.     mov    dx,DisassemblySeg     ;
  259.     mov    ax,DEFAULTBYTES        ; Default bytes to disassemble
  260.     add    ax,bx            ;
  261.     mov    endningDisAddr,ax     ; Set up end
  262. gotargs:
  263.     call    defCS            ; get CS segment
  264.     mov    code_address,bx        ; Save code address for printout
  265.     mov    si,bx            ;
  266.     mov    fs,dx            ; ES = the seg
  267.     mov    DisassemblySeg,fs        
  268. gcloop:    
  269.     call    scankey
  270.     jnz    dusetadr
  271.     lea    di,[bp - 256]        ; Get the buffer
  272.     call    GetCodeLine        ; Get a line of text
  273.     lea    bx,[bp - 256]        ; Print out the text
  274.     call    dgroupMessage
  275.     call    crlf
  276.     cmp    si,0fff0h
  277.     jnc    dusetadr2
  278.     cmp    si,endningDisAddr        
  279.     jc    gcloop            ; Loop if not
  280.     test    extrabytes,0FFFFh    ; Loop if not done with dump
  281.     jnz    gcloop            
  282. dusetadr:
  283.     mov    si,code_address    
  284.     mov    startingDisAddr,si        
  285.     clc
  286.     LEAVE
  287.     ret
  288. dusetadr2:
  289.     sub    si,si
  290.     mov    code_address,si
  291.     jmp    dusetadr
  292. diss    ENDP    
  293. ;
  294. ; Disassemble one line.  Used by the Reg display command
  295. ; INPUT: DX holds segment value (CS)
  296. ;    BS holds offset value (IP)
  297. ;
  298. DisOneLine    PROC    
  299.     ENTER    256,0            ; Space for buffer
  300.     push    bx             ;save logical IP
  301.     push    dx            ;and logical CS
  302.     call    crlf            ;so CRLF won't blow them
  303.     pop    dx
  304.     pop    bx
  305.     mov    ax,1            ;move to next position        
  306.     add    ax,bx            ; One byte to disassemble
  307.     mov    endningDisAddr,ax     ;(will disassemble entire instruction)
  308.     mov    code_address,bx        ;save this disassembly address
  309.     mov    fs,dx            ;save segment in FS
  310.     mov    si,bx            ;point to code to disassemble in SI
  311.     mov    startingDisAddr,si    ; Save new starting index
  312.     mov    DisassemblySeg,fs     ;set disassembly segment
  313. dol_loop:
  314.     lea    di,[bp - 256]        ;Point DI at buffer to dis into
  315.     call    GetCodeLine        ; Get a line of code
  316.     lea    bx,[bp -256]        ;point BX at line we created
  317.     call    dgroupMessage        ;and put it on the screen
  318.     call    crlf            ;down to the next line
  319.     test    extrabytes,0FFFFh    ; See if >5 opcode bytes
  320.     jnz    dol_loop        ; Loop if so
  321.     clc                ; No errors
  322.     leave
  323.     ret
  324. DisOneLine    ENDP    
  325. END