%title 'Main program for my disassembler. (c) 1998 Henrik Nebrin'

;BUGS:
;       1. If it's 32-bit code and we're disassembling it from memory,
;          we're still limited to 64k segments. We truncate eip to 64k
;          and increment cs in disassemble:proc and rememberallcodelabels:proc.
;          I fixed this so this bug isn't present if we're disassembling
;          a file and it's 32-bit. I didn't fix it for memory since if
;          we should disassemble > 64k, and we get a byte from cs:eip,
;          it will still be truncated to 64k. So we'll increment cs by
;          1000h and decrement eip by 100000h.

        ideal
        p386
        nowarn  brk

_wordsize       equ     2
        include 'proc.inc'
        include '__dislib.inc'
        include 'dislib.inc'

signed          equ     0001h           ;eax is a signed number
showsign        equ     0002h           ;always show '+' or '-'
bighex          equ     0004h           ;big hex characters (A-F) (ntoa:proc)

;debug   equ     1
;debug32 equ     1

        extrn   strlen:procptr,__ntoa:procptr,strcpy:procptr,antob:procptr
        extrn   ahtob:procptr

printcs         equ     01h             ;print cs value
printeip        equ     02h             ;print ip/eip value
printbytes      equ     04h             ;print the opcode bytes
printopcode     equ     08h             ;print the opcode
printlabels     equ     10h             ;print labels instead of offsets

stacksize       equ     0200h

ifdef iscom
        startlastseg
        dw      stacksize/2 dup (?)
label   stackofs word
        endlastseg
else
        startstack
        dw      stacksize/2 dup (?)
label   stackofs word
        endstack
endif

        startcodeend
        assume  cs:@curseg
label   lastcodeofs near
        endcodeend

        startbss
dis_input       dis_input_t ?
labelseglinear  dd      ?               ;labelseg shl 4
opcodeeip       dd      ?               ;start of opcode
bytesseg        dw      ?               ;segment of where the code is
filehandle      dw      ?               ;must be after bytesseg
opcodebytesptr  dw      ?               ;ptr in opcodebytes
bufbytesleft    dw      ?               ;# of bytes left in the buffer
buflen          dw      ?               ;buffer length
ifndef iscom
psp             dw      ?
endif
label   filename byte
disstring       db      80 dup (?)
opcodebytes     db      40 dup (?)      ;more than enough for a valid opcode
label   opcodebytesend byte
tmpstring       db      160 dup (?)     ;'cs:ip XXXX    opcode' string
        endbss

        startconst
firstoptiontable        db      'punsNjbox?d13c'
nfirstoptions   = $-firstoptiontable
        align   word
firstoptiontableptrs    dw      charsp,optblp,charsu,optblu,charsn,optbln,\
                                charss,optbls,charsNN,optblNN,charsj,optblj,\
                                charsb,optblb,charso,optblo,charsx,optblx,\
                                chars?,optbl?,charsd,optbld,chars1,optbl1,\
                                chars3,optbl3,charsc,optblc
n=($-firstoptiontableptrs)/4
if n ne nfirstoptions
  err
endif
optblp          dw      @pc,@pe,@pb,@po,@pl
optblu          dw      @um,@ur,@up,@ub
optbln          dw      @n0,@na,@nb,@nn,@nl,@nf,@nc
optbls          dw      @sm,@ss,@so,@sc
optblNN         dw      @NNd,@NNm,@NNz,@NNs,@NNp,@NNMM,@NNo
optblj          dw      @jn,@jf
optblb          dw      @bp,@bs
optblo          dw      @od,@om
optblx          dw      @x1,@xs,@xb,@xo,@xq,@xd,@xh,@xr,@xt,@xp,@xc,@xf,@xPP,@xa
optbl?          dw      @?
optbld          dw      @dc,@dl,@dm,@df,@dx,@do,@dCC,@de
optbl1          dw      @16
optbl3          dw      @32
optblc          dw      @ci,@ca,@cc
charsp          db      5,'cebol'       ;cobol?
charsu          db      4,'mrpb'
charsn          db      7,'0abnlfc'
charss          db      4,'msoc'
charsNN         db      7,'dmzspMo'
charsj          db      2,'nf'
charsb          db      2,'ps'
charso          db      2,'dm'
charsx          db      14,'1sboqdhrtpcfPa'
label   chars1 byte
label   chars3 byte
chars?          db      0
charsd          db      8,'clmfxoCe'
charsc          db      3,'iac'
printflags      db      printcs or printeip or printbytes or printopcode or printlabels
outofmem        db      'Out of memory',13,10
outofmemlen     = $-outofmem
disintro        db      'DIS Copyright (c) 1998 Henrik Nebrin <wbinvd@mail.bip.net>',13,10,'$'
optionerr       db      'option error',13,10
optionerrlen    = $-optionerr
tabsizestr      db      'tabsize 1-20h, please',13,10
tabsizelen      = $-tabsizestr
erropenfile     db      'error opening the file',13,10
erropenfilelen  = $-erropenfile
readerrstr      db      'error reading the file',13,10
readerrlen      = $-readerrstr
notexe          db      'not an exe file',13,10
notexelen       = $-notexe
nocount         db      'you must tell me how much to disassemble /dl<N> or /dc<N>',13,10
nocountlen      = $-nocount
opcodestartstr  db      'opcodestart 1-50h, please',13,10
opcodestartlen  = $-opcodestartstr
outoflabels     db      'No more memory for more labels! Need more memory...',13,10
outoflabelslen  = $-outoflabels
printedlabelerr db      00h

label   dishelp byte
  db    'DIS Help for helpless people (not that you are one, though)',13,10
  db    '  /pcebol       c - print cs            e - print eip',13,10
  db    '                b - print opcode bytes  o - print opcodes & operands',13,10
  db    '                l - print all labels (LSEGOFS: jmp LSEGOFS)',13,10
  db    '  /umrpb        m - uppercase mnemonic  r - uppercase registers',13,10
  db    '                p - uppercase ptr       b - uppercase base # character',13,10
  db    '  /n0abnlfc     0 - 0 as msd if needed  a - always a 0 as msd (left-most digit)',13,10
  db    '                b - use base # char     n - base char if needed',13,10
  db    '                l - lcase digit chars   f - as few digits as poss.: 0021 -> 21',13,10
  db    '                c - 1234h -> 0x1234',13,10
  db    '  /bsp          s - seg inside brackets p - ptr inside brackets [word ptr 0]',13,10
  db    '  /smosc        m - show the mem''s size o - show opcode size',13,10
  db    '                s - show seg mem size   c - space after the comma',13,10
  db    '  /NdmzspMo     d - no brack. if displ. m - no brack. if reg mem ([bp]/[etc])',13,10
  db    '                z - no zero-displ.      s - no short: jmp short X -> jmp X',13,10
  db    '                p - no ptr: [word 0]    M - no memory size: mov [0],0',13,10
  db    '                o - movb %al,%cl -> mov %al,%cl (only if op has a reg)',13,10
  db    '  /odm          d - [1234] -> ds:[1234] m - [reg] -> defaultseg:[reg]',13,10
  db    '  /jnf          n - call/jmp near ptr   f - print "far ptr" if far call/jmp',13,10
  db    '  /x1rboqdhstp  1 - show *1: [eax*1]    r - tab after rep/repnz',13,10
  db    '  /xcfPa        b - base is binary      o - base is octal (ends in o)',13,10
  db    '                q - octal (ends in q)   d - base is decimal',13,10
  db    '                h - base is hexadecimal s - expand string instr. + xlat',13,10
  db    '                t - new tabsize         p - disassemble this program',13,10
  db    '                c - opcode start column f - print all float ops as ESC',13,10
  db    '                P - prefixes are instr. a - AT&T: mov al,ah -> movb %ah,%al',13,10
  db    '  /dclfmxoCe    c - # of bytes to dis   l - # of lines to disassemble',13,10
  db    '                f - file to dis from    m - seg:ofs to disassemble (in hex)',13,10
  db    '                x - exe file (skip hdr) o - new file offset to dis from',13,10
  db    '                C - cs value (files)    e - eip value (files only)',13,10
  db    '  /ciac         i - intel 8088+ opcodes a - AMD CPU and 3DNow! opcodes',13,10
  db    '                c - Cyrix CPU opcodes',13,10
  db    '  /16 /32       16 - 16-bit code        32 - 32-bit code',13,10
  db    '  /-Xxx clears the option: /-pceb/-nb: clear /pceb and /nb',13,10
  db    'The environment is scanned for "DISCMD=" (do ``set DISCMD=/Xxxx/Yyyy/....'''')',13,10
  db    'try this: ``DIS /-pceb/n0b/Nz/xht8/xc1Ah/xc9/dmF000:0000/dc10000h''''',13,10
  db    '$'
