	   PAGE    80,132 ;
	   TITLE DEBUASM.ASM
;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      All Rights Reserved.
; */
; Code for the UASSEMble command in the debugger

	    IF1
		%OUT COMPONENT=DEBUG, MODULE=DEBUASM
	    ENDIF
.XLIST
.XCREF
	   include version.inc		; cas -- missing equates
	   INCLUDE DOSSYM.INC
           INCLUDE debug.inc
.CREF
.LIST
CODE	   SEGMENT PUBLIC BYTE
CODE	   ENDS

CONST	   SEGMENT PUBLIC BYTE
	   EXTRN SYNERR_PTR:BYTE,UNASSEM_LN_PTR:WORD
	   EXTRN NSEG:WORD,SISAVE:WORD,BPSAVE:WORD,DISAVE:WORD
	   EXTRN BXSAVE:WORD,DSSAVE:WORD,ESSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD
	   EXTRN SSSAVE:WORD,CXSAVE:WORD,SPSAVE:WORD,FLSAVE:WORD
	   EXTRN DISTAB:WORD,SHFTAB:WORD,IMMTAB:WORD,GRP1TAB:WORD,GRP2TAB:WORD
	   EXTRN DBMN:BYTE,ESCMN:BYTE,DISPB:WORD,STACK:BYTE,REG8:BYTE
	   EXTRN REG16:BYTE,SREG:BYTE,SIZ8:BYTE,SEGTAB:WORD,M8087_TAB:BYTE
	   EXTRN FI_TAB:BYTE,SIZE_TAB:BYTE,MD9_TAB:BYTE,MD9_TAB2:BYTE
	   EXTRN MDB_TAB:BYTE,MDB_TAB2:BYTE,MDD_TAB:BYTE,MDD_TAB2:BYTE
	   EXTRN MDF_TAB:BYTE
CONST	   ENDS

CSTACK	   SEGMENT STACK
CSTACK	   ENDS

DATA	   SEGMENT PUBLIC BYTE
	   EXTRN DISADD:BYTE,DISCNT:WORD,BYTCNT:BYTE,TEMP:BYTE,AWORD:BYTE
	   EXTRN MIDFLD:BYTE,MODE:BYTE,REGMEM:BYTE,OPCODE:WORD,OPBUF:BYTE
	   EXTRN INDEX:WORD,ARG_BUF:BYTE,ARG_BUF_PTR:BYTE,ARG_BUF_INDEX:WORD
	   EXTRN OPBUF:BYTE,OPCODE:WORD
DATA	   ENDS

DG	   GROUP CODE,CONST,CSTACK,DATA

CODE	   SEGMENT PUBLIC BYTE
	   ASSUME CS:DG,DS:DG,ES:DG,SS:DG

	   PUBLIC UNASSEM
	   PUBLIC DISASLN,MEMIMM,JMPCALL,SIGNIMM,ALUFROMREG,WORDTOALU
	   PUBLIC GRP2,PREFIX,OUTVARW,GRP1,SSPRE,MOVSEGTO,DSPRE,SHIFT
	   PUBLIC ESPRE,IMMED,CSPRE,OUTVARB,CHK10,ACCIMM,INT3,INVARB
	   PUBLIC MOVSEGFROM,LOADACC,OUTFIXB,XCHGAX,REGIMMW,SHORTJMP
	   PUBLIC SAV8,M8087,M8087_DB,M8087_DF,M8087_D9,M8087_DD
	   PUBLIC SAV16,SAVHEX,INFIXW,REGIMMB,OUTFIXW,SHIFTV,LONGJMP
	   PUBLIC INVARW,STOREACC,INFIXB,NOOPERANDS,ALUTOREG
	   PUBLIC SEGOP,REGOP,GETADDR

	   EXTRN CRLF:NEAR,BLANK:NEAR,TAB:NEAR,STD_PRINTF:NEAR
	   EXTRN HEX:NEAR,DEFAULT:NEAR,OUTSI:NEAR,OUTDI:NEAR
	   EXTRN HEX_ADDRESS_ONLY:NEAR

