	page	78,132
	title	Disassembly command

ActionBits	=	4
ActionMask	=	(1 shl ActionBits) - 1
SubIndexMask	=	not ActionMask

	.sall
dm		MACRO	string
$StrSize	sizestr	<&string>
$FirstStr	substr	<&string>,1,$StrSize-1
$LastChar	substr	<&string>,$StrSize
%		db	"&$FirstStr","&$LastChar"+80H
		ENDM

DefAction	MACRO	ActName
ActName&Ind	=	($ - Actions)/2
		dw	ActName
		ENDM

NewAction	MACRO	ActName
CurActInd	=	ActName&Ind
ActName&Ops	label	word
pos		=	0
		ENDM
	
DefMne		MACRO	mnemonic
Strings		segment
mnemonic&Op	label	byte
		dm	mnemonic
Strings		ends
		.code
		dw	offset DGroup:mnemonic&Op
		ENDM

OpInd	MACRO	opcode,MneInd
CurPos	=	$
.erre	CurActInd LE ActionMask
	org	OpGroup+opcode
	db	CurActInd + MneInd * (ActionMask+1)
	org	CurPos
	ENDM

DefOp	MACRO	opcode,mnemonic,count
	IFB	<count>
cnt	=	1
	ELSE
cnt	=	count
	ENDIF
	IRP	opc,<opcode>
i	=	0
	REPT	cnt
	OpInd	opc+i,pos
i	=	i+1
	ENDM	;;REPT
	ENDM	;;IRP
	IFNB	<mnemonic>
char1	substr	<mnemonic>,1,1
%	IFIDN	<char1>,<_>
Lchar	substr	<mnemonic>,2
OpNam	catstr	Lchar,<Op>
	dw	offset DGroup:OpNam
	ELSE
	DefMne	mnemonic
	ENDIF	;;IFIDN
	ENDIF	;;IFNB mnemonic
pos	=	pos + 1
	ENDM

DefSpc	MACRO	opcode,action,count
	IFB	<count>
cnt	=	1
	ELSE
cnt	=	count
	ENDIF
	IRP	opc,<opcode>
i	=	0
	REPT	cnt
	OpInd	opc+i,pos
i	=	i+1
	ENDM	;;REPT
	ENDM	;;IRP
	dw	offset DGroup:action
pos	=	pos + 1
	ENDM

	.model	small
	.code
	.data
Strings	segment	byte public
Strings	ends

DGroup	group	_DATA,Strings

	.data

	extrn	BxSave:word, BpSave:word, SiSave:word, DiSave:word, CsSave:word

fAddr32		=	1
fData32		=	2
FlagWord	dw	0
Prefix		equ	byte ptr FlagWord
Override	equ	byte ptr FlagWord+1
DisBuf		db	80 dup(?)
DefDis		dw	0,0

	.code

	public	UnAssemble,DisLine

	extrn	Default:near, PrintMes:near, OutCh:near, OutSi:near

tByteReg	label	word	
	db	"al"
	db	"cl"
	db	"dl"
	db	"bl"
	db	"ah"
	db	"ch"
	db	"dh"
	db	"bh"

tWordReg	label	word
	db	"ax"
	db	"cx"
	db	"dx"
	db	"bx"
	db	"sp"
	db	"bp"
	db	"si"
	db	"di"

tSegReg		label	word
	db	"es"
	db	"cs"
	db	"ss"
	db	"ds"
	db	"fs"
	db	"gs"

tShiftOps	label	word
	DefMne	rol
	DefMne	ror
	DefMne	rcl
	DefMne	rcr
	DefMne	shl
	DefMne	shr
	DefMne	sal
	DefMne	sar

tGrp3Ops	label	word
	dw	offset DGroup:TestOp
	dw	offset DGroup:TestOp
	DefMne	not
	DefMne	neg
	DefMne	mul
	DefMne	imul
	DefMne	div
	DefMne	idiv

tGrp4Ops	label	word
	dw	offset DGroup:IncOp
	dw	offset DGroup:DecOp
	dw	offset DGroup:CallOp
	dw	offset DGroup:CallOp
	dw	offset DGroup:JmpOp
	dw	offset DGroup:JmpOp
	dw	offset DGroup:PushOp
	dw	offset DGroup:???Op


XlatOp:		dm	xlat
IntOp:		dm	int
EscOp:		dm	esc
ByteMsg:	dm	byte
WordMsg:	dm	word
DwordMsg:	dm	dword
PtrMsg:		dm	< ptr >