DISCMD  db      'DISCMD=',0
        endconst

        startdata
bytesleft       dd      -1              ;# of bytes left to disassemble
linesleft       dd      -1              ;# of lines left to disassemble
fileofs         dd      00000000h       ;start in the file to disassemble from
label   bufptr dword
bufofs          dw      0000h           ;current buffer offset
bufseg          dw      0000h           ;buffer segment
label   labelptr fword
labelofs        dd      0000h
labelseg        dw      0000h
opcodestart     dw      28h             ;start of opcode string
labelsize       dd      0000h
disfile         db      00h             ;disassemble a file?
skipheader      db      00h             ;skip exe header?
        enddata

        startcode
ifdef iscom
        org     0100h
start:
        assume  es:@data,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        cmp     sp,offset stackofs-2
        jae     short @@spok
@@outofmem:
        mov     cx,outofmemlen
        mov     dx,offset outofmem
        call    near ptr printerrstring
        int     20h
@@spok:
        mov     sp,offset stackofs
        mov     bx,sp
        shr     bx,04h
        mov     ah,4Ah
        int     21h
        jc      short @@outofmem
else
start:
        assume  es:nothing,cs:@code,ss:@stack,ds:nothing,fs:nothing,gs:nothing
        mov     ax,es
        mov     bx,seg __lastofs
        sub     bx,ax
        mov     ah,4Ah
        int     21h
        push    @data
        pop     ds
        assume  ds:@data
        jnc     short @@10
@@outofmem:
        mov     cx,outofmemlen
        mov     dx,offset outofmem
        call    near ptr printerrstring
        mov     al,01h
        jmp     exit
@@10:
ifndef stackfar
        push    ds
        pop     ss
        assume  ss:@data
        mov     sp,offset stackofs
endif
        mov     psp,es
        push    ds
        pop     es
        assume  es:@data
endif

if @datasize
        push    ds
        pop     gs
        assume  gs:@data
endif
        mov     si,offset dis_input
        mov     bh,10h
        call    dis_changenumberbase
        mov     (dis_input_t ptr ds:si).__dis_input.codesize,10h
        mov     (dis_input_t ptr ds:si).octalbasechar,'o'
        mov     (dis_input_t ptr ds:si).tabsize,08h
        mov     (dis_input_t ptr ds:si).__dis_input.cputype,__discpu_intel
        xor     eax,eax
        mov     (dis_input_t ptr ds:si).__dis_input.flags,eax
        mov     (dis_input_t ptr ds:si).flags,eax

        mov     di,offset DISCMD
        call    near ptr getenv
        jne     short @@20
ifdef iscom
        mov     es,[002Ch]
else
        mov     es,psp
        mov     es,es:002Ch
endif
        assume  es:nothing
        mov     si,di
        call    near ptr parseoptions
        push    ds
        pop     es
        assume  es:@data
        jc      exit
@@20:
ifndef iscom
        mov     es,psp
endif
        mov     si,0081h
        call    near ptr parseoptions
ifndef iscom
        push    ds
        pop     es
        assume  es:@data
endif
        jc      exit
        test    dx,dx
        jz      @?
        cmp     bytesleft,-1
        jne     short @@25
        cmp     linesleft,-1
        mov     cx,nocountlen
        mov     dx,offset nocount
        je      short @@printerrstringandexit
@@25:
if @codesize
        db      66h
endif
        mov     word ptr dis_input.__dis_input.getbyte,offset getbytemem
if @codesize
        dw      seg getbytemem
endif
        cmp     disfile,00h
        je      short @@disassemble
if @codesize
        db      66h
endif
        mov     word ptr dis_input.__dis_input.getbyte,offset getbytefile
if @codesize
        dw      seg getbytefile
endif
        mov     bx,0100h
        call    near ptr allocmem
        jc      @@outofmem
        and     bufbytesleft,0000h
        mov     buflen,bx
        mov     bufseg,ax

        mov     ax,3D00h
        mov     dx,offset filename
        int     21h
        mov     cx,erropenfilelen
        mov     dx,offset erropenfile
        jc      short @@printerrstringandexit
        mov     filehandle,ax
        xchg    bx,ax
        cmp     skipheader,00h
        je      short @@dontskipheader
        mov     ah,3Fh
        mov     cx,1Ch
        mov     dx,offset tmpstring
        int     21h
        jnc     short @@30
@@readerror:
        mov     cx,readerrlen
        mov     dx,offset readerrstr
@@printerrstringandexit:
        call    near ptr printerrstring
        mov     al,02h
        jmp     short exit
@@30:
        cmp     ax,cx
        jne     short @@readerror
        mov     ax,word ptr tmpstring
        cmp     ax,'MZ'
        je      short @@exe
        cmp     ax,'ZM'
        mov     cx,notexelen
        mov     dx,offset notexe
        jne     short @@printerrstringandexit
@@exe:
        movzx   eax,word ptr tmpstring+8
        shl     eax,04h
        add     fileofs,eax
@@dontskipheader:
@@disassemble:
if @codesize
        db      66h
endif
        mov     word ptr dis_input.checkoperand,offset stcret
if @codesize
        dw      seg stcret
endif

ifdef debug
        mov     dis_input.__dis_input.eip,offset testcode
        mov     bytesseg,seg testcode
        mov     bytesleft,testcodeend-testcode
  ifdef debug32
        mov     dis_input.__dis_input.codesize,20h
  endif
endif
        testflag printflags,printlabels
        jz      short @@disassemble2
        mov     bx,0FFFFh
        call    near ptr allocmem
        jc      short @@disassemble2
        mov     labelseg,ax
        movzx   eax,ax
        shl     eax,04h
        mov     labelsize,ebx
        mov     labelseglinear,eax
        call    near ptr rememberallcodelabels
if @codesize
        db      66h
endif
        mov     word ptr dis_input.checkoperand,offset printlabel
if @codesize
        dw      seg printlabel
endif
@@disassemble2:
        call    near ptr disassemble
        xor     al,al
exit:
        mov     bx,offset bufseg
        call    near ptr delmem
        mov     bx,offset labelseg
        call    near ptr delmem
        mov     ah,4Ch
        int     21h
@?:
        mov     ah,09h
        mov     dx,offset dishelp
        int     21h
        mov     dx,offset disintro
        int     21h
        jmp     short exit

delmem:
        mov     cx,[bx]
        jcxz    @@delmemretn
        push    es ax
        mov     ah,49h
        mov     es,cx
        int     21h
        pop     ax es
@@delmemretn:
        retn

allocmem:
        mov     ah,48h
        int     21h
        jnc     short @@gotmem
        mov     ah,48h
        int     21h
        jc      short @@allocmemretn
@@gotmem:
        movzx   ebx,bx
        shl     ebx,04h
@@allocmemretn:
        retn

printerrstring:
        mov     ah,40h
        mov     bx,0002h
        int     21h
        retn

        ;
        ;   getenv:near
        ;
        ;   get an evironment string
        ;
        ;   input: _es:di string to find
        ;   output: zf=1=[psp:2C]:di=environment string
        ;           zf=0=NOT FOUND
        ;   registers: di
        ;
proc    getenv near
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        push    ds ax cx si
        call    strlen
ifndef iscom
        mov     ds,psp
        assume  ds:nothing
endif
        mov     ds,[002Ch]
        assume  ds:nothing
        xor     si,si
@@getenvloop:
        push    cx di
        rep cmpsb
        pop     di cx
        je      short @@foundit
        lodsb
        test    al,al
        jnz     $-3
        cmp     [si],al
        jne     short @@getenvloop
        inc     ax
@@foundit:
        mov     di,si
        pop     si cx ax ds
        assume  ds:@data
        retn
endp    getenv

        ;
        ;   parseoptions:near
        ;
        ;   check the cmd line
        ;
proc    parseoptions near
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        xor     dx,dx
@@firstoptionloop:
        lods    byte ptr es:[si]
        call    near ptr @@isspace
        je      short @@firstoptionloop
        call    near ptr @@endofcmd
        je      short @@666
        cmp     al,'/'
        jne     short @@erroption
@@firstoptionloopslash:
        xor     ah,ah
        lods    byte ptr es:[si]
        cmp     al,'-'
        jne     short @@10
        inc     ah
        lods    byte ptr es:[si]