UNASSEM:
	   MOV	BP,[CSSAVE]		; Default code segment
	   MOV	DI,OFFSET DG:DISADD	; Default address
	   MOV	CX,DISPB		; Default length
	   SHR	CX,1
	   SHR	CX,1
	   CALL DEFAULT
	   MOV	WORD PTR [DISADD],DX	; Displacement of disassembly
	   MOV	WORD PTR [DISADD+2],AX	; Segment
	   MOV	WORD PTR [DISCNT],CX	; No. of bytes (but whole instructions)
DISLP:
	   CALL DISASLN 		; Disassemble one line
	   CALL CRLF
	   TEST [DISCNT],-1		; See if we've used up the range
	   JNZ	DISLP
	   RET

GOTDIS:
	   PUSH DS			; RE-GET LAST BYTE
	   PUSH SI
	   LDS	SI,DWORD PTR [DISADD]
	   MOV	AL,[SI-1]
	   POP	SI
	   POP	DS
	   RET

GETDIS:
	   PUSH DS
	   LDS	SI,DWORD PTR [DISADD]
	   LODSB			; Get the next byte of code
	   POP	DS
	   MOV	WORD PTR [DISADD],SI	; Update pointer
	   PUSH AX
	   PUSH DI
	   MOV	DI,[ARG_BUF_INDEX]
	   CALL HEX			; Display each code byte
	   MOV	[ARG_BUF_INDEX],DI
	   POP	DI
	   MOV	SI,[DISCNT]
	   OR	SI,SI			; Check if range exhausted
	   JZ	ENDRNG			; If so, don't wrap around
	   DEC	SI			; Count off the bytes
	   MOV	[DISCNT],SI
ENDRNG:
	   INC	BYTE PTR[BYTCNT]	; Keep track of no. of bytes per line
	   POP	AX
	   RET

DSPRE:
	   INC	BYTE PTR [NSEG+1]
SSPRE:
	   INC	BYTE PTR [NSEG+1]
CSPRE:
	   INC	BYTE PTR [NSEG+1]
ESPRE:
	   INC	BYTE PTR [NSEG+1]

PREFIX:
	   POP	BX			; Dump off return address
	   CALL FINLN
	   CALL CRLF
DISASLN:
	   PUSH DS
	   LDS	SI,DWORD PTR [DISADD]
	   CALL OUTSI			; Show disassembly address
	   POP	DS
	   CALL HEX_ADDRESS_ONLY
DISASLN1:
	   MOV	BYTE PTR [BYTCNT],0	; Count of code bytes per line
; Fill overflow area with zeros
	   MOV	DI,OFFSET DG:OPBUF
	   MOV	CX,50
	   MOV	AL,0
	   REP	STOSB
; fill buffer with spaces
	   MOV	DI,OFFSET DG:OPBUF
	   MOV	CX,OPBUFLEN
	   MOV	AL," "
	   REP	STOSB
	   MOV	DI,OFFSET DG:ARG_BUF
	   MOV	[ARG_BUF_INDEX],DI
	   CALL GETDIS			; Get opcode
	   MOV	DI,[ARG_BUF_INDEX]
	   MOV	AH,0
	   MOV	BX,AX
	   AND	AL,1			; Mask to "W" bit
	   MOV	[AWORD],AL
	   MOV	AL,BL			; Restore opcode
	   SHL	BX,1
	   SHL	BX,1			; Multiply opcode by 4
	   ADD	BX,OFFSET DG:DISTAB
	   MOV	DX,[BX] 		; Get pointer to mnemonic from table
	   MOV	[OPCODE],DX
	   MOV	[ARG_BUF_INDEX],DI
	   MOV	DI,OFFSET DG:OPBUF
	   CALL WORD PTR [BX+2]
FINLN:
	   MOV	AH,[BYTCNT]		; See how many bytes in this instruction
	   ADD	AH,AH			; Each uses two characters
	   MOV	AL,14			; Amount of space we want to use
	   SUB	AL,AH			; See how many fill characters needed
	   CBW
	   XCHG CX,AX			; Parameter for TAB needed in CX
	   MOV	DI,[ARG_BUF_INDEX]
	   CALL TAB
	   MOV	SI,[OPCODE]
	   OR	SI,SI
	   JZ	GET_TAB
GET_OPCODE:
	   LODSB
	   OR	AL,AL
	   JZ	GET_TAB
	   STOSB
	   JMP	GET_OPCODE

GET_TAB:
	   MOV	AL,9
	   STOSB
	   MOV	BYTE PTR [DI],0 	; nul terminate address buffer
	   MOV	DX,OFFSET DG:UNASSEM_LN_PTR
	   CALL STD_PRINTF
	   RET