AddrBx	=	1
AddrBp	=	2
AddrSi	=	4
AddrDi	=	8
AddrPlus=	10H

AddrMod16	label	byte
	db	AddrBx+AddrSi+AddrPlus
	db	AddrBx+AddrDi+AddrPlus
	db	AddrBp+AddrSi+AddrPlus
	db	AddrBp+AddrDi+AddrPlus
	db	AddrSi
	db	AddrDi
	db	AddrBp
	db	AddrBx

OpGroup	db	100H dup(0)		;Allocate opcode lookup table

Actions	label	word
	DefAction	OneByte
	DefAction	OneByte2
	DefAction	Arith
	DefAction	OneReg
	DefAction	CondJump
	DefAction	CondJump2
	DefAction	SegPush
	DefAction	String
	DefAction	ArithIm
	DefAction	Jump
	DefAction	Special
	DefAction	RepLock
	DefAction	InOut
	DefAction	AamAad
	DefAction	LdPointer
	DefAction	RetImm

NewAction	OneByte			;Start data for action routine
	DefOp	0F1H,???		;Must be first!!
	DefOp	027H,daa
	DefOp	02FH,das
	DefOp	037H,aaa
	DefOp	03FH,aas
	DefOp	060H,pusha
	DefOp	061H,popa
	DefOp	090H,nop
	DefOp	098H,cbw
	DefOp	099H,cwd
	DefOp	09BH,wait
	DefOp	09CH,pushf
	DefOp	09DH,popf
	DefOp	09EH,sahf
	DefOp	09FH,lahf
	DefOp	0C3H,ret
NewAction	OneByte2
	DefOp	0C9H,leave
	DefOp	0CBH,retf
	DefOp	0CEH,into
	DefOp	0CFH,iret
	DefOp	0F4H,hlt
	DefOp	0F5H,cmc
	DefOp	0F8H,clc
	DefOp	0F9H,stc
	DefOp	0FAH,cli
	DefOp	0FBH,sti
	DefOp	0FCH,cld
	DefOp	0FDH,std
NewAction	Arith
;WARNING! this order is needed for ArithIm and Group1 decoding!
	DefOp	00H,add,4
	DefOp	08H,or,4
	DefOp	10H,adc,4
	DefOp	18H,sbb,4
	DefOp	20H,and,4
	DefOp	28H,sub,4
	DefOp	30H,xor,4
	DefOp	38H,cmp,4
	DefOp	84H,test,2
	DefOp	86H,xchg,2
	DefOp	88H,mov,4
NewAction	OneReg
	DefOp	40H,inc,8
	DefOp	48H,dec,8
	DefOp	50H,push,8
	DefOp	58H,pop,8
NewAction	CondJump
	DefOp	70H,jo
	DefOp	71H,jno
	DefOp	72H,jc
	DefOp	73H,jnc
	DefOp	74H,jz
	DefOp	75H,jnz
	DefOp	76H,jbe
	DefOp	77H,ja
	DefOp	78H,js
	DefOp	79H,jns
	DefOp	7AH,jpe
	DefOp	7BH,jpo
	DefOp	7CH,jl
	DefOp	7DH,jge
	DefOp	7EH,jle
	DefOp	7FH,jg
NewAction	CondJump2
	DefOp	0E0H,loopne
	DefOp	0E1H,loope
	DefOp	0E2H,loop
	DefOp	0E3H,jcxz
	DefOp	0EBH,jmp
NewAction	SegPush
	DefOp	<06H,0EH,16H,1EH>,_push
	DefOp	<07H,17H,1FH>,_pop
NewAction	String
	DefOp	06CH,ins,2
	DefOp	06EH,outs,2
	DefOp	0A4H,movs,2
	DefOp	0A6H,cmps,2
	DefOp	0AAH,stos,2
	DefOp	0ACH,lods,2
	DefOp	0AEH,scas,2
NewAction	ArithIm
	DefOp	04H,,2
	DefOp	0CH,,2
	DefOp	14H,,2
	DefOp	1CH,,2
	DefOp	24H,,2
	DefOp	2CH,,2
	DefOp	34H,,2
	DefOp	3CH,,2
	DefOp	0A8H,,2
NewAction	Jump
	DefOp	<9AH,0E8H>,call
	DefOp	<0E9H,0EAH>,_jmp