@@10:
        call    near ptr @@endofcmd
        je      short @@erroption
        mov     cx,nfirstoptions
        mov     bx,offset firstoptiontable
        mov     di,offset firstoptiontableptrs
@@firstoptioninnerloop:
        cmp     al,[bx]
        je      short @@secondoption
        inc     bx
        add     di,0004h
        loop    @@firstoptioninnerloop
        jcxz    @@erroption
@@secondoption:
        lods    byte ptr es:[si]
        call    near ptr @@endofcmd
        jne     short @@secondoptionloopstarthere
        mov     bx,[di]
        cmp     byte ptr ds:[bx],00h
        je      short @@secondoptionloopstarthere
        jmp     short @@erroption
@@secondoptionloop:
        lods    byte ptr es:[si]
        call    near ptr @@endofcmd
        je      short @@666
        cmp     al,'/'
        je      short @@firstoptionloopslash
        call    near ptr @@isspace
        je      short @@firstoptionloop
@@secondoptionloopstarthere:
        mov     bx,[di]
        mov     bp,[di+02h]
        movzx   cx,byte ptr ds:[bx]
        jcxz    @@anoption
        inc     bx
@@secondoptioninnerloop:
        cmp     al,[bx]
        je      short @@anoption
        inc     bx
        inc     bp
        inc     bp
        loop    @@secondoptioninnerloop
        jcxz    @@erroption
@@666:
        clc
        retn
@@anoption:
        inc     dx
        push    di dx
ifdef stackfar
        call    word ptr ds:[bp]
else
        call    word ptr ss:[bp]
endif
        pop     dx di
        jnc     short @@secondoptionloop
@@erroption:
        mov     cx,optionerrlen
        mov     dx,offset optionerr
        call    near ptr printerrstring
        stc
        retn
@@endofcmd:
        cmp     al,13
        je      short $+4
        test    al,al
        retn
@@isspace:
        cmp     al,20h
        je      short $+4
        cmp     al,09h
        retn
@pc:                                    ;print cs
        mov     cl,printcs
        jmp     short @@setclearprintflags
@pe:                                    ;print eip
        mov     cl,printeip
        jmp     short @@setclearprintflags
@pb:                                    ;print opcode bytes
        mov     cl,printbytes
        jmp     short @@setclearprintflags
@po:                                    ;print the opcode
        mov     cl,printopcode
        jmp     short @@setclearprintflags
@pl:                                    ;print labels instead of just offsets
        mov     cl,printlabels
@@setclearprintflags:
        test    ah,ah
        jnz     short @@clearprintflagsbit
        or      printflags,cl
        retn
@@clearprintflagsbit:
        not     cl
        and     printflags,cl
        retn

@xPP:
        mov     ecx,__df_prefixinstructions
        jmp     short @@setclear__disflags
@so:
        mov     ecx,__df_showsizeop
        jmp     short @@setclear__disflags
@xs:
        mov     ecx,__df_stringoperands
        jmp     short @@setclear__disflags
@xf:
        mov     ecx,__df_floatasesc
@@setclear__disflags:
        mov     di,offset dis_input.__dis_input.flags
        jmp     short @@setclearflags
@um:
        mov     ecx,df_uppercasemnemonic
        jmp     short @@setcleardisflags
@ur:
        mov     ecx,df_uppercasereg
        jmp     short @@setcleardisflags
@up:
        mov     ecx,df_uppercaseptr
        jmp     short @@setcleardisflags
@ub:
        mov     ecx,df_uppercasebasechar
        jmp     short @@setcleardisflags
@n0:
        mov     ecx,df_msd0
        jmp     short @@setcleardisflags
@na:
        mov     ecx,df_msd0always
        jmp     short @@setcleardisflags
@nb:
        mov     ecx,df_usebasechar
        jmp     short @@setcleardisflags
@nn:
        mov     ecx,df_basecharifneeded
        jmp     short @@setcleardisflags
@nl:
        mov     ecx,df_lowercasedigitchar
        jmp     short @@setcleardisflags
@nf:
        mov     ecx,df_fewdigits
        jmp     short @@setcleardisflags
@sm:
        mov     ecx,df_showsizemem
        jmp     short @@setcleardisflags
@ss:
        mov     ecx,df_showsegmemsize
        jmp     short @@setcleardisflags
@sc:
        mov     ecx,df_commaspace
        jmp     short @@setcleardisflags
@NNd:
        mov     ecx,df_nobracketsdispl
        jmp     short @@setcleardisflags
@NNm:
        mov     ecx,df_nobracketsmem
@@setcleardisflags:
        mov     di,offset dis_input.flags
@@setclearflags:
        test    ah,ah
        jnz     short @@cleardisflags
        or      [di],ecx
        retn
@@cleardisflags:
        not     ecx
        and     [di],ecx
        retn
@NNz:
        mov     ecx,df_nozerodispl
        jmp     short @@setcleardisflags
@NNs:
        mov     ecx,df_noshort
        jmp     short @@setcleardisflags
@NNp:
        mov     ecx,df_noptr
        jmp     short @@setcleardisflags
@NNMM:
        mov     ecx,df_nomemsize
        jmp     short @@setcleardisflags
@jn:
        mov     ecx,df_nearptr
        jmp     short @@setcleardisflags
@jf:
        mov     ecx,df_farptr
        jmp     short @@setcleardisflags
@x1:
        mov     ecx,df_usescale1
        jmp     short @@setcleardisflags
@xr:
        mov     ecx,df_tabafterrep
        jmp     short @@setcleardisflags
@bp:
        mov     ecx,df_ptrinsidebrack
        jmp     short @@setcleardisflags
@bs:
        mov     ecx,df_seginsidebrack
        jmp     short @@setcleardisflags
@od:
        mov     ecx,df_dsdispl
        jmp     short @@setcleardisflags
@om:
        mov     ecx,df_memsegoverride
        jmp     short @@setcleardisflags
@xa:
        mov     ecx,df_attsyntax
        jmp     short @@setcleardisflags
@nc:
        mov     ecx,df_Cnumbers
        jmp     @@setcleardisflags
@NNo:
        mov     ecx,df_noopnamesizeatt
        jmp     @@setcleardisflags
@xb:                                    ;base is binary
        mov     al,10b
        jmp     short @@setbasenumber
@xo:                                    ;base is octal (o is base char)
        mov     al,'o'
        jmp     short @@setoctalbasechar
@xq:                                    ;base is octal (q is base char)
        mov     al,'q'
@@setoctalbasechar:
        mov     dis_input.octalbasechar,al
        mov     al,10o
        jmp     short @@setbasenumber
@xd:                                    ;base is decimal
        mov     al,10d
        jmp     short @@setbasenumber
@xh:                                    ;base is hexadecimal
        mov     al,10h
@@setbasenumber:
        mov     dis_input.numberbase,al
        retn
@xt:                                    ;/xt<N> - set new tabsize
        call    near ptr @@getnumber
        mov     dis_input.tabsize,al
        jc      short @xt666
        cmp     eax,00000020h
        ja      short @xterr
        test    ax,ax                   ;eax[31:16]=0000
        jnz     short @xt666
@xterr:
        mov     cx,tabsizelen
        mov     dx,offset tabsizestr
        call    near ptr printerrstring
        stc
@xt666:
        retn
@xp:                                    ;disassemble this program from memory
        mov     bytesseg,cs
ife @codesize
  ifdef iscom
        mov     dis_input.__dis_input.eip,00000100h
        mov     bytesleft,offset @code:lastcodeofs-100h
  else
        and     dis_input.__dis_input.eip,00000000h
        mov     bytesleft,offset @code:lastcodeofs
  endif
else
        mov     eax,@codeend
        sub     ax,_text
        shl     eax,04h
        and     dis_input.__dis_input.eip,00000000h
        mov     bytesleft,eax
endif
        retn
@ci:                                    ;only intel 8088+ opcodes
        mov     al,__discpu_intel
        jmp     short setcputype
@ca:                                    ;intel 8088+ and AMD opcodes
        mov     al,__discpu_amd
        jmp     short setcputype
@cc:                                    ;intel 8088+ and Cyrix opcodes
        mov     al,__discpu_cyrix
setcputype:
        mov     dis_input.__dis_input.cputype,al
        retn
@dc:                                    ;/dc<N> - set # of bytes to disassemble
        push    offset bytesleft
__getandsavedword:
        call    near ptr @@getnumber
        pop     bx
        mov     [bx],eax
        retn
@dl:                                    ;/dl<N> - set # of lines to disassemble
        push    offset linesleft
        jmp     short __getandsavedword
@do:                                    ;/do<N> - new file offset
        push    offset fileofs
        jmp     short __getandsavedword