GETMODE:
	   CALL GETDIS			; Get the address mode byte
	   MOV	AH,AL
	   AND	AL,7			; Mask to "r/m" field
	   MOV	[REGMEM],AL
	   SHR	AH,1
	   SHR	AH,1
	   SHR	AH,1
	   MOV	AL,AH
	   AND	AL,7			; Mask to center 3-bit field
	   MOV	[MIDFLD],AL
	   SHR	AH,1
	   SHR	AH,1
	   SHR	AH,1
	   MOV	[MODE],AH		; Leaving 2-bit "MOD" field
	   RET

IMMED:
	   MOV	BX,OFFSET DG:IMMTAB
	   CALL GETMNE
FINIMM:
	   CALL TESTREG
	   JMP	SHORT IMM

MEMIMM:
	   CALL GETMODE
	   JMP	SHORT FINIMM

ACCIMM:
	   XOR	AL,AL
IMM1:
	   CALL SAVREG
IMM:
	   MOV	AL,","
	   STOSB
	   TEST BYTE PTR [AWORD],-1
	   JNZ	SAV16
SAV8:
	   CALL GETDIS
	   JMP	SHORT SAVHEX

LONGJMP:
	   PUSH DI
	   MOV	DI,OFFSET DG:TEMP
	   CALL SAV16
	   POP	DI
	   CALL SAV16
	   MOV	AL,":"
	   STOSB
	   MOV	SI,OFFSET DG:TEMP
	   MOV	CX,4
MOVDIG:
	   LODSB
	   STOSB
	   LOOP MOVDIG
	   RET

SAV16:
	   CALL GETDIS			; Get low byte
	   MOV	DL,AL
	   CALL GETDIS			; Get high byte
	   MOV	DH,AL
	   CALL SAVHEX			; Convert and store high byte
	   MOV	AL,DL
SAVHEX:
	   MOV	AH,AL
	   SHR	AL,1
	   SHR	AL,1
	   SHR	AL,1
	   SHR	AL,1
	   CALL SAVDIG
	   MOV	AL,AH
SAVDIG:
	   AND	AL,0FH
	   ADD	AL,90H
	   DAA
	   ADC	AL,40H
	   DAA
	   STOSB
	   RET

CHK10:
	   CALL GETDIS
	   CMP	AL,10
	   JNZ	SAVHEX
	   RET

SIGNIMM:
	   MOV	BX,OFFSET DG:IMMTAB
	   CALL GETMNE
	   CALL TESTREG
	   MOV	AL,","
	   STOSB
SAVD8:
	   CALL GETDIS			; Get signed 8-bit number
	   CBW
	   MOV	DX,AX			; Save true 16-bit value in DX
	   MOV	AH,AL
	   MOV	AL,"+"
	   OR	AH,AH
;	JZ	NOSIGN
	   JNS	POSITIV 		; OK if positive
	   MOV	AL,"-"
	   NEG	AH			; Get magnitude if negative
POSITIV:
	   STOSB
; NOSIGN:
	   MOV	AL,AH
	   JMP	SHORT SAVHEX

ALUFROMREG:
	   CALL GETADDR
	   MOV	AL,","
	   STOSB
REGFLD:
	   MOV	AL,[MIDFLD]
SAVREG:
	   MOV	SI,OFFSET DG:REG8
	   CMP	BYTE PTR [AWORD],1
	   JNE	FNDREG
SAVREG16:
	   MOV	SI,OFFSET DG:REG16
FNDREG:
	   CBW
	   ADD	SI,AX
	   ADD	SI,AX
	   MOVSW
	   RET

SEGOP:
	   SHR	AL,1
	   SHR	AL,1
	   SHR	AL,1
SAVSEG:
	   AND	AL,3
	   MOV	SI,OFFSET DG:SREG
	   JMP	SHORT FNDREG

REGOP:
	   AND	AL,7
	   JMP	SHORT SAVREG16

MOVSEGTO:
	   MOV	BYTE PTR [AWORD],1
	   CALL GETADDR
	   MOV	AL,","
	   STOSB
	   MOV	AL,[MIDFLD]
	   JMP	SHORT SAVSEG