NewAction	Special
	DefSpc	0B0H,MoveIm,16
	DefSpc	91H,XchgAx,7
	DefSpc	<26H,2EH,36H,3EH,64H,65H>,SegOver
	DefSpc	0D7H,XlatInst
	DefSpc	0A0H,MovAcc,4
	DefSpc	0C6H,MovImMem,2
	DefSpc	<8CH,8EH>,SegMov
	DefSpc	8FH,PopMem
	DefSpc	0CCH,Interrupt,2
	DefSpc	0D8H,Coprocessor,8
	DefSpc	80H,Group1,4
	DefSpc	0C0H,Group2,2
	DefSpc	0D0H,Group2,4
	DefSpc	0F6H,Group3,2
	DefSpc	0FEH,Group4,2
NewAction	RepLock
	DefOp	0F0H,lock
	DefOp	0F2H,repne
	DefOp	0F3H,repe
NewAction	InOut
	DefOp	<0E4H,0ECH>,in,2
	DefOp	<0E6H,0EEH>,out,2
NewAction	AamAad
	DefOp	0D4H,aam
	DefOp	0D5H,aad
NewAction	LdPointer
	DefOp	62H,bound
	DefOp	8DH,lea
	DefOp	0C4H,les
	DefOp	0C5H,lds
NewAction	RetImm
	DefOp	0C2H,_ret
	DefOp	0CAH,_retf

	assume	ds:nothing,es:nothing,ss:DGroup

UnAssemble:
	mov	bp,[CsSave]		;Default segment is cs
	mov	cx,8
	mov	di,offset DGroup:DefDis
	call	Default			;Get range to disassemble
	mov	ds,ax			;Set segment
	mov	si,dx			;SI has displacement in segment
LineDis:
	push	cx
	call	DisLine
	pop	cx
	loop	LineDis
	ret

DisLine:
;Display disassembly of line at ds:si
	call	OutSi
	mov	al,9			;Tab char
	call	OutCh
	mov	di,offset DGroup:DisBuf
	call	DisAssemble
	mov	ax,13+(10+80H)*100H	;Add Cr/Lf terminator
	stosw
	mov	word ptr [DefDis],si
	mov	word ptr [DefDis+2],ds	;Remember last addrss as default
	push	ds
	push	si
	push	cs
	pop	ds
	mov	si,offset DGroup:DisBuf
	call	PrintMes
	pop	si
	pop	ds
	ret

DisAssemble:
;ds:si points to code
;es:di points to destination buffer
	mov	[FlagWord],0
DisNext:
	lodsb				;Get first code byte
	mov	ah,al			;Save a copy
	mov	bx,offset DGroup:OpGroup
	xlat	OpGroup
	mov	bl,al
	and	bx,ActionMask		;Low 4 bits have action index
	shl	bx,1
	mov	dx,[bx].Actions		;Get address of action routine
	mov	bl,al
	and	bl,SubIndexMask		;Mask to mnemonic index
	mov	cl,ActionBits - 1
	shr	bx,cl			;Now a word index
	jmp	dx

Special:    
;Dispatch for those opcodes with only one mnemonic per action
	jmp	[bx].SpecialOps

RepLock:
	mov	bx,[bx].RepLockOps
	call	CopyMsgTab
	jmp	DisNext

SegOver:
	mov	al,ah
	cmp	al,60H			;FS/GS?
	jae	SegInPlace
	mov	cl,3
	shr	al,cl			;Bring seg no. down to low end
	and	al,3
SegInPlace:
	and	al,7
	inc	ax
	mov	[Override],al
	jmp	DisNext

SegMov:
	mov	bx,offset DGroup:MovOp
	call	CopyMsgTab
	lodsb				;Get R/M byte
	mov	bl,al
	and	bx,7*8			;Mask to segment reg
	shr	bx,1
	shr	bx,1
	mov	bx,[bx].tSegReg
	test	ah,2			;To segment reg?
	mov	ah,1			;Ensure word size
	jnz	ToSeg
	push	bx			;Save segment reg
	call	ModRm
	mov	al,","
	stosb
	pop	ax			;Get seg reg back
	stosw
	ret

ToSeg:
	xchg	bx,ax			;Seg reg to ax
	stosw
	mov	al,","
	stosb
	xchg	bx,ax			;Restore R/M byte
	jmp	ModRm

PopMem:
	mov	bx,offset DGroup:PopOp
	call	CopyMsgTab
	lodsb				;Get R/M byte
	jmp	ModRm