@dCC:                                   ;/dC<N> - new CS value (files only)
        push    offset bytesseg
        jmp     short __getandsavedword
@de:                                    ;/de<N> - new EIP value (files only)
        push    offset dis_input.__dis_input.eip
        jmp     short __getandsavedword
@dm:                                    ;/dm<SEG:OFS> - disassemble memory
        mov     ah,':'
if @codesize
        db      66h
        mov     dx,offset ahtob
        dw      seg ahtob
else
        mov     dx,offset ahtob
endif
        call    near ptr @@____getnumber
        mov     bytesseg,ax
        jc      short @@dmretn
        cmp     byte ptr es:[si],':'
        stc
        jne     short @@dmretn
        inc     si
        mov     ah,'/'
        call    near ptr @@____getnumber
        mov     dis_input.__dis_input.eip,eax
@@dmretn:
        retn
@xc:                                    ;/xc<N> - set new opcode start column
        call    near ptr @@getnumber
        mov     opcodestart,ax
        cmp     eax,00000051h
        cmc
        jae     short @@xcretn
        mov     cx,opcodestartlen
        mov     dx,offset opcodestartstr
        call    near ptr printerrstring
        stc
@@xcretn:
        retn
@16:                                    ;disassemble 16-bit code
        mov     al,10h
        jmp     short @@setdis_codesize
@32:                                    ;disassemble 32-bit code
        mov     al,20h
@@setdis_codesize:
        mov     dis_input.__dis_input.codesize,al
        retn
@dx:                                    ;/dx<FILENAME> - disassemble an .exe
        mov     skipheader,01h
@df:                                    ;/df<FILENAME> - disassemble a file
        mov     disfile,01h
        call    near ptr @@getstring
        jc      short @@xcretn
        mov     bx,offset filename

        ;
        ;   @@copystring:near
        ;
        ;   copy something and make an asciiz string
        ;
        ;   input: es:di start of data
        ;          es:si after the last byte to copy
        ;          ds:bx copy to this and then make an asciiz string
        ;   output: cf=0
        ;           si  di
        ;           bx  end of string
        ;   registers: al,bx,di
        ;
@@copystring:
@@copystringloop:
        mov     al,es:[di]
        inc     di
        mov     [bx],al
        inc     bx
        cmp     di,si
        jne     short @@copystringloop
        mov     byte ptr ds:[bx],00h
        retn

        ;
        ;   @@getnumber:near
        ;
        ;   get a number (in ascii) and convert it to binary
        ;
        ;   input: es:si string with options
        ;   output: cf=1=error
        ;           cf=0=ok
        ;             eax value
        ;             es:si advanced past the number
        ;   registers: eax,si,di
        ;
@@getnumber:
        mov     ah,'/'
@@__getnumber:
if @codesize
        db      66h
        mov     dx,offset antob
        dw      seg antob
else
        mov     dx,offset antob
endif
@@____getnumber:
        call    near ptr @@__getstring
        jc      short @@getnumber666
if @datasize
        xor     cl,cl
        xchg    cl,es:[si]
  if @codesize
        db      66h
        push    offset @@getnumberretofs
        dw      seg @@getnumberretofs
        push    edx
        retf
@@getnumberretofs:
  else
        call    dx
  endif
        mov     es:[si],cl
else
        mov     bx,offset tmpstring
        push    bx
        call    near ptr @@copystring
        pop     di
        push    es ds
        pop     es
        assume  es:@data
  if @codesize
        db      66h
        push    offset @@getnumberretofs
        dw      seg @@getnumberretofs
        push    edx
        retf
@@getnumberretofs:
  else
        call    dx
  endif
        pop     es
        assume  es:nothing
endif
@@getnumber666:
        retn

        ;
        ;   @@getstring:near
        ;
        ;   get a string
        ;
        ;   input: es:si string with options (ends in 0 or 13)
        ;   output: cf=1=error
        ;           cf=0=ok
        ;             es:si after the last character
        ;             es:di the first character in the string
        ;           al the last character we got
        ;   registers: al,si,di
        ;
@@getstring:
        mov     ah,'/'
@@__getstring:
@@getstringspaceloop:
        lods    byte ptr es:[si]
        call    near ptr @@isspace
        je      short @@getstringspaceloop
        dec     si
        mov     di,si
@@getstringloop:
        lods    byte ptr es:[si]
        call    near ptr @@isspace
        je      short @@getstringloopend
        call    near ptr @@endofcmd
        je      short @@getstringloopend
        cmp     al,ah
        jne     short @@getstringloop
@@getstringloopend:
        dec     si
        cmp     si,di
        stc
        je      short @@getstring666
        cmc
@@getstring666:
        retn
        assume  es:@data
endp    parseoptions

        ;
        ;   printcsipbytes:near
        ;
        ;   print cs:ip XXXXXXXX    XXX    XX,XX
        ;
        ;   input: _es:di string to print it inside
        ;          _gs:si opcode string
        ;   output: none
        ;   registers: none
        ;
proc    printcsipbytes near
        assume  es:@data,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
if @datasize
        assume  es:nothing
endif
        push    eax
        pop     ax
        pusha
        mov     bp,di
        mov     bx,(10h shl 8) or bighex
        testflag dis_input.flags,df_lowercasedigitchar
        jz      short @@10
        xor     bl,bl
@@10:

ColonAndEIP     equ     1               ;":00401000" instead of "00401000"

        testflag printflags,printcs
        jz      short @@checkip
        movzx   eax,bytesseg
        mov     cx,0004h
        call    __ntoa
        add     di,cx
ife ColonAndEIP
        testflag printflags,printeip
        jz      short @@checkbytes
        mov     al,':'
        stosb
endif
@@checkip:
        testflag printflags,printeip
        jz      short @@checkbytes
if ColonAndEIP
        mov     al,':'
        stosb
endif
        mov     eax,opcodeeip
        mov     cx,0008h
        cmp     dis_input.__dis_input.codesize,20h
        je      short @@20
        movzx   eax,ax
        shr     cx,01h
@@20:
        call    __ntoa
        add     di,cx
@@checkbytes:
        testflag printflags,printbytes
        jz      short @@checkopcode
        testflag printflags,printcs or printeip
        jz      short @@30
        mov     al,20h
        stosb
@@30:
        xor     eax,eax
        mov     cx,0002h
        push    si
        mov     si,offset opcodebytes
@@opcodebytesloop:
        lodsb
        call    __ntoa
        add     di,cx
        cmp     si,opcodebytesptr
        jb      short @@opcodebytesloop
        pop     si
        testflag printflags,printopcode
        jz      short @@666
        mov     al,20h
        stosb
@@checkopcode:
        testflag printflags,printopcode
        jz      short @@666
        mov     cx,di
        sub     cx,bp                   ;length of string
        sub     cx,opcodestart
        inc     cx
        neg     cx
        jle     short @@40              ;just in case
        mov     al,20h
        rep stosb
@@40:
if @datasize
        push    ds gs
        pop     ds
        assume  ds:nothing
endif
        call    strcpy
if @datasize
        pop     ds
        assume  ds:@data
endif
        jmp     short @@dontzero
@@666:
        xor     al,al
        stosb
@@dontzero:
        popa
        push    ax
        pop     eax
        retn
endp    printcsipbytes

        ;
        ;   seektostartinfile:near
        ;
        ;   seek to where we should start disassembling in a file
        ;
proc    seektostartinfile near
        cmp     disfile,00h
        je      short @@dontseek
        mov     ax,4200h
        mov     cx,word ptr fileofs+2
        mov     dx,word ptr fileofs
        mov     bx,filehandle
        int     21h
@@dontseek:
        retn
endp    seektostartinfile

        ;
        ;   rememberallcodelabels:near
        ;
        ;   remembler all code labels
        ;
proc    rememberallcodelabels near
        call    near ptr seektostartinfile
        push    dis_input.__dis_input.eip bytesseg bytesleft\
                linesleft bufbytesleft bufofs buflen
        jmp     short @@starthere
@@opcodeeiploop:
        dec     word ptr (dis_input.__dis_input.eip)+2 ;sub 10000h
        add     byte ptr bytesseg+1,10h ;add 1000h
@@loop:
@@starthere:
        cmp     disfile,00h
        jne     short @@dontdoit
        cmp     word ptr (dis_input.__dis_input.eip)+2,0000h ;greater than 64k?
        jne     short @@opcodeeiploop
@@dontdoit:

        mov     opcodebytesptr,offset opcodebytes
        mov     si,offset dis_input.__dis_input