MOVSEGFROM:
	   CALL GETMODE
	   CALL SAVSEG
	   MOV	BYTE PTR [AWORD],1
	   JMP	SHORT MEMOP2

GETADDR:
	   CALL GETMODE
	   JMP	SHORT ADDRMOD

WORDTOALU:
	   MOV	BYTE PTR [AWORD],1
ALUTOREG:
	   CALL GETMODE
	   CALL REGFLD
MEMOP2:
	   MOV	AL,","
	   STOSB
ADDRMOD:
	   CMP	BYTE PTR [MODE],3
	   MOV	AL,[REGMEM]
	   JE	SAVREG
	   XOR	BX,BX
	   MOV	BYTE PTR [NSEG],3
	   MOV	BYTE PTR [DI],"["
	   INC	DI
	   CMP	AL,6
	   JNE	NODRCT
	   CMP	BYTE PTR [MODE],0
	   JE	DIRECT			; Mode=0 and R/M=6 means direct addr.
NODRCT:
	   MOV	DL,AL
	   CMP	AL,1
	   JBE	USEBX
	   CMP	AL,7
	   JE	USEBX
	   CMP	AL,3
	   JBE	USEBP
	   CMP	AL,6
	   JNE	CHKPLS
USEBP:
	   MOV	BX,[BPSAVE]
	   MOV	BYTE PTR [NSEG],2	; Change default to Stack Segment
	   MOV	AX,BPREG
SAVBASE:
	   STOSW
CHKPLS:
	   CMP	DL,4
	   JAE	NOPLUS
	   MOV	AL,"+"
	   STOSB
NOPLUS:
	   CMP	DL,6
	   JAE	DOMODE			; No index register
	   AND	DL,1			; Even for SI, odd for DI
	   JZ	USESI
	   ADD	BX,[DISAVE]
	   MOV	AX,DIREG
SAVINDX:
	   STOSW
DOMODE:
	   MOV	AL,[MODE]
	   OR	AL,AL
	   JZ	CLOSADD 		; If no displacement, then done
	   CMP	AL,2
	   JZ	ADDDIR
	   CALL SAVD8			; Signed 8-bit displacement
ADDCLOS:
	   ADD	BX,DX
CLOSADD:
	   MOV	AL,"]"
	   STOSB
	   MOV	[INDEX],BX
NOOPERANDS:
	   RET

ADDDIR:
	   MOV	AL,"+"
	   STOSB
DIRECT:
	   CALL SAV16
	   JMP	SHORT ADDCLOS

USEBX:
	   MOV	BX,[BXSAVE]
	   MOV	AX,BXREG
	   JMP	SHORT SAVBASE

USESI:
	   ADD	BX,[SISAVE]
	   MOV	AX,SIREG
	   JMP	SHORT SAVINDX

SHORTJMP:
	   CALL GETDIS
	   CBW
	   ADD	AX,WORD PTR [DISADD]
	   XCHG DX,AX
SAVJMP:
	   MOV	AL,DH
	   CALL SAVHEX
	   MOV	AL,DL
	   JMP	SAVHEX

JMPCALL:
	   CALL GETDIS
	   MOV	DL,AL
	   CALL GETDIS
	   MOV	DH,AL
	   ADD	DX,WORD PTR [DISADD]
	   JMP	SHORT SAVJMP

XCHGAX:
	   AND	AL,7
	   CALL SAVREG16
	   MOV	AL,","
	   STOSB
	   XOR	AL,AL
	   JMP	SAVREG16

LOADACC:
	   XOR	AL,AL
	   CALL SAVREG
	   MOV	AL,","
	   STOSB
MEMDIR:
	   MOV	AL,"["
	   STOSB
	   XOR	BX,BX
	   MOV	BYTE PTR [NSEG],3
	   JMP	DIRECT

STOREACC:
	   CALL MEMDIR
	   MOV	AL,","
	   STOSB
	   XOR	AL,AL
	   JMP	SAVREG

REGIMMB:
	   MOV	BYTE PTR [AWORD],0
	   JMP	SHORT REGIMM

REGIMMW:
	   MOV	BYTE PTR [AWORD],1
REGIMM:
	   AND	AL,7
	   JMP	IMM1

INT3:
	   MOV	BYTE PTR [DI],"3"
	   INC	DI
	   RET