MoveIm:
	mov	bx,offset DGroup:MovOp
	call	CopyMsgTab
	mov	al,ah
	mov	cl,3
	shr	ah,cl			;Move bit 3 down to bit 0
	jmp	short RegImm

MovAcc:
	mov	bx,offset DGroup:MovOp
	call	CopyMsgTab
	test	ah,2			;To accumulator?
	jz	ToAcc
	push	ax
	mov	al,"["
	stosb
	call	WordImm
	mov	ax,",]"
	stosw
	pop	ax			;Get byte/word flag back
	xor	al,al			;Use al/ax
	jmp	ShowReg

ToAcc:
	xor	al,al			;Use al/ax
	call	ShowReg
	mov	ax,"[,"
	stosw
	call	WordImm
	mov	al,"]"
	stosb
	ret

ArithIm:
	mov	bx,[bx].ArithOps
	call	CopyMsgTab
	mov	al,0			;Select al, ax, or eax
RegImm:
	call	ShowReg
ShowImm:
	mov	al,","
	stosb
	add	si,cx
	push	si
ImmLp:
	dec	si
	mov	al,ds:[si]
	call	HexByteDis
	loop	ImmLp
	pop	si
	ret	

Group3:
	mov	bx,offset DGroup:tGrp3Ops
	call	IndexRm
	push	ax
	call	ModRmSize
	pop	ax
	and	al,7*8			;Mask to operation bits
	cmp	al,1			;Is it TEST?
	jbe	ShowImm			;Yes, has immediate value
	ret

MovImMem:
	mov	bx,offset DGroup:MovOp
	call	CopyMsgTab
	lodsb
	call	ModRm
	jmp	ShowImm

Coprocessor:
	mov	bx,offset DGroup:EscOp
	call	CopyMsgTab
	lodsb				;Get R/M byte
	push	ax
	and	ax,7*8+700H		;Get middle bits of al, low bits of ah
	shl	al,1			;Now in high nybble
	or	al,ah
	call	HexByteDis
	mov	al,","
	stosb
	pop	ax
	jmp	ModRm

Group4:
	mov	bx,offset DGroup:tGrp4Ops
	call	IndexRm
	push	ax
;Look for far call (3*8) and far jump (5*8)
	sub	al,3*8			;Now 0*8 or 2*8
	and	al,5*8			;Get middle bits
	jnz	@F
	or	[Prefix],fData32	;Set operand size to dword
@@:
	pop	ax
	call	ModRmSize
Ret1:
	ret

AamAad:
	mov	bx,[bx].AamAadOps
	call	CopyMsg
	lodsb				;Next byte "should" be 10
	cmp	al,10			;Standard instruction?
	jz	Ret1
	push	ax			;Save value
	mov	al,9
	stosb
	pop	ax
	jmp	HexByteDis

InOut:
	mov	bx,[bx].InOutOps
	call	CopyMsgTab
	test	ah,2			;IN instruction?
	jnz	ShowPort
AxInpOut:
	xor	al,al			;Select al/ax
	push	ax
	call	ShowReg
	pop	ax
	test	ah,2			;IN instruction?
	jnz	Ret1			;No, already did port
	mov	al,","
	stosb
ShowPort:
	push	ax
	test	ah,8			;Immediate port?
	jz	ImmedPort
	mov	ax,"xd"
	stosw
	jmp	short PortDone

ImmedPort:
	call	ByteImm
PortDone:
	pop	ax
	test	ah,2			;IN instruction?
	jz	Ret1			;Yes, already did register
	mov	al,","
	stosb
	jmp	AxInpOut

String:
	mov	bx,[bx].StringOps
	call	CopyMsg
	mov	al,"b"			;Assume byte version
	test	ah,1			;word/dword?
	jz	StrTyp
	mov	al,"d"
	test	[Prefix],fData32
	jnz	StrTyp
	mov	al,"w"
StrTyp:
	stosb
TabOverride:
	cmp	[Override],0		;Segment override present?
	jz	NoOver
	mov	al,9
	stosb
SegOverride:
	mov	bl,[Override]
	cmp	bl,0			;Segment override present?
	jz	NoOver
	mov	bh,0
	shl	bx,1
	mov	ax,[bx-2].tSegReg
	stosw
	mov	al,":"
	stosb
NoOver:
	ret

XlatInst:
	mov	bx,offset DGroup:XlatOp
	call	CopyMsg
	jmp	TabOverride

