Source code for a disassembler (16/32-bit code) and a simple
DOS based disassembler to test it.

If you want to use DIS.COM, just copy it to \Windows\Command or
any other directory in your PATH environment variable.
Type "PATH" to see all the paths.

This is free software. No-one may sell this program.
You may distribute this as much as you want, though.

My email is at the last line in this file.
Email me bugs and questions about this program. No spam.

Chances are that you have NOT the latest version!
http://home.bip.net/wbinvd/dislib.zip
is always the latest version. Start your browser and d/l it.

What are all those files?
-------------------------
w.bat   - Builds a C++ Win32 disassembler app. You must have
          Borland C++ (or any other C++ compiler). It just
          shows you how to call the dis() and __dis() procedures
          from C/C++. It disassembles WinMain()

x.bat   - Same as w.bat, but it disassembles main() and is
          a DOS app.

Makefile - Build DIS.COM and disassembler libs
 o Make                 Creates DIS.COM
 o Make DIS.COM         Same as above
 o Make dislib16        Create dislib16.lib (ASM lib)
 o Make dislib32        Create dislib32.lib (ASM lib)

How do I assemble it?
---------------------
Use the Makefile, but if you like to type:
NOTE: Add "/DClib" if you want to call them from a C/C++ procedure
after the "/t" option. You must also define the model you will
use "/Dmdl=MODEL" where MODEL is TINY, SMALL, MEDIUM (etc...)

16-bit code:
        TASM /w2/ml/t dislib
        TASM /w2/ml/t __dislib
        del dislib16.lib
        TLIB dislib16.lib +dislib +__dislib,dislib16.lst

And if you want 32-bit code:
        TASM /w2/ml/t dislib32
        TASM /w2/ml/t __disl32
        del dislib32.lib
        TLIB dislib32.lib +dislib32 +__disl32,dislib32.lst

DIS.COM: (Create dislib16.lib first)
        TASM /w2/ml/t dis.asm
        TASM /w2/ml/t misc.asm
        TLINK /3/t dis misc,dis,dis,dislib16.lib

FAQ
---
Q: The command line options are really hard to understand!
A: Don't worry. Most of them are NOT needed. I just added
   them so you it would disassemble the code the way you
   code your own ASM files (if you code in ASM, that is).