ifdef debug
  if @datasize
        ;Normalize the ptr so we know that we really have a gs: override
        ;in __dis:proc and not just forgot it (ds: override)
        mov     esi,seg dis_input
        shl     esi,04h
        add     esi,large offset dis_input
        push    si
        shr     esi,04h
        mov     gs,si
        pop     si
        and     si,000Fh
  endif
endif
        call    __dis
ifdef debug
  if @datasize
        push    ds
        pop     gs
  endif
endif
        jc      short @@666
        call    near ptr savelabels
        dec     linesleft
        jnz     short @@loop
@@666:
        pop     buflen bufofs bufbytesleft linesleft\
                bytesleft bytesseg dis_input.__dis_input.eip
        retn
endp    rememberallcodelabels

        ;
        ;   disassemble:near
        ;
        ;   disassemble something
        ;
proc    disassemble near
        assume  es:@data,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        call    near ptr seektostartinfile
        jmp     short @@starthere
@@opcodeeiploop:
        dec     word ptr (dis_input.__dis_input.eip)+2 ;sub 10000h
        add     byte ptr bytesseg+1,10h ;add 1000h
@@loop:
@@starthere:
        cmp     disfile,00h
        jne     short @@dontdoit
        cmp     word ptr (dis_input.__dis_input.eip)+2,0000h ;greater than 64k?
        jne     short @@opcodeeiploop
@@dontdoit:
        mov     opcodebytesptr,offset opcodebytes
        mov     si,offset dis_input
        mov     di,offset disstring
        mov     eax,dis_input.__dis_input.eip
        mov     opcodeeip,eax           ;save start of opcode
        call    near ptr fixofs
        call    near ptr findlabel
        jne     short @@labelnotfound
        push    di
        call    near ptr printlabelname
        mov     ax,':'
        stosw
        pop     di
        call    near ptr @@printasciizstring
        call    near ptr @@printcrlf
        dec     linesleft
        jz      short @@666
@@labelnotfound:
ifdef debug
  if @datasize
        mov     esi,seg dis_input
        shl     esi,04h
        add     esi,large offset dis_input
        push    si
        shr     esi,04h
        mov     gs,si
        pop     si
        and     si,000Fh
  endif
endif
        call    dis
        mov     si,di
        jc      short @@666
        mov     di,offset tmpstring
ifdef debug
  if @datasize
        push    ds
        pop     gs
  endif
endif
        call    near ptr printcsipbytes
@@printstringandcrlf:
        call    near ptr @@printasciizstring
        call    near ptr @@printcrlf
        dec     linesleft
        jnz     short @@loop
@@666:
        retn
@@printasciizstring:
        call    strlen
        mov     ah,40h
        mov     dx,di
        mov     bx,0001h
        int     21h
        retn
@@printcrlf:
        mov     ah,02h
        mov     dl,0Dh
        int     21h
        mov     dl,0Ah
        int     21h
        retn
endp    disassemble

        ;
        ;   fixofs:near
        ;
        ;   fix the offset in eax
        ;
        ;   input: __dis_gs:si __dis_input_t struc
        ;          eax  ofs
        ;   output: eax bytesseg:ofs or ofs32
        ;   registers: eax
        ;
proc    fixofs near
        cmp     (__dis_input_t ptr __dis_gs:si).codesize,20h
        je      short @@666
        push    bytesseg ax
        pop     eax
@@666:
        retn
endp    fixofs

        ;
        ;   iscalljmpjcc:near
        ;
        ;   check if it's near/short call/jmp/jcc
        ;
        ;   input: __dis_gs:bx dis_operand_t struc
        ;   output: zf=1=yes
        ;           zf=0=no
        ;   registers: none
        ;
proc    iscalljmpjcc near
        push    ax
        mov     al,byte ptr (dis_operand_t ptr __dis_gs:bx).flags
        and     al,dop_typemask
        cmp     al,dop_nearofs
        pop     ax
        retn
endp    iscalljmpjcc

        ;
        ;   savelabels:near
        ;
        ;   save all jmp/call/jcc labels
        ;
        ;   input: __dis_gs:si __dis_input_t struc (and relatives)
        ;   output: none
        ;   registers: none
        ;
proc    savelabels near
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        push    bx
        lea     bx,(__dis_input_t ptr __dis_gs:si).opcode.op1
        call    near ptr iscalljmpjcc
        jne     short @@666
        push    eax
        mov     eax,(dis_operand_t ptr __dis_gs:bx).ops.nearptr.ofs
        call    near ptr fixofs
        call    near ptr rememberlabel
        pop     eax
@@666:
        pop     bx
        retn
endp    savelabels

        ;
        ;   rememberlabel:near
        ;
        ;   remember a call/jmp/jcc label
        ;
        ;   input: __dis_gs:si __dis_input_t struc (and relatives)
        ;          __dis_gs:bx dis_operand_t struc
        ;          eax  ofs:seg or ofs32
        ;   output: cf=1=out of memory
        ;           cf=0=inserted
        ;   registers: eax
        ;
proc    rememberlabel near
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        call    near ptr findlabel
        je      short @@retn
        push    es edi
        mov     edi,labelofs
        cmp     labelsize,edi
        jbe     short @@printerr
        add     edi,labelseglinear
        push    di
        shr     edi,04h
        mov     es,di
        pop     di
        and     di,000Fh
        stosd
        add     labelofs,00000004h
@@666:
        pop     edi es
@@retn:
        retn
@@printerr:
        cmp     printedlabelerr,00h
        jne     short @@stc
        mov     printedlabelerr,01h
        push    cx dx bx
        mov     cx,outoflabelslen
        mov     dx,offset outoflabels
        call    near ptr printerrstring
        pop     bx dx cx
@@stc:
        stc
        jc      short @@666
endp    rememberlabel

        ;
        ;   printlabelname:near
        ;
        ;   print a label name
        ;
        ;   input: eax  seg:ofs or ofs32
        ;          _es:di string
        ;   output: di  after the string+asciiz
        ;   registers: eax,di
        ;
proc    printlabelname near
        mov     byte ptr _es:[di],'L'
        inc     di
        push    cx bx
        mov     cx,0008h
        mov     bx,(10h shl 8) or bighex
        call    __ntoa
        add     di,cx
        pop     bx cx
        mov     byte ptr _es:[di],00h
        retn
endp    printlabelname

        ;
        ;   printlabel:procptr
        ;
        ;   print all jmp/call/jcc labels
        ;
        ;   input: __dis_gs:si __dis_input_t struc (and relatives)
        ;          __dis_gs:bx dis_operand_t struc
        ;          di   string to print something in
        ;   output: cf=1=didn't print a thing in di
        ;           cf=0=did print something in di. di=after last char+asciiz
        ;   registers: cf=1=none,cf=0=di
        ;
proc    printlabel procptr
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        call    near ptr iscalljmpjcc
        stc
        jne     short @@666
        push    eax
        mov     eax,(dis_operand_t ptr __dis_gs:bx).ops.nearptr.ofs
        call    near ptr fixofs
        call    near ptr findlabel
        stc
        jne     short @@30
        call    near ptr printlabelname
        clc
@@30:
        pop     eax
@@666:
        ret
endp    printlabel

        ;
        ;   stcret:procptr
        ;
        ;   stc ret
        ;
proc    stcret procptr
        stc
        ret
endp    stcret

        ;
        ;   findlabel:near
        ;
        ;   find a label
        ;
        ;   input: __dis_gs:si __dis_input_t struc (and relatives)
        ;          __dis_gs:bx dis_operand_t struc
        ;          eax  seg:ofs or ofs32
        ;   output: zf=1=found it (eax=seg:ofs or ofs32)
        ;           zf=0=didn't find it
        ;   registers: eax
        ;
proc    findlabel near
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        push    es ecx edx di
        mov     edx,labelofs
        mov     es,labelseg
        xor     di,di
@@findloop:
        mov     ecx,00010000h
        cmp     edx,ecx
        ja      short @@10
        mov     ecx,edx
@@10:
        sub     edx,ecx
        shr     ecx,02h
        jz      short @@not
        repnz scasd
        mov     cx,es
        je      short @@666
        add     ch,10h
        mov     es,cx
        jmp     short @@findloop
@@666:
        pop     di edx ecx es
        retn
@@not:
        inc     cx
        jnz     short @@666
endp    findlabel

        ;
        ;   getbytemem:proc
        ;
        ;   get a byte from memory
        ;
        ;   input: __dis_gs:si __dis_input_t struc
        ;   output: __dis_gs:si.eip is incremented by one
        ;           cf=1=error
        ;           cf=0=ok
        ;             al  byte from mem
        ;   registers: al
        ;