;  8087 instructions whose first byte is 0dfh
M8087_DF:
	   CALL GET64F
	   JZ	ISDD3
	   MOV	SI,OFFSET DG:MDF_TAB
	   JMP	short NODB3

;  8087 instructions whose first byte is 0ddh
M8087_DD:
	   CALL GET64F
	   JZ	ISDD3
	   MOV	SI,OFFSET DG:MDD_TAB
	   JMP	short NOD93

ISDD3:
	   MOV	AL,DL
	   TEST AL,100B
	   JZ	ISSTI
	   JMP	ESC0

ISSTI:
	   AND	AL,11B
	   MOV	SI,OFFSET DG:MDD_TAB2
	   MOV	CL,AL
	   CALL MOVBYT
	   JMP	short PUTRST

;  8087 instructions whose first byte is 0dbh
M8087_DB:
	   CALL GET64F
	   JZ	ISDB3
	   MOV	SI,OFFSET DG:MDB_TAB
NODB3:
	   CALL PUTOP
	   CALL PUTSIZE
	   JMP	ADDRMOD

ISDB3:
	   MOV	AL,DL
	   TEST AL,100B
	   JNZ	ISDBIG
ESC0V:
	   JMP	ESC0

ISDBIG:
	   CALL GOTDIS
	   AND	AL,11111B
	   CMP	AL,4
	   JAE	ESC0V
	   MOV	SI,OFFSET DG:MDB_TAB2
	   JMP	short DOBIG

;  8087 instructions whose first byte is 0d9h
M8087_D9:
	   CALL GET64F
	   JZ	ISD93

	   MOV	SI,OFFSET DG:MD9_TAB
NOD93:
	   CALL PUTOP
	   AND	AL,111B
	   CMP	AL,3
	   JA	NOSHO
	   MOV	AL,DL
	   CALL PUTSIZE
NOSHO:
	   JMP	ADDRMOD

ISD93:
	   MOV	AL,DL
	   TEST AL,100B
	   JNZ	ISD9BIG
	   AND	AL,111B
	   OR	AL,AL
	   JNZ	NOTFLD
	   MOV	AX,"DL"
	   STOSW
	   JMP	SHORT PUTRST

NOTFLD:
	   CMP	AL,1
	   JNZ	NOTFXCH
	   MOV	AX,"CX"
	   STOSW
	   MOV	AL,"H"
	   JMP	SHORT PUTRST1

NOTFXCH:
	   CMP	AL,3
	   JNZ	NOTFSTP
	   MOV	AX,"TS"
	   STOSW
	   MOV	AL,"P"
PUTRST1:
	   STOSB
PUTRST:
	   MOV	AL,9
	   STOSB
	   JMP	short PUTST0

NOTFSTP:
	   CALL GOTDIS
	   CMP	AL,11010000B		; CHECK FOR FNOP
	   JZ	GOTFNOP
	   JMP	ESC0

GOTFNOP:
	   MOV	AX,"ON"
	   STOSW
	   MOV	AL,"P"
	   STOSB
	   RET

ISD9BIG:
	   CALL GOTDIS			; GET THE MODE BYTE
	   MOV	SI,OFFSET DG:MD9_TAB2
DOBIG:
	   AND	AL,11111B
	   MOV	CL,AL
	   JMP	MOVBYT

; entry point for the remaining 8087 instructions
M8087:
	   CALL GET64
	   CALL PUTFI			; PUT FIRST PART OF OPCODE
	   MOV	AL,DL
	   CMP	BYTE PTR [MODE],11B	; CHECK FOR REGISTER MODE
	   JZ	MODEIS3
	   CALL PUTMN			; PUT MIDDLE PART OF OPCODE
NO3:
	   MOV	AL,9			; OUTPUT A TAB
	   STOSB
	   MOV	AL,DL
	   CALL PUTSIZE 		; OUTPUT THE OPERAND SIZE
	   JMP	ADDRMOD

MODEIS3:
	   TEST AL,100000B		; D BIT SET?
	   JZ	MPUT			; NOPE...
	   TEST AL,000100B		; FDIV OR FSUB?
	   JZ	MPUT			; NOPE...
	   XOR	AL,1			; REVERSE SENSE OF R
	   MOV	DL,AL			; SAVE CHANGE
MPUT:
	   CALL PUTMN			; PUT MIDDLE PART OF OPCODE
	   MOV	AL,DL
	   TEST AL,010000B
	   JZ	NOPSH
	   MOV	AL,"P"
	   STOSB