A little documentation for DIS.COM:

    Here's how you enter one or more options on the command line:
        1 A /
        2 If you want to remove an option, add a -
        3 Print the "option-group" character
        4 Print one or more characters in that option group
        5 If the option requires a string/number/whatever,
          you can print spaces/tabs/nothing and then print the
          string/number/whatever (/xc9 or /xc      9)
        6 Print as many spaces/tabs as you like or go to 1
          or press enter

          /xp/xa        can also be     /xpa
          /xp/Nz        can NOT be      /xpz
          /-xp/xa       can NOT be      /-xpa
          /-xp/-xa      can also be     /-xpa
          /xp/xa        can also be     /xp /xa
          /-etc         can also be     /-etc

    All of the options you can use:

        ;All of the /pX options are default! use /-pX to remove one or more
        /pc     print cs value on each line
        /pe     print ip (16-bit code) or eip (32-bit code) value on each line
        /pb     print the opcode bytes on each line
        /po     print the opcodes and operands
        /pl     print labels instead of offsets in call/jmp (near/short)

        ;Uppercase some stuff (lowercase if you remove one or more of them)
        /um     uppercase all mnemonics (mov -> MOV)
        /ur     uppercase all registers (cr0 -> CR0)
        /up     uppercase all ptr strings (word -> WORD)
        /ub     uppercase base # char (FFh -> FFH)

        ;How should we print a number?
        /n0     use 0 as msd if needed (12h -> 12h FFh -> 0FFh)
        /na     always 0 as msd (12h -> 012h FFh -> 0FFh)
        /nb     use base # character (21 -> 21h)
        /nn     use base # char if needed (21 -> 21 FB -> FBh 1D -> 1Dh)
        /nl     lowercase hex characters (FFh -> ffh)
        /nf     as few digits as possible (0001h -> 1h)
        /nc     C/C++ numbers (1234h -> 0x1234). Good with /xa option
                Note: /nb option must also be set!

        ;Inside or outside the brackets?
        /bs     print segment overrides inside the brackets (es:[0] -> [es:0])
        /bp     print ptr strings inside (word ptr [0] -> [word ptr 0])

        ;Show something?
        /sm     print the memory's size (mov al,[0] -> mov al,byte ptr [0])
        /so     print the opcode size (not all ops) (pushf -> pushfw)
        /ss     print the seg mem size ([0],es -> dword ptr [0],es)
                        db      66h
                        mov     [0000],es
                                will be:
                        mov     dword ptr [0000],es
                                even if this option isn't set
                                since a 66h prefix was found
        /sc     a space after the comma (xor ax,DEADh -> xor ax, DEADh)

        ;A no really means NO
        /Nd     no brackets if it's just a displacement ([0] -> 0)
        /Nm     no brackets if it's [reg] mem ([esp+ebp] -> esp+ebp)
        /Nz     no zero-displacement if [reg] mem ([bp+00] -> [bp])
        /Ns     no short (jmp short X -> jmp X)
        /Np     no ptr (word ptr [0] -> word [0])
        /NM     no mem size (dword ptr [0],00000000h -> [0],00000000h)
        /No     no at&t opcode size if there's a reg in one of the operands
                (movb %al,%cl -> mov %al,%cl)

        ;Always print segment overrides if there are no segment overrides
        /od     print ds: override if it's just a displ ([0000] -> ds:[0000])
        /om     print default segoverride if [reg] mem ([esp] -> ss:[esp])

        ;Print "near ptr"/"far ptr"?
        /jn     print "near ptr" if it's a near call/jmp
                (jmp X -> jmp near ptr X)
        /jf     print "far ptr" if it's a far call/jmp
                (jmp X:Y -> jmp far ptr X:Y)

        ;Some junk
        /x1     print *1 if the scale is *1 ([eax+ecx] -> [eax+ecx*1])
        /xr     tab after rep/repnz
                (rep stosd      -> rep     stosd)
        /xb     base # is binary
        /xo     base is octal (base # character is o)
        /xq     base is octal (base # character is q)
        /xd     base is decimal
        /xh     base is hexadecimal (default)
        /xs     expand string instructions and xlatb
                movsw -> movs word ptr es:[di],word ptr [si]
                Normally, xlatb and string instructions are only
                expanded if we've found a segment override or a 67h prefix
        /xt<N>  set the new tabsize between the first character in
                the mnemonic name to the first operand (default is 8)
        /xp     disassemble this program from memory
        /xc<N>  opcode start column. If you've used "/-pceb",
                use "tabsize+1" (9) for best result.
                Default is 28h (good for 32-bit code, 1Ah=good for 16-bit)
        /xf     print all float opcodes as ESC. Normally, we only print
                it as esc if the opcode is 00D8h-00DFh and it's not a
                float opcode
        /xP     rep/repnz/lock/segoverrides are instructions. It won't work
                if a 66h/67h byte is placed before any of them
        /xa     use AT&T syntax (you know, the ugly syntax).
                All instructions except enter/enterw/enterl/db
                are reversed:
                        mov     eax,ecx         ;intel (default)
                        movl    %ecx,%eax       ;at&t (ugly, and not default!)

        ;What should we disassemble today, my son?
        /dc<N>  # of bytes to disassemble
        /dl<N>  # of lines to disassemble. A line is not just
                a mnemonic and its operands, but also a label!
        /df<FILENAME> disassemble a file
        /dm<SEG:OFS> disassemble memory. SEG:OFS must be in hex
        /dx<FILENAME> disassemble an exe file (skip the .exe header)
        /do<N>  new file offset to start disassembling a file from.
                if we're disassembling an exe file, we add this offset
                to the start of the exe header size
        /dC<N>  new cs value (if we're disassembling a file)
        /de<N>  new ip/eip value (if we're disassembling a file)

        ;What processor should we assume we disassemble for?
        /ci     intel 8088 to P2. This is the default option.
        /ca     AMD and AMD K3D opcodes. If any of AMD's opcodes are
                mapped to the same place as one of intel's, dis will
                use AMD's opcodes.
        /cc     Cyrix CPU opcodes. They have some more MMX instructions.
                The same rule applies for Cyrix' opcodes VS Intel's opcodes.
                If they are mapped to the same place, we will use Cyrix'
                opcodes.

        ;Pick a codesize
        /16     it's 16-bit code (default)
        /32     it's 32-bit code

    A good thing to know:
        Dis scans the environment for "DISCMD=". Put your
        favorite options in it ("set discmd=/Xxxx/-Yyyy").
        The options in the environment is parsed before the
        options on the command line. Put that line in your
        autoexec.bat file so it's executed whenever you start
        dos/win/win95/win98/whatever
    Another good thing to know:
        All numbers passed on the command line can be in any base.
        (they are dwords, 32-bit numbers)
                1111b   binary
                9999    decimal
                9999d   decimal
                7777o   octal
                7777q   octal
                FFFFh   hexadecimal
        No leading zeros are needed.

http://home.bip.net/wbinvd/dislib.zip
mailto:wbinvd@mail.bip.net