proc    getbytemem procptr
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        sub     bytesleft,00000001h
        jc      short @@666
        push    bx ds ax
        mov     ax,word ptr (__dis_input_t ptr __dis_gs:si+02h).eip
        shl     ax,0Ch
        mov     bx,word ptr (__dis_input_t ptr __dis_gs:si).eip
        add     ax,bytesseg
        mov     ds,ax
        assume  ds:nothing
        pop     ax
__movalbxpopdsincdis_eipetc:
        mov     al,[bx]
        pop     ds
        assume  ds:@data
        inc     (__dis_input_t ptr __dis_gs:si).eip
        mov     bx,opcodebytesptr
        cmp     bx,offset opcodebytesend
        je      short @@dont
        clc
        mov     [bx],al
        inc     opcodebytesptr
@@dont:
        pop     bx
@@666:
        ret
endp    getbytemem

        ;
        ;   getbytefile:proc
        ;
        ;   get a byte from a file
        ;
        ;   input: __dis_gs:si __dis_input_t struc
        ;   output: __dis_gs:si.eip is incremented by one
        ;           cf=1=error
        ;           cf=0=ok
        ;             al  byte from the file
        ;   registers: al
        ;
proc    getbytefile procptr
        assume  es:nothing,cs:@code,ss:@stack,ds:@data,fs:nothing,gs:nothing
        sub     bufbytesleft,0001h
        jc      short @@readsomemore
        inc     bufofs
        push    bx ds
        lds     bx,bufptr
        dec     bx
        jmp     short __movalbxpopdsincdis_eipetc
@@readsomemore:
        push    ecx ax dx bx
        mov     ah,3Fh
        movzx   ecx,buflen
        cmp     ecx,bytesleft
        jb      short @@10
        mov     cx,word ptr bytesleft
@@10:
        xor     dx,dx
        mov     bx,filehandle
        push    ds
        mov     ds,bufseg
        assume  ds:nothing
        int     21h
        pop     ds
        assume  ds:@data
        mov     bufofs,dx
        mov     bufbytesleft,ax
        xchg    cx,ax
        lahf
        sub     bytesleft,ecx
        sahf
        pop     bx dx ax
        jcxz    @@popecxstcret
        pop     ecx
        jnc     short getbytefile
        ret
@@popecxstcret:
        pop     ecx
        stc
        ret
endp    getbytefile
        endcode

ifdef debug
  ifndef debug32
        startcode
  else
    segment _text32 para public 'code32' use32
  endif
        assume  cs:@curseg
        p486
        ideal
testcode:
if 0
  @@modrm       equ     0CAh
else
  ifdef debug32
    @@modrm     equ     <0Dh,78h,56h,34h,12h>
  else
    @@modrm     equ     <0Eh,34h,12h>
  endif