NOPSH:
	   MOV	AL,9
	   STOSB
	   MOV	AL,DL
	   AND	AL,00000111B
	   CMP	AL,2			; FCOM
	   JZ	PUTST0
	   CMP	AL,3			; FCOMP
	   JZ	PUTST0
	   MOV	AL,DL
	   TEST AL,100000B
	   JZ	PUTSTST0

; output 8087 registers in the form st(n),st
PUTST0ST:
	   CALL PUTST0
	   MOV	AL,','
ISCOMP:
	   STOSB

PUTST:
	   MOV	AX,"TS"
	   STOSW
	   RET

; output 8087 registers in the form st,st(n)
PUTSTST0:
	   CALL PUTST
	   MOV	AL,','
	   STOSB

PUTST0:
	   CALL PUTST
	   MOV	AL,"("
	   STOSB
	   MOV	AL,[REGMEM]
	   ADD	AL,"0"
	   STOSB
	   MOV	AL,")"
	   STOSB
	   RET

; output an 8087 mnemonic
PUTMN:
	   MOV	SI,OFFSET DG:M8087_TAB
	   MOV	CL,AL
	   AND	CL,00000111B
	   JMP	SHORT MOVBYT

; output either 'FI' or 'F' for first byte of opcode
PUTFI:
	   MOV	SI,OFFSET DG:FI_TAB
	   JMP	SHORT PUTFI2

; output size (dword, tbyte, etc.)
PUTSIZE:
	   MOV	SI,OFFSET DG:SIZE_TAB
PUTFI2:
	   CMP	BYTE PTR [MODE],11B	; check if 8087 register
	   JNZ	PUTFI3
	   AND	AL,111000B		; LOOK FOR INVALID FORM OF 0DAH OPERANDS
	   CMP	AL,010000B
	JZ	ESC0PJ
	   MOV	AL,DL
	   CMP	AL,110011B		; FCOMPP
	   JNZ	GOFI
	   CMP	BYTE PTR [REGMEM],1
	JZ	GOFI
ESC0PJ:
	jmp	short ESC0P		; we could've reached without a
;					; double branch here, but we needed
;					; a bridge for ESC0PJ
GOFI:
	   XOR	CL,CL
	   JMP	SHORT MOVBYT

;  Look for qword
PUTFI3:
	   CMP	AL,111101B
	   JZ	GOTQU
	   CMP	AL,111111B
	   JNZ	NOTQU
GOTQU:
	   MOV	CL,2
	   JMP	SHORT MOVBYT

;  look for tbyte
NOTQU:
	   CMP	AL,011101B
	   JZ	GOTTB
	   CMP	AL,111100B
	   JZ	GOTTB
	   CMP	AL,111110B
	   JZ	GOTTB
	   CMP	AL,011111B
	   JNZ	NOTTB
GOTTB:
	   MOV	CL,5
	   JMP	SHORT MOVBYT

NOTTB:
	   MOV	CL,4
	   SHR	AL,CL
	   MOV	CL,AL
; SI POINTS TO A TABLE OF TEXT SEPARATED BY "$"
; CL = WHICH ELEMENT IN THE TABLE YOU WISH TO COPY TO [DI]
MOVBYT:
	   PUSH AX
	   INC	CL
MOVBYT1:
	   DEC	CL
	   JZ	MOVBYT3
MOVBYT2:
	   LODSB
	   CMP	AL,"$"
	   JZ	MOVBYT1
	   JMP	MOVBYT2

MOVBYT3:
	   LODSB
	   CMP	AL,'$'
	   JZ	MOVBYT5
	   CMP	AL,'@'                  ; THIS MEANS RESVERED OP-CODE
	   JNZ	MOVBYT4
	   POP	AX
	   JMP	SHORT ESC0P		; GO DO AN ESCAPE COMMAND

MOVBYT4:
	   STOSB
	   JMP	MOVBYT3

MOVBYT5:
	   POP	AX
	   RET

PUTOP:
	   AND	AL,111B
	   MOV	CL,AL
	   CALL MOVBYT
	   MOV	AL,9
	   STOSB
	   MOV	AL,DL
	   RET

GET64F:
	   CALL GET64
	   MOV	AL,"F"
	   STOSB
	   CMP	BYTE PTR [MODE],3
	   MOV	AL,DL
	   RET