SegPush:
	mov	bx,[bx].SegPushOps
	call	CopyMsgTab
	mov	al,ah
	and	ax,18H			;Mask to seg reg bits
	shr	ax,1
	shr	ax,1
	xchg	bx,ax
	mov	ax,[bx].tSegReg
	stosw
	ret

OneReg:
	mov	bx,[bx].OneRegOps	;Point to opcode
	call	CopyMsgTab
	mov	al,ah
	mov	ah,1			;Indicate word operation
	jmp	ShowReg


XchgAx:
	mov	bx,offset DGroup:XchgOp
	call	CopyMsgTab
	mov	al,ah
	mov	ah,1			;Word reg
	push	ax
	mov	ax,"xa"
	stosw
	jmp	short SecondReg

LdPointer:
	mov	bx,[bx].LdPointerOps	;Point to opcode
	or	ah,3			;Set WORD, to CPU
	jmp	short RegMem

Arith:
	mov	bx,[bx].ArithOps	;Point to opcode
RegMem:
	call	CopyMsgTab
	lodsb				;Get R/M byte
	mov	dl,al
	mov	cl,3
	shr	al,cl			;Put register in low end
	test	ah,2			;Check direction
	jnz	ToCpu
	push	ax
	xchg	al,dl
	call	ModRm
SecondReg:
	mov	al,","
	stosb
	pop	ax
	jmp	ShowReg

ToCpu:
;List register in R/M byte first
	mov	dh,ah
	push	dx
	call	ShowReg
	mov	al,","
	stosb
	pop	ax
	jmp	ModRm

Jump:
	mov	bx,[bx].JumpOps
	call	CopyMsgTab
	test	ah,2			;Is it far?
	lodsw				;Get offset
	jz	RelJump
	xchg	dx,ax
	call	WordImm			;Print segment
	mov	al,":"
	stosb
	xchg	ax,dx			;Offset back to ax
	jmp	short HexWordDis

Group2:
;Shifts
	mov	bx,offset DGroup:tShiftOps
	call	IndexRm
	push	ax
	call	ModRmSize
	pop	ax
	mov	al,","
	stosb
	test	ah,10H			;Immediate count of shifts?
	jz	ByteImm
	mov	al,"1"
	test	ah,2			;One bit shift?
	jz	OneChar
	mov	ax,"lc"
	stosw
	ret

Group1:
;Arithmetic immediate
	mov	bx,offset DGroup:ArithOps
	call	IndexRm
	push	ax
	call	ModRmSize
	pop	ax
	mov	al,","
	stosb
	test	ah,1
	jz	ByteImm
	test	ah,2
	jz	WordImm
	lodsb				;Get 8-bit displacement
SignedByte:
	mov	ah,al
	or	al,al			;Check sign
	mov	al,"+"
	jns	@F
	mov	al,"-"
	neg	ah
@@:
	stosb				;Store sign
	xchg	al,ah
	jmp	short HexByteDis

ByteImm:
	lodsb
	jmp	short HexByteDis

RetImm:
	mov	bx,[bx].RetImmOps
	call	CopyMsgTab
WordImm:
	lodsw
	jmp	short HexWordDis

CondJump2:
	mov	bx,[bx].CondJump2Ops	;Point to opcode
	jmp	short AllCondJump

CondJump:
	mov	bx,[bx].CondJumpOps	;Point to opcode
AllCondJump:
	call	CopyMsgTab
	lodsb				;Get displacement
	cbw
RelJump:
	add	ax,si			;Compute target address
HexWordDis:
;Convert word in ax to ASCII hex and store
	mov	cl,al
	mov	al,ah
	call	HexByteDis
	mov	al,cl
HexByteDis:
;Convert byte in al to ASCII hex and store
	mov	ah,al
	shr	al,1
	shr	al,1
	shr	al,1
	shr	al,1
	call	Nybble
	mov	al,ah
Nybble:
;Convert low nybble in AL to hex and stosb
	and	al,0FH
	cmp	al,10
	sbb	al,69H
	das
OneChar:
	stosb
	ret

Interrupt:
	mov	bx,offset DGroup:IntOp
	call	CopyMsgTab
	test	ah,1			;With immediate byte?
	jnz	ByteImm
	mov	al,"3"
	stosb
	ret

CopyMsgTab:
	call	CopyMsg
	mov	al,9
	stosb
	ret