endif

        ;Cyrix Opcodes
        db      0Fh,78h                 ;svdc
        db      0Fh,79h                 ;rsdc
        db      0Fh,7Ah                 ;svldt
        db      0Fh,7Bh                 ;rsldt
        db      0Fh,7Ch                 ;svts
        db      0Fh,7Dh                 ;rsts

        db      0Fh,36h                 ;rdshr
        db      0Fh,37h                 ;wrshr
        db      0Fh,38h                 ;smint
        db      0Fh,50h,@@modrm         ;paveb Pq,Qq
        db      0Fh,51h,@@modrm         ;paddsiw Pq,Qq
        db      0Fh,52h,@@modrm         ;pmagw Pq,Qq
        db      0Fh,54h,@@modrm         ;pdistib Pq,Qq
        db      0Fh,55h,@@modrm         ;psubsiw Pq,Qq
        db      0Fh,58h,@@modrm         ;pmvzb Pq,Qq
        db      0Fh,59h,@@modrm         ;pmulhrw Pq,Qq
        db      0Fh,5Ah,@@modrm         ;pmvnzb Pq,Qq
        db      0Fh,5Bh,@@modrm         ;pmvlzb Pq,Qq
        db      0Fh,5Ch,@@modrm         ;pmvgezb Pq,Qq
        db      0Fh,5Dh,@@modrm         ;pmulhriw Pq,Qq
        db      0Fh,5Eh,@@modrm         ;pmachirw Pq,Qq

        db      90h,90h,90h,90h,90h     ;if we're not disassembling cyrix

        ;AMD Opcodes and 3DNow! opcodes
        db      0Fh,05h                 ;syscall
        db      0Fh,07h                 ;sysret
        db      0Fh,0FFh                ;ud (generate #ud)
        db      0Fh,0Dh,0C0h            ;prefetch
        db      0Fh,0Dh,0C8h            ;prefetchw
        db      0Fh,0Dh,0D0h            ;(actually, this should be memory,
        db      0Fh,0Dh,0D8h            ; not register)
        db      0Fh,0Dh,0E0h
        db      0Fh,0Dh,0E8h
        db      0Fh,0Dh,0F0h
        db      0Fh,0Dh,0F8h
        db      0Fh,0Eh                 ;femms
        n = 00h
        rept    0100h ;;almost all 3DNow! opcodes
        db      0Fh,0Fh,@@modrm,n
        n = n + 1
        endm

        db      90h,90h,90h,90h,90h     ;if we're not disassembling cyrix

        ;Intel opcodes
        db      0Fh,34h                 ;sysenter
        db      0Fh,35h                 ;syscall
        db      0D6h                    ;salc
        db      0F1h                    ;int01
        db      0Fh,04h                 ;loadall (80286)
        db      0Fh,05h                 ;loadall (80286)
        db      0Fh,07h                 ;loadall (80386)
        db      0Fh,10h,@@modrm         ;umov Eb,Gb
        db      0Fh,11h,@@modrm         ;umov Ev,Gv
        db      0Fh,12h,@@modrm         ;umov Gb,Eb
        db      0Fh,13h,@@modrm         ;umov Gv,Ev
        db      0Fh,33h                 ;rdpmc
        db      0Fh,60h,@@modrm         ;punpcklbw Pq,Qd
        db      0Fh,61h,@@modrm         ;punpcklwd Pq,Qd
        db      0Fh,62h,@@modrm         ;punpckldq Pq,Qd
        db      0Fh,63h,@@modrm         ;packsswb Pq,Qq
        db      0Fh,64h,@@modrm         ;pcmpgtb Pq,Qq
        db      0Fh,65h,@@modrm         ;pcmpgtw Pq,Qq
        db      0Fh,66h,@@modrm         ;pcmpgtd Pq,Qq
        db      0Fh,67h,@@modrm         ;packuswb Pq,Qq
        db      0Fh,71h,0D0h,00h        ;psrlw Pq,Ib
        db      0Fh,71h,0E1h,01h        ;psraw Pq,Ib
        db      0Fh,71h,0F2h,02h        ;psllw Pq,Ib
        db      0Fh,72h,0D3h,03h        ;psrld Pq,Ib
        db      0Fh,72h,0E4h,04h        ;psrad Pq,Ib
        db      0Fh,72h,0F5h,05h        ;pslld Pq,Ib
        db      0Fh,73h,0D6h,06h        ;psrlq Pq,Ib
        db      0Fh,73h,0F7h,07h        ;psllq Pq,Ib
        db      0Fh,74h,@@modrm         ;pcmpeqb Pq,Qq
        db      0Fh,75h,@@modrm         ;pcmpeqw Pq,Qq
        db      0Fh,76h,@@modrm         ;pcmpeqd Pq,Qq
        db      0Fh,77h                 ;emms
        db      0Fh,0D1h,@@modrm        ;psrlw Pq,Qq
        db      0Fh,0D2h,@@modrm        ;psrld Pq,Qq
        db      0Fh,0D3h,@@modrm        ;psrlq Pq,Qq
        db      0Fh,0D5h,@@modrm        ;pmullw Pq,Qq
        db      0Fh,0E1h,@@modrm        ;psraw Pq,Qq
        db      0Fh,0E2h,@@modrm        ;psrad Pq,Qq
        db      0Fh,0E5h,@@modrm        ;pmulhw Pq,Qq
        db      0Fh,0F1h,@@modrm        ;psllw Pq,Qq
        db      0Fh,0F2h,@@modrm        ;pslld Pq,Qq
        db      0Fh,0F3h,@@modrm        ;psllq Pq,Qq
        db      0Fh,0F5h,@@modrm        ;pmaddwd Pq,Qq
        db      0Fh,0Bh                 ;ud1
        db      0Fh,40h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,41h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,42h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,43h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,44h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,45h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,46h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,47h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,48h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,49h,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Ah,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Bh,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Ch,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Dh,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Eh,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,4Fh,@@modrm         ;cmovcc Gv,Ev
        db      0Fh,68h,@@modrm         ;punpckhbw Pq,Qq
        db      0Fh,69h,@@modrm         ;punpckhwd Pq,Qq
        db      0Fh,6Ah,@@modrm         ;punpckhdq Pq,Qq
        db      0Fh,6Bh,@@modrm         ;packssdw Pq,Qq
        db      0Fh,6Eh,@@modrm         ;movd Pq,Ed
        db      0Fh,6Fh,@@modrm         ;movq Pq,Qq
        db      0Fh,7Eh,@@modrm         ;movd Ed,Pq
        db      0Fh,7Fh,@@modrm         ;movq Qq,Pq
        db      0Fh,0B9h                ;ud2
        db      0Fh,0D8h,@@modrm        ;psubusb Pq,Qq
        db      0Fh,0D9h,@@modrm        ;psubusw Pq,Qq
        db      0Fh,0DBh,@@modrm        ;pand Pq,Qq
        db      0Fh,0DCh,@@modrm        ;paddusb Pq,Qq
        db      0Fh,0DDh,@@modrm        ;paddusw Pq,Qq
        db      0Fh,0DFh,@@modrm        ;pandn Pq,Qq
        db      0Fh,0E8h,@@modrm        ;psubsb Pq,Qq
        db      0Fh,0E9h,@@modrm        ;psubsw Pq,Qq
        db      0Fh,0EBh,@@modrm        ;por Pq,Qq
        db      0Fh,0ECh,@@modrm        ;paddsb Pq,Qq
        db      0Fh,0EDh,@@modrm        ;paddsw Pq,Qq
        db      0Fh,0EFh,@@modrm        ;pxor Pq,Qq
        db      0Fh,0F8h,@@modrm        ;psubb Pq,Qq
        db      0Fh,0F9h,@@modrm        ;psubw Pq,Qq
        db      0Fh,0FAh,@@modrm        ;psubd Pq,Qq
        db      0Fh,0FCh,@@modrm        ;paddb Pq,Qq
        db      0Fh,0FDh,@@modrm        ;paddw Pq,Qq
        db      0Fh,0FEh,@@modrm        ;paddd Pq,Qq

        db      0Fh,01h,0E0h            ;smsw ax
        db      66h,0Fh,01h,0E0h        ;smsw eax
        db      0C0h,0F0h,02h           ;shl al,immediate
        db      0C1h,0F0h,03h           ;shl ax,immediate
        db      66h,0C1h,0F0h,04h       ;shl eax,immediate
        db      0D0h,0F0h               ;shl al,1
        db      0D1h,0F0h               ;shl ax,1
        db      66h,0D1h,0F0h           ;shl eax,1
        db      0D2h,0F0h               ;shl al,cl
        db      0D3h,0F0h               ;shl ax,cl
        db      66h,0D3h,0F0h           ;shl eax,cl
        db      0F6h,0C8h,01h           ;test al,imm8
        db      0F7h,0C8h,00h,01h       ;test ax,imm16
        db      66h,0F7h,0C8h,00h,00h,00h,01h;test eax,imm32

        call    ax
        call    eax
        jmp     ax
        jmp     eax
        call    word ptr ds:0
        call    dword ptr ds:0
        db      66h
        call    word ptr ds:0
        call    fword ptr ds:0
        jmp     word ptr ds:0
        jmp     dword ptr ds:0
        db      66h
        jmp     word ptr ds:0
        jmp     fword ptr ds:0
        dw      0E0DCh,0E8DCh,0F0DCh,0F8DCh
        dw      0E0DEh,0E8DEh,0F0DEh,0F8DEh

        mov     al,[ecx*8-00000003h]
        mov     al,[edx*8-00000005h]
        mov     al,[ebx*8+00000103h]
        mov     al,[ebp*8+00000105h]

        esc     00h,eax
        fmul    st,st(1)
        fcomp   st(1)
        fcomp   st(6)

        esc     09h,[eax*8]
        fadd    dword ptr gs:[esp+eax*8-80000000h]
        fucom   st(0)
        db      0DFh,0C0h,90h,90h,90h,90h
        esc     09h,[eax*8]
        call    word ptr ds:[large 00000000]
        call    dword ptr ds:[large 00000000]
        db      66h
        call    word ptr ds:[large 00000000]
        call    fword ptr ds:[large 00000000]
        mov     eax,12345678h
        xlat    byte ptr gs:[ebx]
        mov     cx,[ebp+edi*8+0DEADBEEFh]
        mov     cx,[ebp+edi*8+0DEADBEEFh]
        mov     cx,[ebp+edi*8+0BEEFh]
        mov     cx,[ebp+edi*8+0BEEF0000h]
        mov     cx,[ebp+edi*8+00BEEF00h]
        mov     al,[bp+7Bh]
        mov     al,[bp-7Bh]
        mov     al,[bp+7Dh]
        mov     al,[bp-7Dh]
        mov     al,[bp+7FFBh]
        mov     al,[bp-7FFBh]
        mov     al,[bp+7FFDh]
        mov     al,[bp-7FFDh]
        mov     al,[ebp+7FFFFFFBh]
        mov     al,[ebp-7FFFFFFBh]
        mov     al,[ebp+7FFFFFFDh]
        mov     al,[ebp-7FFFFFFDh]
        mov     al,[bp]
        mov     al,0FFh
        mov     al,0FDh
        mov     al,0FBh
        db      66h
        mov     [1234h],gs
        xlatb
        xlat    byte ptr ss:[ebx]
if 01
;        fucom   st(0),st
        fucom   st(0)
        esc     09h,[eax*8]
        esc     19h,[eax]
        esc     1Ch,[12345678h]
        esc     1Eh,[bx]
        esc     29h,[bp]
        esc     2Dh,[esp]
        esc     39h,[ebp]
endif
        mov     cx,[small 0]
        mov     cx,[large 0]
        mov     ax,[bx]
        mov     cx,[ebx]
        mov     ax,[bp+di+0DEADh]
        mov     cx,[ebp+edi*8+0DEADBEEFh]
        mov     ax,[eax*8]
n = 0
        rept 40h
        esc     n,gs:[esp+eax*8+80000000h+n]
        n = n + 1
        endm
n = 0
        rept 40h
        esc     n,ax
        esc     n,cx
        esc     n,dx
        esc     n,bx
        esc     n,sp
        esc     n,bp
        esc     n,si
        esc     n,di
        n = n + 1
        endm

        rep movs byte ptr es:[di],byte ptr fs:[si]
        db      66h
        mov     [1234h],gs
        mov     es:[0000],ax
        mov     cs:[0000],cx
        mov     ss:[0000],dx
        segds
        mov     ds:[0000],bx
        mov     fs:[0000],sp
        mov     gs:[0000],bp
        mov     si,es:[0000]
        mov     di,cs:[0000]
        mov     eax,ss:[0000]
        segds
        mov     ecx,ds:[0000]
        mov     edx,fs:[0000]
        mov     ebx,gs:[0000]

        lock xchg ax,[1234q]
        repnz scasb
        mov     [1234h],cs
        db      66h
        mov     [1234h],gs
        mov     ss,[1234h]
        db      66h
        mov     fs,[1234h]
        setne   cl
        setne   [1234o]
        mov     word ptr ds:[0000],1234h
        call    $+8000h
        jmp     $+8000h
        mov     [si],al
        mov     al,[bp-03]
        mov     al,[bp-05]
        mov     al,[bp+0103h]
        mov     al,[bp+0105h]
        mov     al,[ebp*8-3]
        mov     al,[ebp*8-5]
        mov     al,[ebp*8+00000103h]
        mov     al,[ebp*8+00000105h]
        mov     al,[ebp+0FFFFFFFDh]
        mov     al,[ebp+0FFFFFFFBh]
        mov     al,[ebp+4FFFFFFDh]
        mov     al,[ebp+6FFFFFFBh]

        mov     eax,[eax*2+00000123h]
        mov     ecx,[ecx*2+00000001h]
        mov     edx,[edx*2+00000000h]
        mov     ebx,[ebx]
        mov     esp,[esp]
        mov     ebp,[ebp]
        mov     esi,[esi]
        mov     edi,[edi]

        mov     eax,[ebp*8]
        lea     cx,[eax*4]
        mov     esp,[small 1234h]
        mov     cx,[large 12345678h]
        mov     eax,[ebp*8]
        lea     cx,[eax*4]
        mov     eax,[esp+ebp*8]
        lea     cx,[ecx+eax*4]
        mov     ecx,[esp]
        mov     ecx,[esp+01]
        mov     ecx,[esp+1000h]
        mov     [esi],ss
        mov     ax,[bx+si+01]
        mov     cx,[bx+di+01]
        mov     dx,[bp+si+01]
        mov     bx,[bp+di+01]
        mov     sp,[bp+01]
        mov     bp,[bx+01]
        mov     si,[si+01]
        mov     di,[di+01]
        mov     al,[bp-03]
        mov     al,[bp-05]
        ror     eax,08h
        sub     word ptr ds:[ebx+8FFFFFFDh],8FFBh
        sub     dword ptr ds:[esi+9FFFFFFBh],9FFFFFFDh
        sub     cx,0EF1Bh
        sub     word ptr ds:[321],001Dh
        sub     ecx,00ABh
        sub     dword ptr ds:[ecx],000000ADh
        sub     ebx,0FFFFFFFDh
        sub     ebp,0FFFFFFFBh
        mov     [8000h],al
        mov     [0A000h],al
        mov     [0800h],al
        mov     [0A00h],al
        mov     [0080h],al
        mov     [00A0h],al
        mov     [0008h],al
        mov     [000Ah],al
        call    large far ptr 1234h:56789ABCh
        call    small far ptr 8888h:7777h
        movsx   ecx,byte ptr gs:[0000h]
        movsx   esi,word ptr fs:[1234h]

        mov     eax,cr0
        mov     cr2,ecx
        mov     edx,dr1
        mov     dr7,ebx
        mov     esp,tr3
        mov     tr6,ebp
        mov     esi,cr0
        mov     cr3,edi
        or      ecx,12345678h
        lar     cx,dx
        imul    sp,[bx+1234h]
        bsr     edi,[0000]
        movsx   sp,al
        movzx   edi,byte ptr ss:[esi*2+00000000]
        movsx   esp,sp
        movzx   edi,word ptr ss:[esi*2+00000000]
        rol     word ptr ds:[0000h],01h
        shl     eax,01h
        rcr     word ptr ds:[esp],cl
        sar     edx,cl
        mov     ecx,12345678h
        or      eax,12345678h
        test    eax,12345678h
        in      ax,21h
        in      eax,21h
        mov     ah,20h
        mov     bh,21h
        add     ecx,ecx
        cmp     [0000h],sp
        cmpxchg [0000h],bp
        bt      [0000h],esi
        xadd    esp,ebp
        db      0Fh,5Bh
        db      0Fh,72h
        rol     dh,01h
        shr     byte ptr fs:[0000h],01h
        rcr     cl,cl
        sar     byte ptr gs:[0000h],cl
        mov     ax,cs
        mov     [esp],ss
        mov     fs,cx
        mov     gs,[bp]
        sbb     cl,ss:[0000h]
        xor     ah,dh
        out     20h,eax
        out     20h,ax
        out     20h,al
        add     al,12h
        in      al,21h
        or      al,0Fh
        and     [0000],dl
        cmpxchg [0000],dh
        mov     al,[0000]
        mov     ax,[0000]
        mov     eax,[0000]
        mov     [0000],al
        mov     [0000],ax
        mov     [0000],eax
        les     eax,[0000]
        lfs     sp,[esp+ebp]
        bound   esp,[0000]
        lea     sp,[bp+si]
        mov     byte ptr ds:[bx],12h
        rcl     byte ptr ds:[0000],02h
        test    byte ptr ds:[esi],21h
        add     dword ptr ds:[esp],-2
        xor     cx,-3
        xchg    sp,ax
        xchg    edi,eax
        rol     ecx,10h
        btc     esp,03h
        mov     word ptr ds:[bx],0000h
        mov     dword ptr ds:[esp+ebp],0BADCAFEh
        in      al,dx
        in      ax,dx
        in      eax,dx
        out     dx,al
        out     dx,ax
        out     dx,eax
        jmp     $+8000h
        jmp     far ptr 1234h:5678h
        call    $+8000h
        call    far ptr 1234h:5678h
        aam
        db      0D4h,21h
        aad
        db      0D5h,10h
        int     03
        sgdt    [0000]
        push    small es
        push    large cs
        push    small ss
        push    large ds
        push    small fs
        push    large gs
        pop     small gs
        pop     large fs
        pop     small ds
        pop     large ss
        pop     small es
        retf    1234h
        retn    1234h
        int     21h
        pop     dword ptr ds:[bx]
        jmp     word ptr ds:[0000]
        push    word ptr ss:[edi]
        not     byte ptr ds:[0000]
        inc     bh
        idiv    ch
        call    fword ptr ds:[0000]
        jmp     dword ptr ds:[0000]
        setp    [0000]
        sldt    [0000]
        verr    [0000]
        inc     bp
        inc     esp
        dec     eax
        dec     si
        push    cx
        push    edi
        pop     dx
        pop     ebx
        bswap   eax
        bswap   sp
        push    small 1234h
        push    large 12345678h
        jo      $+8000h
        call    $+8000h
        jmp     $+8000h
        push    small -1
        push    large -3
        db      66h
        loopne  $-1
        loopde  $
        loop    $
        jecxz   $
        jmp     $
        je      $
        cbw
        cwde
        cwd
        cdq
        pusha
        pushad
        popad
        popa
        pushf
        pushfd
        popfd
        popf
        enter   0000h,00h
        enterd  0000h,00h
        db      66h
        enter   0000h,00h
        leaved
        leave
        iret
        iretd
        retn
        retf
        xlatb
        xlat    byte ptr gs:[bx]
        xlat    byte ptr ss:[ebx]
        db      0Fh,0C7h,38h
        rep ins byte ptr es:[di],dx
        rep ins word ptr es:[di],dx
        rep ins dword ptr es:[di],dx
        rep ins byte ptr es:[edi],dx
        rep ins word ptr es:[edi],dx
        rep ins dword ptr es:[edi],dx
        rep outs dx,byte ptr es:[si]
        rep outs dx,word ptr cs:[si]
        rep outs dx,dword ptr ss:[si]
        rep outs dx,byte ptr es:[esi]
        rep outs dx,word ptr cs:[esi]
        rep outs dx,dword ptr ss:[esi]
        rep movs byte ptr es:[di],byte ptr fs:[si]
        rep movs word ptr es:[di],word ptr gs:[si]
        rep movs dword ptr es:[di],dword ptr es:[si]
        rep movs byte ptr es:[edi],byte ptr fs:[esi]
        rep movs word ptr es:[edi],word ptr gs:[esi]
        rep movs dword ptr es:[edi],dword ptr es:[esi]
        rep cmps byte ptr es:[di],byte ptr es:[si]      ;tasm bug: must use
        rep cmps word ptr es:[di],word ptr es:[si]      ; es:si
        rep cmps dword ptr es:[di],dword ptr es:[si]
        rep cmps byte ptr es:[edi],byte ptr es:[esi]
        rep cmps word ptr es:[edi],word ptr es:[esi]
        rep cmps dword ptr es:[edi],dword ptr es:[esi]
        rep stos byte ptr es:[di]
        rep stos word ptr es:[di]
        rep stos dword ptr es:[di]
        rep stos byte ptr es:[edi]
        rep stos word ptr es:[edi]
        rep stos dword ptr es:[edi]
        rep lods byte ptr es:[si]
        rep lods word ptr cs:[si]
        rep lods dword ptr ss:[si]
        rep lods byte ptr es:[esi]
        rep lods word ptr cs:[esi]
        rep lods dword ptr ss:[esi]
        rep scas byte ptr es:[di]
        rep scas word ptr es:[di]
        rep scas dword ptr es:[di]
        rep scas byte ptr es:[edi]
        rep scas word ptr es:[edi]
        rep scas dword ptr es:[edi]
        imul    eax,[0000],12345678h
        imul    cx,dx,1234h
        imul    sp,[ebp],-3
        imul    bp,[bx],-5
        shld    [0000],esi,02h
        shrd    ax,dx,04h
        shld    [0000],esp,04h
        shrd    cx,bx,08h
        shld    edx,eax,cl
        shrd    [1234h],esp,cl
        db      80h,00h,90h
        db      82h,00h,90h
        test    cx,1234h
        not     sp
        db      0FFh,38h
testcodeend:
  ifndef debug32
        endcode
  else
    ends _text32
  endif
endif

ifndef iscom
segment __lastone para public '__lastone' use16
label   __lastofs word
ends    __lastone
endif

        end     @code:start