GET64:
	   AND	AL,7
	   MOV	DL,AL
	   CALL GETMODE
	   SHL	DL,1
	   SHL	DL,1
	   SHL	DL,1
	   OR	AL,DL
	   MOV	DL,AL			; SAVE RESULT
	   RET

ESC0P:
	   POP	DI			; CLEAN UP STACK
ESC0:
	   MOV	WORD PTR [OPCODE],OFFSET DG:ESCMN
	   MOV	AL,DL
	   MOV	DI,OFFSET DG:OPBUF
	   JMP	SHORT ESC1

ESCP:
	   CALL GET64
ESC1:
	   CALL SAVHEX
	   CMP	BYTE PTR [MODE],3
	   JZ	SHRTESC
	   MOV	BYTE PTR  [AWORD],1
	   JMP	MEMOP2

SHRTESC:
	   MOV	AL,","
	   STOSB
	   MOV	AL,[REGMEM]
	   AND	AL,7
	   JMP	SAVREG

INVARW:
	   CALL PUTAX
	   JMP	SHORT INVAR

INVARB:
	   CALL PUTAL
INVAR:
	   MOV	AL,','
	   STOSB
	   JMP	short PUTDX

INFIXW:
	   CALL PUTAX
	   JMP	SHORT INFIX

INFIXB:
	   CALL PUTAL
INFIX:
	   MOV	AL,','
	   STOSB
	   JMP	SAV8

	   STOSW			;IS THIS DEAD CODE? EMK
	   RET

OUTVARB:
	   MOV	BX,"LA"
	   JMP	SHORT OUTVAR

OUTVARW:
	   MOV	BX,"XA"
OUTVAR:
	   CALL PUTDX
OUTFV:
	   MOV	AL,','
	   STOSB
	   MOV	AX,BX
	   STOSW
	   RET

OUTFIXB:
	   MOV	BX,"LA"
	   JMP	SHORT OUTFIX

OUTFIXW:
	   MOV	BX,"XA"
OUTFIX:
	   CALL SAV8
	   JMP	OUTFV

PUTAL:
	   MOV	AX,"A"+4C00H            ; "AL"
	   JMP	SHORT PUTX

PUTAX:
	   MOV	AX,"A"+5800H            ; "AX"
	   JMP	SHORT PUTX

PUTDX:
	   MOV	AX,"D"+5800H            ; "DX"
PUTX:
	   STOSW
	   RET

SHFT:
	   MOV	BX,OFFSET DG:SHFTAB
	   CALL GETMNE
TESTREG:
	   CMP	BYTE PTR [MODE],3
	   JZ	NOFLG
	   MOV	SI,OFFSET DG:SIZE_TAB
	   MOV	CL,3
	   TEST BYTE PTR [AWORD],-1
	   JNZ	TEST_1
	   INC	CL
TEST_1:
	   CALL MOVBYT
NOFLG:
	   JMP	ADDRMOD

SHIFTV:
	   CALL SHFT
	   MOV	AL,","
	   STOSB
	   MOV	WORD PTR [DI],"C"+4C00H ; "CL"
	   ADD	DI,2
	   RET

SHIFT:
	   CALL SHFT
	   MOV	AX,"1,"
	   STOSW
	   RET

GETMNE:
	   CALL GETMODE
	   MOV	DL,AL
	   CBW
	   SHL	AX,1
	   ADD	BX,AX
	   MOV	AX,[BX]
	   MOV	[OPCODE],AX
	   MOV	AL,DL
	   RET

GRP1:
	   MOV	BX,OFFSET DG:GRP1TAB
	   CALL GETMNE
	   OR	AL,AL
	   JZ	FINIMMJ
	   JMP	TESTREG
FINIMMJ:
	   JMP	FINIMM

GRP2:
	   MOV	BX,OFFSET DG:GRP2TAB
	   CALL GETMNE
	   CMP	AL,2
	   JB	TESTREG
	   CMP	AL,6
	   JAE	INDIRECT
	   TEST AL,1
	   JZ	INDIRECT
	   MOV	AX,"AF"                 ; "FAR"
	   STOSW
	   MOV	AX," R"
	   STOSW
INDIRECT:
	   JMP	ADDRMOD

CODE	   ENDS
	   END	UNASSEM