OneByte2:
	mov	bx,[bx].OneByte2Ops	;Point to opcode
	jmp	short CopyMsg

OneByte:
	mov	bx,[bx].OneByteOps	;Point to opcode
	jmp	short CopyMsg

CopyMore:
	stosb
CopyMsg:
	mov	al,DGroup:[bx]
	inc	bx
	or	al,al			;End of string?
	jns	CopyMore
	and	al,7FH
	stosb
	ret

IndexRm:
	lodsb				;Get R/M byte
	mov	dl,al
	and	al,7*8			;Mask to operation field
	shr	al,1
	shr	al,1
	add	bl,al
	adc	bh,0
	mov	bx,cs:[bx]
	call	CopyMsgTab
	mov	al,dl			;R/M byte back to al
	ret

;****************************************************************************
	subttl	ModRm, ModRmSize, and ShowReg
	page

;ModRm displays a memory or register operand.
;
;ModRmSize includes a leading "byte ptr" (or whatever) to indicate size
;if the operand is not a register.
;
;ShowReg looks up a register.
;
;As always, ds:si points to code to disassemble, es:di points to destination
;buffer.  These pointers will be updated as appropriate.


ModRmSize:
	mov	cl,1			;Indicate a size is needed
	jmp	short ModRmCommon

ModRm:
;Inputs:
;	al = R/M byte
;	ah bit 1 has word flag (0 = byte)
;Outputs:
;	cx = no. of bytes in operand

	xor	cx,cx			;Operand size not needed
ModRmCommon:
	and	al,0C7H			;Mask out middle bits
	cmp	al,0C0H			;Register mode?
	jb	MemOp

ShowReg:
;Display general register
;Inputs:
;	al bits 0 - 2 have register number
;	ah bit 1 has word flag (0 = byte)
;Outputs:
;	cx = no. of bytes in register

	and	al,7			;Get register
	mov	bl,al
	mov	bh,0
	shl	bx,1			;Word index into register
	and	ah,1			;Byte size?
	mov	cl,ah
	mov	ch,0
	jz	RegIndex
	add	bx,offset tWordReg - offset tByteReg
	test	[Prefix],fData32
	jz	RegIndex
	mov	al,"e"
	stosb
	mov	cl,3
RegIndex:
	inc	cx
	mov	ax,[bx].tByteReg
	stosw
	ret

MemOp:
	push	ax
	mov	bx,offset DGroup:ByteMsg
	mov	dx,1
	test	ah,1			;Check word bit
	jz	ShowMemSize
	mov	bx,offset DGroup:WordMsg
	inc	dx
	test	[Prefix],fData32	;32-bit data mode?
	jz	ShowMemSize
	mov	bx,offset DGroup:DwordMsg
	inc	dx
	inc	dx
ShowMemSize:
	jcxz	NoMemSize
	call	CopyMsg
	mov	bx,offset DGroup:PtrMsg
	call	CopyMsg
NoMemSize:
	call	SegOverride
	mov	al,"["
	stosb
	pop	ax
	test	[Prefix],fAddr32	;32-bit address mode?
	jnz	Addr32
	cmp	al,6			;Direct address mode?
	jz	Disp16
	mov	ch,al
	and	al,7
	mov	bx,offset DGroup:AddrMod16
	xlat	AddrMod16		;Get address registers
	mov	cl,al
	test	cl,AddrBp
	jnz	UseBp
	test	cl,AddrBx
	jz	TestAddrSi
	mov	ax,"xb"
	stosw
TestPlus:
	test	cl,AddrPlus
	jz	DispTest
	mov	al,"+"
	stosb
TestAddrSi:
	test	cl,AddrSi
	jnz	UseSi
	test	cl,AddrDi
	jz	DispTest
	mov	ax,"id"
	stosw
DispTest:
	and	ch,0C0H			;Displacement?
	jz	EndMem
	mov	al,"+"
	js	AddDisp16
	lodsb
	cbw
	call	SignedByte
EndMem:
	mov	cx,dx			;Operand size to cx
	mov	al,"]"
	stosb
	ret

UseBp:
	mov	ax,"pb"
	stosw
	jmp	TestPlus

UseSi:
	mov	ax,"is"
	stosw
	jmp	DispTest

Addr32:
;UNDONE

AddDisp16:
	stosb
Disp16:
	lodsw				;Get 16-bit displacement
	call	HexWordDis
	jmp	EndMem


	end
