;
; GRDP
;
; Copyright(c) LADsoft
;
; David Lindauer, gclind01@starbase.spd.louisville.edu
;
;
; Operands.asm
;
; Function: Handle 386 operands as dictated by the opcode table
;   Handle formatting output
;
; Sorry, I didn't have time to document this one yet
;
; years later:
;
; sorry, I STILL didn't have time to document this one yet :)
;
	.386
	;MASM MODE
	.MODEL SMALL

include	dispatch.ase 
include	opcodes.asi
include	operands.asi
include	opcom.ase

	PUBLIC TabTo, ReadOverrides, DispatchOperands
	PUBLIC	FormatDisassembly, FormatValue, code_address
	PUBLIC	PutDword, PutWord,PutByte
	PUBLIC	put2,put3,put4, strlen

	extrn x86pfx : byte
SZ_QWORD	=	2
SZ_TBYTE	=	4

	.DATA
code_address	dd	0		;disassembly address within segment
dest2		dd	0		;temps to aid decoding
source2		dd	0
segs		dd	0		
extraoperand	OPERAND <>		;third operand
source		OPERAND	<>		;second operand
dest		OPERAND	<>		;first operand
nmmnemonic 	db	10 DUP (?)	;mnemonic (may be modified here)
reqsPtrSizeOvride	db	0	;flag set if xxx ptr required

	.CODE

;Find the length of a string in a buffer pointed to by SI, and return that
;length in AX.  This is a strange way to do this. I think I'll change it
;just a little.
;  If SI comes in pointing to a 0, we return a string length of 0

strlen	PROC	
	push	edi
	push	esi
	push	ecx
	mov	edi,esi
	mov	ecx,-1
	sub	al,al
	repnz	scasb
	mov	eax,ecx
	not	eax
	dec	eax
	pop	ecx
	pop	esi
	pop	edi
	ret
strlen	ENDP	




strcpy	PROC	
strcpylp:
	lodsb
	stosb
	or	al,al
	jnz	strcpylp
	ret
strcpy	ENDP	


strcat	PROC	
	mov	al,[edi]
	inc	edi
	or	al,al
	jnz	strcat
	dec	edi
	jmp	strcpy
strcat	ENDP	


copyextra	PROC	
	push	esi
	push	edi
	mov	esi,offset extraoperand
	xchg	esi,edi
	mov	ecx,OPERANDSIZE
	rep	movsb
	pop	edi
	pop	esi
	ret
copyextra	ENDP	



put2	PROC	
	mov	[esi],ah
	inc	esi
	mov	[esi],al
	inc	esi
	mov	BYTE PTR [esi],0
	ret
put2	ENDP	


put3	PROC	
	push	eax
	shr	eax,8
	mov	[esi],ah
	inc	esi
	pop	eax
	call	put2
	ret
put3	ENDP	


put4	PROC	
	push	eax
	shr	eax,16
	call	put2
	pop	eax
	call	put2
	ret
put4	ENDP	


SetSeg	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+OPERAND.CODE],OM_SEGMENT
	mov	[edi+OPERAND.THEREG],al
	ret
SetSeg	ENDP	


setreg	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+OPERAND.CODE],OM_REG
	mov	[edi+OPERAND.THEREG],al
	ret
setreg	ENDP	


ReadRM	PROC	
	push	ecx
	sub	ecx,ecx
	mov	cl,2
	RM	esi
	mov	[edi+OPERAND.THEREG],al
	MODX	esi
	mov	ch,al
	cmp	ch,MOD_REG
	jnz	short notregreg
	mov	[edi+OPERAND.CODE],OM_REG
	mov	[reqsPtrSizeOvride],FALSE
	sub	eax,eax
	pop	ecx
	ret
notregreg:
	bt	[edi+OPERAND.OEFLAGS],OMF_ADR32
	jnc	adr16
	cmp	[edi+OPERAND.THEREG],RM_32_SCALED
	jnz	notscaled
	inc	cl
	RM	esi+1
	mov	[edi+OPERAND.THEREG],al
	REG	esi+1
	mov	[edi+OPERAND.SCALEREG],al
	MODX	esi+1
	mov	[edi+OPERAND.SCALE],al
	cmp	[edi+OPERAND.SCALEREG],RM_32_STACKINDEX
	jz	hassp
	bts	[edi+OPERAND.OEFLAGS],OMF_SCALED
hassp:
	cmp	[edi+OPERAND.THEREG],RM_32_ABSOLUTE
	jnz	basedAndScaled
	cmp	ch,MOD_NOOFS
	jnz	short basedAndScaled
	mov	[edi+OPERAND.CODE],OM_ABSOLUTE
	LONG	esi+3
	mov	[edi+OPERAND.ADDRESS],eax
	sub	eax,eax
	mov	al,5
	pop	ecx
	ret
notscaled:
	
	cmp	ch,MOD_NOOFS
	jnz	basedAndScaled
	cmp	[edi+OPERAND.THEREG], RM_32_ABSOLUTE
	jnz	basedAndScaled
	mov	[edi+OPERAND.CODE], OM_ABSOLUTE
	LONG	esi+2
	mov	[edi+OPERAND.ADDRESS],eax
	sub	eax,eax
	sub	eax,eax
	mov	al,4
	pop	ecx
	ret
adr16:
	cmp	ch,MOD_NOOFS
	jnz	basedAndScaled
	cmp	[edi+OPERAND.THEREG], RM_16_ABSOLUTE
	jnz	basedAndScaled
	mov	[edi+OPERAND.CODE], OM_ABSOLUTE
	UINT	esi+2
	mov	[edi+OPERAND.ADDRESS],eax
	sub	eax,eax
	mov	al,2
	pop	ecx
	ret
basedAndScaled:
	mov	[edi+OPERAND.CODE], OM_BASED
	cmp	ch,MOD_ADDR
	jnz	short checksigned
	bts	[edi+OPERAND.OEFLAGS], OMF_WORD_OFFSET
	push	ecx
	sub	ch,ch
	movzx	ecx,cl
	mov	eax,[esi+ecx]
	pop	ecx
	bt	[edi+OPERAND.OEFLAGS], OMF_ADR32
	jc	dwordx
	and	eax,0ffffh
	sub	cl,2
dwordx:
	mov	[edi+OPERAND.ADDRESS],eax
	add	cl,4
	jmp	short ReadRMdone
checksigned:
	cmp	ch, MOD_SIGNED
	jnz	short ReadRMdone
	bts	[edi+OPERAND.OEFLAGS],OMF_SIGNED_OFFSET
	movzx	ecx,cl
	movzx	eax,byte ptr [esi+ecx]
	mov	[edi+OPERAND.ADDRESS],eax
	inc	cl
ReadRMdone:
	movzx	eax,cl
	sub	al,2
	pop	ecx
	ret
ReadRM	ENDP	


RegRM	PROC	
	mov	edi,[dest2]
	REG	esi
	call	setreg
	mov	edi,[source2]
	call	ReadRM
	ret
RegRM	ENDP	


Immediate	PROC	
	push	ecx
	sub	ecx,ecx
	mov	[edi+OPERAND.CODE],OM_IMMEDIATE
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jnc	short inotbyte
	inc	cl
	sub	eax,eax
	mov	al,[esi]
	jmp	short i_ret
inotbyte:
	bt	[edi+OPERAND.OEFLAGS], OMF_OP32
	jnc	iword
	add	cl,4
	LONG	esi
	jmp	short i_ret
iword:
	add	cl,2
	UINT	esi
i_ret:
	mov	[edi+OPERAND.ADDRESS],eax
	mov	eax,ecx
	pop	ecx
	ret
Immediate	ENDP	

;Find a binary 0, stick whatever is in AL there, and put a 0 after that.

MnemonicChar	PROC	
	push	edi
	mov	edi,offset nmmnemonic
mc2:
	inc	edi
	cmp	BYTE PTR [edi-1],0
	jnz	mc2
	mov	[edi-1],al
	mov	BYTE PTR [edi],0
	pop	edi
	ret
MnemonicChar	ENDP	



;/* op 1- word reg from bits 0 - 2 of opcode */

op1	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,[esi]
	B02
	call	setreg
	sub	eax,eax
	ret
op1	ENDP	


;/* Op2 acc, reg bits 0-2 of opcode */
op2	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	mov	al,[esi]
	and	al,7
	call	setreg
	sub	eax,eax
	ret
op2	ENDP	


;/* op3 - seg from b3-5 of opcode */
op3	PROC	
	mov	al,[esi]
	B35
	call	SetSeg
	sub	eax,eax
	ret
op3	ENDP	


;/* op4 - REGRM with b1 of opcode set reg is dest else source */
op4	PROC	
	bt	DWORD PTR [esi],1
	jc	short op4nox
	xchg	ebx,edi
op4nox:
	mov	[dest2],edi
	mov	[source2],ebx
	call	RegRM
	ret
op4	ENDP	


;/* op5 - use RM only */
op5	PROC	
	call	ReadRM
	ret
op5	ENDP	


;/* op6 ReadRM for shift */
op6	PROC	
	call	ReadRM
	sub	ecx,ecx
	mov	cl,al
	mov	edi,ebx
	mov	[edi+OPERAND.CODE],OM_SHIFT
	bt	DWORD PTR [esi],4
	jnc	short op6cnt
	bt	DWORD PTR [esi],1
	jnc	op61
	bts	[edi+OPERAND.OEFLAGS],OMF_CL
	jmp	short op6done
op61:
	mov	[edi+OPERAND.ADDRESS],1
	jmp	short op6done
op6cnt:
	movzx	eax,BYTE PTR [esi+ecx+2]
	inc	cl
	mov	[edi+OPERAND.ADDRESS],eax
op6done:
	mov	eax,ecx
	ret
op6	ENDP	


;/* op 7 regrm with reg dest */
op7	PROC	
	mov	[dest2],edi
	mov	[source2],ebx
	call	RegRM
	ret
op7	ENDP	


;/* OP8 - word regrm with reg dest */
op8	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	jmp	op7
op8	ENDP	


;/* op 9 - interrupts */
op9	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	sub	eax,eax
	mov	al,3
	bt	DWORD PTR [esi],0
	jnc	short op9int3
	mov	al,[esi+1]
op9int3:
	mov	[edi+OPERAND.ADDRESS],eax
	mov	BYTE PTR [edi+OPERAND.CODE],OM_INT
	sub	al,al
	ret
op9	ENDP	


;/* op 10, short relative branch */
op10	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+OPERAND.CODE],OM_SHORTBRANCH
	movsx	eax,BYTE PTR [esi+1]
	inc	eax
	inc	eax
	add	eax,[code_address]
	mov	[edi+OPERAND.ADDRESS],eax
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jc	short op10notword
	and	[edi+OPERAND.ADDRESS],0ffffh
op10notword:
	sub	eax,eax
	ret
op10	ENDP	


;/* op 11 RM, immediate */
op11	PROC	
	call	ReadRM
	movzx	ecx,al
	mov	edi,ebx
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	add	cl,al
	pop	esi
	mov	eax,ecx
	ret
op11	ENDP	


;/* op 12 - acc, immediate */
op12	PROC	
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	inc	esi
	call	Immediate
	dec	esi
	ret
op12	ENDP	


;/* op 13 absolute, acc*/
op13	PROC	
	sub	ecx,ecx
	mov	[edi+OPERAND.CODE],OM_ABSOLUTE
	bt	[edi+OPERAND.OEFLAGS],OMF_ADR32
	jnc	short op13word
	LONG	esi+1
	inc	cl
	inc	cl
	jmp	short op13fin
op13word:
	UINT	esi+1
op13fin:
	mov	[edi+OPERAND.ADDRESS],eax
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	mov	eax,ecx
	ret
op13	ENDP	


;/* op 14 - RM, immediate, b01 of opcode != 1 for byte */
op14	PROC	
	call	ReadRM
	movzx	ecx,al
	mov	al,[esi]
	B01
	jnz	short op14checkbyte
	bts	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jmp	short op14source
op14checkbyte:
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	cmp	al,1
	jz	short op14check2
	bts	[ebx+OPERAND.OEFLAGS],OMF_BYTE
op14check2:
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
op14source:
	mov	edi,ebx
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	pop	esi
	add	cl,al
	mov	al,[esi]
	B01
	cmp	al,3
	jnz	op14done
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jnc	op14done
	bts	[edi+OPERAND.OEFLAGS],OMF_SIGNED
	movzx	eax,byte ptr [edi+OPERAND.ADDRESS]
	mov	[edi+OPERAND.ADDRESS],eax
op14done:
	mov	eax,ecx
	ret
op14	ENDP	


;/* op 15 - acc, immediate, B3 of opcode clear for byte */
op15	PROC	
	mov	al,[esi]
	B02
	call	setreg
	bt	DWORD PTR [esi],3
	jnc	op15byte
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	jmp	short op15source
op15byte:
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bts	[ebx+OPERAND.OEFLAGS],OMF_BYTE
op15source:
	mov	edi,ebx
	inc	esi
	call	Immediate
	dec	esi
	ret
op15	ENDP	


;/* op 16 - seg,ReadRM, if B1 of opcode seg is dest else source */
op16	PROC	
	bt	DWORD PTR [esi],1
	jc	noswap
	xchg	ebx,edi
noswap:
	REG	esi
	call	SetSeg
	mov	edi,ebx
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	call	ReadRM
	ret
op16	ENDP	


;/* op 17, far return */
op17	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+OPERAND.CODE],OM_RETURN
	btr	[edi+OPERAND.OEFLAGS],OMF_ADR32
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	UINT	esi+1
	mov	[edi+OPERAND.ADDRESS],eax
	sub	eax,eax
	ret
op17	ENDP	


;/* op 18, far branch/call */
op18	PROC	
	sub	ecx,ecx
	mov	[reqsPtrSizeOvride],FALSE
	mov	[edi+OPERAND.CODE],OM_FARBRANCH
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jnc	short op18word
	inc	cl
	inc	cl
	LONG	esi+1
	jmp	short	op18fin
op18word:
	UINT	esi+1
op18fin:
	mov	[edi+OPERAND.ADDRESS],eax
	UINT	esi+ecx+3
	mov	[edi+OPERAND.OESEG],ax
	mov	eax,ecx
	ret
op18	ENDP	


;/* op 19 - ESC, mnem of bits 0-2 of opcode, imm,ReadRM */
op19	PROC	
	mov	[edi+OPERAND.CODE],OM_IMMEDIATE
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,[esi]
	and	al,7
	shl	al,3
	mov	ah,[esi+1]
	shr	ah,3
	and	ah,7
	or	al,ah
	sub	ah,ah
	cwde
	mov	[edi+ OPERAND.ADDRESS],eax
	mov	edi,ebx
	call	ReadRM
	ret
op19	ENDP	


;/* op 20 - long branch */
op20	PROC	
	sub	eax,eax
	mov	[reqsPtrSizeOvride],FALSE
	sub	ecx,ecx
	mov	[edi+OPERAND.CODE],OM_LONGBRANCH
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jnc	short op20word
	LONG	esi+1
	inc	cl
	inc	cl
	jmp	short op20fin
op20word:
	UINT	esi+1
op20fin:
	add	eax,[code_address]
	test	[segs],SG_TWOBYTEOP
	jz	op20xx
	inc	eax
op20xx:
	add	eax,ecx
	add	eax,3
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jc	op20done
	and	eax,0ffffh
op20done:
	mov	[edi+OPERAND.ADDRESS],eax
	mov	eax,ecx
	ret
op20	ENDP	


;/* op21 acc,edx */
op21	PROC	
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,REG_DX
	call	setreg
	sub	eax,eax
	ret
op21	ENDP	


;/* op22 - dx,acc */
op22	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,REG_DX
	call	setreg
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	sub	eax,eax
	ret
op22	ENDP	


;/* op23 - port,acc where B1 of opcode set is port dest */
op23	PROC	
	bt	DWORD PTR [esi],1
	jc	short op20noswap
	xchg	ebx,edi
op20noswap:
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	[edi+OPERAND.CODE],OM_PORT
	movzx	eax,BYTE PTR [esi+1]
	mov	[edi+OPERAND.ADDRESS],eax
	mov	edi,ebx
	mov	al,REG_EAX
	call	setreg
	sub	eax,eax
	ret
op23	ENDP	


;/* op 24 acc, absolute */
op24	PROC	
	sub	ecx,ecx
	mov	al,REG_EAX
	call	setreg
	mov	edi,ebx
	mov	[edi+OPERAND.CODE],OM_ABSOLUTE
	bt	[edi+OPERAND.OEFLAGS],OMF_ADR32
	jnc	short op24word
	inc	cl
	inc	cl
	LONG	esi+1
	jmp	short op24done
op24word:
	UINT	esi+1
op24done:
	mov	[edi+OPERAND.ADDRESS],eax
	mov	eax,ecx
	ret
op24	ENDP	


;/* op 25 - immediate byte or word */
op25	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bt	DWORD PTR [esi],1
	jc	short op25fin
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
op25fin:
	push	esi
	inc	esi
	call	Immediate
	pop	esi
	ret
op25	ENDP	


;/* op 26, immediate 2byte,byte */
op26	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	push	esi
	inc	esi
	call	Immediate
	mov	edi,ebx
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	inc	esi
	inc	esi
	call	Immediate
	pop	esi
	sub	eax,eax
	ret
op26	ENDP	


;/* op 27 - string */
op27	PROC	
	mov	al,'d'
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jc	short op27pc
	mov	al,'w'
op27pc:
	call	MnemonicChar
	sub	eax,eax
	ret
op27	ENDP	


;/* op 28 - source = REG, dest = RM */
op28	PROC	
	xchg	edi,ebx
	jmp	op7
op28	ENDP	


;/* op 29 - rm, size don't care */
op29	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	mov	[reqsPtrSizeOvride],FALSE
	call	ReadRM
	ret
op29	ENDP	


;/* op30 - RM, shift with B3 of stream selecting COUNT or CL*/
op30	PROC	
	call	ReadRM
	mov	ecx,eax
	mov	edi,ebx
	mov	[edi+OPERAND.CODE],OM_SHIFT
	bt	DWORD PTR [esi],3
	jnc	op30cl
	movzx	eax,byte ptr [esi+ecx+2]
	mov	[edi+OPERAND.ADDRESS],eax
	inc	ecx
	jmp	short op30done
op30cl:
	bts	[edi+OPERAND.OEFLAGS],OMF_CL
op30done:
	mov	eax,ecx
	ret
op30	ENDP	


;/* op 31- reg, rm, count where B1 of opcode = byte/word */
op31	PROC	
	call	copyextra
	REG	esi
	call	setreg
	mov	edi,ebx
	call	ReadRM
	mov	ecx,eax
	mov	edi,offset extraoperand
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bt	DWORD PTR [esi],1
	jc	short op31byte
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
op31byte:
	push	esi
	inc	esi
	inc	esi
	call	Immediate
	pop	esi
	add	eax,ecx
	ret
op31	ENDP	


;/* op32 - 386 special regs */
op32	PROC	
	movzx	ecx,WORD PTR [esi]
	and	ecx,0c005h
	cmp	ecx,0c000h
	mov	al,OM_CRX
	jz	short op32gotype
	cmp	ecx,0c001h
	mov	al,OM_DRX
	jz	short op32gotype
	cmp	ecx,0c004h
	mov	al,OM_TRX
	jz	short op32gotype
	mov	al,OM_SUD
op32gotype:
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	bts	[edi+OPERAND.OEFLAGS],OMF_OP32
	bts	[ebx+OPERAND.OEFLAGS],OMF_OP32
	bt	DWORD PTR [esi],1
	jc	op32noswap
	xchg	ebx,edi
op32noswap:
	mov	[edi+OPERAND.CODE],al
	REG	esi
	mov	[edi+OPERAND.THEREG],al
	mov	edi,ebx
	RM	esi
	call	setreg
	sub	eax,eax
	ret
op32	ENDP	


;/* op33 - reg,rm,shiftcnt where B3 = reg source, b0 = shift cl */
op33	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	call	copyextra
	call	ReadRM
	mov	ecx,eax
	REG	esi
	mov	edi,ebx
	call	setreg
	mov	edi,offset extraoperand
	mov	[edi+OPERAND.CODE],OM_SHIFT
	bt	DWORD PTR [esi],0
	jnc	short getofs
	bts	[edi+OPERAND.OEFLAGS],OMF_CL
	jmp	short op33done
getofs:
	movzx	eax,BYTE PTR [esi+ecx+2]
	mov	[edi+OPERAND.ADDRESS],eax
op33done:
	mov	eax,ecx
	ret
op33	ENDP	


;/* op 34 - push & pop word, also no reqsPtrSizeOvride single args */
op34	PROC	
	call	ReadRM
	ret
op34	ENDP	


;/* op 35 -floating RM */
op35	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jnz	short op35fsttab
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	call	ReadRM
	ret
op35	endp



op35fsttab	proc
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	movzx	eax,BYTE PTR [esi]
	B12
	shl	eax, OM_FTAB
	or	[edi+OPERAND.OEFLAGS],ax
	call	ReadRM
	ret
op35fsttab	endp


;/* op 36 - floating math & pop */

op36	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	mov	al,[esi+1]
	and	al,0c7h
	cmp	al,0c1h
	jz	op36noarg
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	and	al,7
	call	setreg
	sub	al,al
	xchg	ebx,edi
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	call	setreg
op36noarg:
	sub	eax,eax
	ret
op36	ENDP	


;/* OP 37 - floating MATH */
op37	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jc	op35fsttab
	test	byte ptr [esi],4
	jnz	op37noflop
	xchg	edi,ebx
op37noflop:
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	RM	esi
	call	setreg
	sub	al,al
	xchg	ebx,edi
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	call	setreg
	sub	eax,eax
	ret
op37	ENDP	


;/* op38 - FAR RM */
op38	PROC	
	mov	[reqsPtrSizeOvride],FALSE
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	call	ReadRM
	ret
op38	ENDP	


;/* OP39 - word regrm with reg source */
op39	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
	call	op40
	ret
op39	ENDP	


;/* op 40 regrm with reg source */
op40	PROC	
	mov	[dest2],ebx
	mov	[source2],edi
	call	RegRM
	ret
op40	ENDP	


;/* op 41 reg, bitnum */
op41	PROC	
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	call	ReadRM
	mov	ecx,eax
	mov	edi,ebx
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	push	esi
	add	esi,ecx
	add	esi,2
	call	Immediate
	pop	esi
	mov	eax,ecx
	ret
op41	ENDP	


;/* op 42 mixed regrm with reg dest & reqsPtrSizeOvrideness enforced */

op42	PROC	
	mov	[dest2],edi
	mov	[source2],ebx
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_OP32
	call	RegRM
	mov	[reqsPtrSizeOvride],TRUE
	ret
op42	ENDP	



;/* op 43 CWDE

op43	PROC	
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32	
	jnc	short op43nochng		
	push	esi				
	mov	esi,offset nmmnemonic+1		
	mov	eax,"wde"			
	call	put3				
	mov	BYTE PTR [esi],0			
	pop	esi				
	sub	eax,eax				
op43nochng:
	ret
op43	ENDP	


;/* op 44 BSWAP

op44	PROC
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,[esi]
	and	al,7
	call	setreg
	sub	eax,eax
	ret
op44	ENDP


;/* OP45 - any regrm with reg source */

op45	PROC	
	bt	word ptr [esi-1],0
	jc	op45nb
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	btr	[ebx+OPERAND.OEFLAGS],OMF_BYTE
op45nb:
	XCHG	ebx,edi
	REG	esi
	call	setreg
	XCHG	ebx,edi
	call	ReadRM
	ret
op45	ENDP	


;/* op 46 - floating R/M, pointers to mem */
op46	PROC	
	jmp	op29
op46	ENDP	


;/* op47 - AX */
op47	PROC
	btr	[edi+OPERAND.OEFLAGS],OMF_OP32
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	sub	al,al
	call	setreg
	sub	eax,eax
	ret
op47	ENDP


;/* op48 - 32-bit reg to r02, no prefix (bswap) */
op48	PROC
	bts	[edi+OPERAND.OEFLAGS],OMF_OP32
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,[esi]
	B02
	call	setreg
	sub	eax,eax
	ret
op48	ENDP


;/* op 49, FST */
op49	PROC
	mov	[reqsPtrSizeOvride],FALSE
	MODX	esi
	cmp	al,3
	jnz	op49noreg
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	jmp	short op49fin
op49noreg:
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	movzx	eax,BYTE PTR [esi]
	and	al,6
	jz	op49nxor
	xor	al,6
op49nxor:
	shl	eax, OM_FTAB
	or	[edi+OPERAND.OEFLAGS],ax
op49fin:
	call	ReadRM
	ret
op49	ENDP


;/* op 50, FLD & FSTP */
op50	PROC
	jmp	op49
op50	ENDP


;/* op 51, FBLD/FBSTP */
op51	PROC
	mov	[reqsPtrSizeOvride],FALSE
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	or	[edi+OPERAND.OEFLAGS],4 SHL OM_FTAB
	call	ReadRM
	ret
op51	ENDP


;/* op 52, FILD & FISTP */
op52	PROC
	mov	[reqsPtrSizeOvride],FALSE
	mov	ah,1		; assume dword
	mov	al,[esi]
	cmp	al,0dfh
	jnz	op52dw
	mov	ah,2		; assume qword
	test	byte ptr [esi+1],20h
	jnz	op52dw
	mov	ah,3
op52dw:
	mov	al,ah
	sub	ah,ah
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	shl	eax,OM_FTAB
	or	[edi+OPERAND.OEFLAGS],ax
	call	ReadRM
	ret
op52	ENDP


;/* op 53, FIST & FISTP */
op53	PROC
	jmp	op52
op53	ENDP


;/* op 54, FREG */
op54	PROC
	mov	[reqsPtrSizeOvride],0
	bts	[edi+OPERAND.OEFLAGS],OMF_FST
	call	ReadRM
	ret
op54	ENDP


;/* op 55, FREG if not one */
op55	PROC
	mov	al,[esi+1]
	and	al,7
	cmp	al,1
	jnz	op54
	sub	eax,eax
	ret
op55	ENDP


;/* op 56, FIMATH */
op56	PROC
	mov	[reqsPtrSizeOvride],FALSE
	mov	eax,1
	test	byte ptr [esi],4
	jz	op56go
	mov	al,3
op56go:
	bts	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	shl	eax,OM_FTAB
	or	[edi+OPERAND.OEFLAGS],ax
	call	ReadRM
	ret
op56	ENDP



ReadOverrides	PROC	
      	
ro_lp:
	sub	eax,eax
	lods	BYTE PTR [esi]
	cmp	al,64h
	jc	short testseg
	cmp	al,68h
	jnc	short testseg
	sub	al,64h
	mov	ebx,SG_FS
ro_found:
	mov	cl,al
	shl	ebx,cl
	or	[segs],ebx
	jmp	short ro_lp
testseg:
	push	eax
	and	al,0e7h
	cmp	al,026h
	pop	eax
	jnz	testrep
	mov	ebx,1
	shr	eax,3
	and	al,3
	jmp	ro_found
testrep:
	sub	al,0f2h
	cmp	al,2
	jnc	ro_done
	mov	ebx,SG_REPNZ
	jmp	short ro_found
ro_done:
	dec	esi
	ret
ReadOverrides	ENDP	


DispatchOperands	PROC	
	mov	edx,eax
	push	ebx
	mov	edi,offset nmmnemonic
	push	esi
	mov	esi,[ebx+OPCODE.MNEMONIC]
	call	strcpy
	pop	esi
	mov	[reqsPtrSizeOvride],TRUE
	movzx	eax,[ebx+OPCODE.OPERANDS]
	push	eax
	mov	edi,offset dest
	mov	ebx,offset source
	test	[x86pfx],1
	jz	short notwobyte
	or	[segs],SG_TWOBYTEOP
notwobyte:
	mov	eax,offset extraoperand
	mov	[eax+OPERAND.CODE],0
	mov	[edi+OPERAND.CODE],0
	mov	[ebx+OPERAND.CODE],0
	mov	[edi+OPERAND.OEFLAGS],0
	mov	[ebx+OPERAND.OEFLAGS],0

	
	bt	DWORD PTR [esi],0
	jc	notbyte
	bts	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bts	[ebx+OPERAND.OEFLAGS],OMF_BYTE
notbyte:
	or	edx,edx
	jz	short xadr16
	bts	[edi+OPERAND.OEFLAGS],OMF_ADR32
	bts	[ebx+OPERAND.OEFLAGS],OMF_ADR32
	bts	[edi+OPERAND.OEFLAGS],OMF_OP32
	bts	[ebx+OPERAND.OEFLAGS],OMF_OP32
xadr16:
	test	[segs],SG_ADRSIZ
	jz	do_word1
	btc	[edi+OPERAND.OEFLAGS],OMF_ADR32
	btc	[ebx+OPERAND.OEFLAGS],OMF_ADR32
do_word1:
	test	[segs],SG_OPSIZ
	jz	do_word2
	btc	[edi+OPERAND.OEFLAGS],OMF_OP32
	btc	[ebx+OPERAND.OEFLAGS],OMF_OP32
do_word2:
	pop	eax
	or	eax,eax
	jz	nodispatch
	dec	al
	push	0
	call	TableDispatch
	dd	55
	dd	op1,  op2,  op3,  op4,  op5,  op6,  op7,  op8,  op9,  op10
	dd	op11, op12, op13, op14, op15, op16, op17, op18, op19, op20
	dd	op21, op22, op23, op24, op25, op26, op27, op28, op29, op30
	dd	op31, op32, op33, op34, op35, op36, op37, op38, op39, op40
	dd	op41, op42, op43, op44, op45, op46, op47, op48, op49, op50
	dd	op51, op52, op53, op54, op55, op56
	movzx	eax,al
	add	esi,eax
nodispatch:
	pop	ebx
	movzx	eax,[ebx+OPCODE.OCLENGTH]
	add	esi,eax
	ret
DispatchOperands	ENDP	


DoreqsPtrSizeOvride	PROC	
	push	edi
	push	esi
	test	[reqsPtrSizeOvride],-1
	jz	short floatreqsPtrSizeOvride
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jnc	chkdwptr
	mov	edi,esi
	mov	esi,offset byptr
	jmp	short reqsPtrSizeOvrideend
chkdwptr:
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	mov	edi,esi
	jnc	mkwordptr
	mov	esi,offset dwptr
	jmp	short reqsPtrSizeOvrideend
mkwordptr:
	mov	esi,offset woptr
  	jmp	short reqsPtrSizeOvrideend
floatreqsPtrSizeOvride:
	bt	[edi+OPERAND.OEFLAGS],OMF_FSTTAB
	jnc	reqsPtrSizeOvridedone
	movzx	eax,[edi+OPERAND.OEFLAGS]
	shr	eax,OM_FTAB
	and	eax,7
	mov	edi,esi
	push	edi
	mov	esi,offset sts
	mov	esi,[esi+eax * 4]
	call	strcat
	mov	esi,offset theptr
	pop	edi
reqsPtrSizeOvrideend:
	call	strcat
reqsPtrSizeOvridedone:
	pop	esi
	call	strlen
	add	esi,eax
	pop	edi
	ret
DoreqsPtrSizeOvride	ENDP	

;Tab over to the next location on the display
; INPUT: AL contains the number of positions to move 
;	esi points to a buffer aparently containing display strings?
; If the buffer contains a string whose length exceeds the passed tab
; position, we just add the requested tab position to SI, which now points
; into the middle of that string somewhere.  Otherwise, we stuff spaces into
; the buffer up to the requested tab position.

TabTo	PROC	
	movzx	eax,al		;convert length to dword
	mov	ecx,eax		;put into loop counter
	call	strlen		;find length of string, returned in AX
	xchg	eax,ecx		;tab length now in AX, string length in CX
	sub	eax,ecx		;subtract string length from tab length
	jnc	tt_noover	;if NC, tab length was longer than string
	add	eax,ecx		;else get tab length back into AX
	add	esi,eax		;and add that to buffer pointer
	jmp	short tt_done	;return new buffer position in SI

;We got here if the string in the buffer was shorter than the distance to
;the tab position.  In this case, AX is tab-string, and cx=stringlen.

tt_noover:
	add	esi,ecx		;add string length to SI
	mov	ecx,eax		;put tab-string into cx		
	or	ecx,ecx		;were they the same?
	jnz	tabtlp		;if not, OK
	inc	ecx		;else stash one space anyway
tabtlp:
	mov	BYTE PTR [esi],' '	;space
	inc	esi		;bump pointer into buffer
	loop	tabtlp		;for the remaining positions
tt_done:
	mov	BYTE PTR [esi],0	;put a 0 in the buffer following the spaces
	ret
TabTo	ENDP	


GetST	PROC	
	push	edi
	mov	al,[edi+OPERAND.THEREG]
	push	eax
	xchg	esi,edi
	mov	esi,offset stsreg
	call	strcpy
	pop	eax
	add	al,'0'
	dec	edi
	stosb
	mov	al,')'
	stosb
	sub	al,al
	stosb
	dec	edi
	xchg	esi,edi
	pop	edi
	ret
GetST	ENDP	


GetStdReg	PROC	
	push	edi
	or	al,al
	jnz	short gsrnoe
	mov	BYTE PTR [esi],'e'
	inc	esi
gsrnoe:
	mov	edi,offset regs
	mov	eax,[edi+ecx *2]
	mov	[esi],al
	inc	esi
	mov	[esi],ah
	inc	esi
	mov	BYTE PTR [esi],0
	pop	edi
	ret
GetStdReg	ENDP	


GetReg	PROC	
	movzx	ecx,al
	sub	al,al
	inc	al
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jc	short grno32
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jnc	short grno32
	dec	al
grno32:
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	jc	short isbyte
	or	cl,8
isbyte:
	call	GetStdReg
	ret
GetReg	ENDP	


GetSpecial	PROC	
	mov	al,[ebx]
	mov	[esi],al
	inc	esi
	inc	ebx
	mov	al,[ebx]
	mov	[esi],al
	inc	esi
	inc	ebx
	movzx	eax,[edi+OPERAND.THEREG]
	mov	al,[ebx +eax]
	mov	[esi],al
	inc	esi
	mov	BYTE PTR [esi],0
	ret
GetSpecial	ENDP	


GetSeg	PROC	
	push	edi
	push	eax
	mov	edi,offset psegs
	mov	eax,[edi+ecx *2]
	mov	[esi],al
	inc	esi
	mov	[esi],ah
	inc	esi
	pop	eax
	or	al,al
	mov	al,':'
	jz	short nocolon
	mov	[esi],al
	inc	esi
nocolon:
	mov	BYTE PTR [esi],0
	pop	edi
	ret
GetSeg	ENDP	


SegOverride	PROC	
	mov	al,1
	sub	ecx,ecx
	test	[segs],SG_ES
	jz	short so_testcs
	call	GetSeg
so_testcs:
	inc	ecx
	test	[segs],SG_CS
	jz	short so_testss
	call	GetSeg
so_testss:
	inc	ecx
	test	[segs],SG_SS
	jz	short so_testds
	call	GetSeg
so_testds:
	inc	ecx
	test	[segs],SG_DS
	jz	short so_testfs
	call	GetSeg
so_testfs:
	inc	ecx
	test	[segs],SG_FS
	jz	short so_testgs
	call	GetSeg
so_testgs:
	inc	ecx
	test	[segs],SG_GS
	jz	short so_done
	call	GetSeg
so_done:
	mov	[segs],0
	ret
SegOverride	ENDP	


scaled	PROC	
	push	DWORD PTR [edi+OPERAND.OEFLAGS]
	btr	[edi+OPERAND.OEFLAGS],OMF_BYTE
	bts	[edi+OPERAND.OEFLAGS],OMF_OP32
	or	al,al
	jz	short notbased
	sub	al,al
	mov	al,[edi+OPERAND.THEREG]
	call	GetReg
notbased:
	bt	[edi+OPERAND.OEFLAGS],OMF_SCALED
	jnc	short notscaled2
	mov	byte ptr [esi],'+'
	inc	esi
	mov	al,[edi+OPERAND.SCALEREG]
	call	GetReg
	movzx	ecx,[edi+OPERAND.SCALE]
	or	ecx,ecx
	jz	notscaled2
	add	ecx,ecx
	add	ecx,offset scales
	mov	eax,[ecx]
	call	put2
notscaled2:
	pop	DWORD PTR [edi+OPERAND.OEFLAGS]
	ret
scaled	ENDP	


FOM_FSTREG	PROC	
	mov	edi,offset stalone
	call	strcat
	ret
FOM_FSTREG	ENDP	


FOM_CRX	PROC	
	mov	ebx,offset crreg
	call	GetSpecial
	ret
FOM_CRX	ENDP	


FOM_DRX	PROC	
	mov	ebx,offset drreg
	call	GetSpecial
	ret
FOM_DRX	ENDP	


FOM_TRX	PROC	
	mov	ebx,offset trreg
	call	GetSpecial
	ret
FOM_TRX	ENDP	


FOM_SUD	PROC	
	mov	ebx,offset sudreg
	call	GetSpecial
	ret
FOM_SUD	ENDP	


FOM_PORT	PROC	
	mov	al,SY_PORT
	jmp	FormatValue
FOM_PORT	ENDP	


FOM_INT	PROC	
	mov	al,SY_INTR
	jmp	FormatValue
FOM_INT	ENDP	


FOM_SHIFT	PROC	
	bt	[edi+OPERAND.OEFLAGS],OMF_CL
	jnc	fos_notcl
	mov	eax,"cl"
	call	put2
	ret
fos_notcl:
	cmp	[edi+OPERAND.ADDRESS],1
	mov	al,SY_SHIFT
	jnz	FormatValue
	mov	BYTE PTR [esi],'1'
	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_SHIFT	ENDP	


FOM_RETURN	PROC	
	mov	al,SY_RETURN
	jmp	FormatValue
FOM_RETURN	ENDP	


FOM_SHORTBRANCH	PROC	
	mov	al,SY_SHORTBRANCH
	jmp	FormatValue
FOM_SHORTBRANCH	ENDP	


FOM_LONGBRANCH	PROC	
	mov	al,SY_LONGBRANCH
	jmp	FormatValue
FOM_LONGBRANCH	ENDP	


FOM_FARBRANCH	PROC	
	mov	al,SY_SEGMENT
	call	FormatValue
	mov	BYTE PTR [esi],':'
	inc	esi
	mov	al,SY_ABSBRANCH
	jmp	FormatValue
FOM_FARBRANCH	ENDP	


FOM_ABSOLUTE	PROC	
	call	DoreqsPtrSizeOvride
	call	SegOverride
	mov	BYTE PTR [esi],'['
	inc	esi
	mov	BYTE PTR [esi],0
	bt	[edi+OPERAND.OEFLAGS],OMF_SCALED
	jnc	foa_notscaled
	mov	al,SY_WORDOFS
	call	FormatValue
	sub	eax,eax
	call	scaled
	jmp	short foa_finish
foa_notscaled:
	mov	al,SY_ABSOLUTE
	call	FormatValue
foa_finish:
	mov	BYTE PTR [esi],']'
	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_ABSOLUTE	ENDP	


FOM_IMMEDIATE	PROC	
	bt	[edi+OPERAND.OEFLAGS],OMF_BYTE
	mov	al,SY_WORDIMM
	jnc	short absformat
	push	ebx
	movzx	ebx,byte ptr [edi + OPERAND.ADDRESS]
	mov	[edi + OPERAND.ADDRESS],ebx
	pop	ebx
absformat:
	jmp	FormatValue
FOM_IMMEDIATE	ENDP	


FOM_REG	PROC	
	bt	[edi+OPERAND.OEFLAGS],OMF_FST
	jnc	short foreg
	call	GetST
	ret
foreg:
	mov	al,[edi+OPERAND.THEREG]
	call	GetReg
	ret
FOM_REG	ENDP	


FOM_BASED	PROC	
	call	DoreqsPtrSizeOvride
	call	SegOverride
	mov	BYTE PTR [esi],'['
	inc	esi
	mov	BYTE PTR [esi],0
	bt	[edi+OPERAND.OEFLAGS],OMF_ADR32
	jnc	fob_notscaled
	mov	al,1
	call	scaled
	jmp	short fob2
fob_notscaled:
	push	edi
	push	esi
	movzx	eax,BYTE PTR [edi+OPERAND.THEREG]
	xchg	esi,edi
	mov	esi,offset based
	mov	esi,[esi+eax * 2]
	call	strcpy
	pop	esi
	pop	edi
	call	strlen
	add	esi,eax
fob2:
	test	[edi+OPERAND.OEFLAGS],OMF_OFFSET
	jz	short fob_noofs
	bt	[edi+OPERAND.OEFLAGS],OMF_SIGNED_OFFSET
	mov	al,SY_SIGNEDOFS
	jc	fob_format
	mov	al,SY_WORDOFS
	bt	[edi+OPERAND.OEFLAGS],OMF_WORD_OFFSET
	jc	fob_format
	mov	al,SY_BYTEOFS
fob_format:
	call	FormatValue
fob_noofs:
	mov	BYTE PTR [esi],']'
	inc	esi
	mov	BYTE PTR [esi],0
	ret
FOM_BASED	ENDP	


FOM_SEGMENT	PROC	
	movzx	ecx,[edi+OPERAND.THEREG]
	sub	eax,eax
	call	GetSeg
	ret
FOM_SEGMENT	ENDP	


PutOperand	PROC	
	call	strlen
	add	esi,eax
	mov	al,[edi+OPERAND.CODE]
	dec	al
	js	short po_none
	push	0
	call	TableDispatch
	dd	17
	dd	FOM_BASED
	dd	FOM_SEGMENT
	dd	FOM_REG
	dd	FOM_IMMEDIATE
	dd	FOM_ABSOLUTE
	dd	FOM_FARBRANCH
	dd	FOM_LONGBRANCH
	dd	FOM_SHORTBRANCH
	dd	FOM_RETURN
	dd	FOM_SHIFT
	dd	FOM_INT
	dd	FOM_PORT
	dd	FOM_SUD
	dd	0
	dd      FOM_TRX
	dd      FOM_DRX
	dd      FOM_CRX
	dd      FOM_FSTREG
po_none:
	ret
PutOperand	ENDP	


FormatDisassembly	PROC	
	ENTER	256,0
	push	esi
	lea	edi,[ebp-256]
	mov	BYTE PTR [edi],0
	test	[segs],SG_REPZ
	push	edi
	jz	fd_notrepz
	mov	esi,offset st_repz
	call	strcpy
fd_notrepz:
	test	[segs],SG_REPNZ
	jz	fd_notrepnz
	mov	esi,offset st_repnz
	call	strcpy
fd_notrepnz:
	pop	edi
	xchg	esi,edi
	call	strlen
	add	esi,eax
	xchg	esi,edi
	mov	esi,offset nmmnemonic
	call	strcat
	lea	esi,[ebp-256]
	sub	eax,eax
	mov	al,TAB_ARGPOS
	call	TabTo
	mov	edi,offset dest
	call	PutOperand
	mov	edi,offset source
	test	[edi+OPERAND.CODE],-1
	jz	short nosource
	mov	BYTE PTR [esi],','
	inc	esi
	mov	BYTE PTR [esi],0
	call	PutOperand
nosource:
	mov	edi,offset extraoperand
	test	[edi+OPERAND.CODE],-1
	jz	short noextra
	mov	BYTE PTR [esi],','
	inc	esi
	mov	BYTE PTR [esi],0
	call	PutOperand
noextra:
	pop	esi	
	mov	BYTE PTR [esi],0
	call	SegOverride
	mov	edi,esi
	lea	esi,[ebp-256]
	call	strcat
	LEAVE
	ret
FormatDisassembly	ENDP	


PutDword:
	push	eax		; To print a dword
	shr	eax,16		; Print the high 16 bits
	call	PutWord
	pop	eax		; And the low 16 bits
PutWord:
	push	eax		; To print a word
	mov	al,ah		; Print the high byte
	call	PutByte
	pop	eax		; And the low byte
PutByte:
	push	eax		; To print a byte
	shr	eax,4		; Print the high nibble
	call	putnibble
	pop	eax		; And the low nibble
putnibble:
	and	al,0fh		; Get a nibble
	add	al,'0'		; Make it numeric
	cmp	al,'9'		; If supposed to be alphabetic
	jle	onib
	add	al,7		; Add 7
onib:
	mov	[esi],al
	inc	esi
	ret

PutWordox:
	bt	[edi+OPERAND.OEFLAGS],OMF_OP32
	jnc	PutWord
	jmp	PutDword
PutWordax:
	bt	[edi+OPERAND.OEFLAGS],OMF_ADR32
	jnc	PutWord
	jmp	PutDword
FSY_SIGNEDOFS	PROC	
	push	ebx
	mov	eax,[edi+OPERAND.ADDRESS]
	bt	eax,7
	mov	bl,'+'
	jnc	fso_pos
	mov	bl,'-'
	neg	al
fso_pos:
	mov	byte ptr [esi],bl
	inc	esi
	call	PutByte
	pop	ebx
	ret
FSY_SIGNEDOFS	ENDP	


FSY_WORDOFS	PROC	
	push	ebx
	mov	eax,[edi+OPERAND.ADDRESS]
	cmp	eax,-4000h
	mov	bl,'+'
	jc	fsy_wouseplus
	neg	eax
	mov	bl,'-'
fsy_wouseplus:
	mov	byte ptr [esi],bl
	inc	esi
	call	PutWordax
	pop	ebx
	ret
FSY_WORDOFS	ENDP	


FSY_BYTEOFS	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutByte
	ret
FSY_BYTEOFS	ENDP	


FSY_ABSOLUTE	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutWordax
	ret
FSY_ABSOLUTE	ENDP	


FSY_SIGNEDIMM	PROC	
	jmp	FSY_SIGNEDOFS
FSY_SIGNEDIMM	ENDP	


FSY_WORDIMM	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutWordox
	ret
FSY_WORDIMM	ENDP	


FSY_BYTEIMM	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutByte
	ret
FSY_BYTEIMM	ENDP	


FSY_PORT	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutByte
	ret
FSY_PORT	ENDP	


FSY_INTR	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutByte
	ret
FSY_INTR	ENDP	


FSY_RETURN	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutWord
	ret
FSY_RETURN	ENDP	


FSY_ABSBRANCH	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutDword
	ret
FSY_ABSBRANCH	ENDP	


FSY_LONGBRANCH	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutDword
	ret
FSY_LONGBRANCH	ENDP	


FSY_SHORTBRANCH	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutDword
	ret
FSY_SHORTBRANCH	ENDP	


FSY_SHIFT	PROC	
	mov	eax,[edi+OPERAND.ADDRESS]
	call	PutByte
	ret
FSY_SHIFT	ENDP	


FSY_SEGMENT	PROC	
	mov	ax,[edi+OPERAND.OESEG]
	call	PutWord
	ret
FSY_SEGMENT	ENDP	


FormatValue	PROC	
	dec	al
	push	0
	call	TableDispatch
	dd	14
	dd	FSY_SIGNEDOFS,FSY_WORDOFS,FSY_BYTEOFS,FSY_ABSOLUTE
	dd	FSY_SIGNEDIMM,FSY_WORDIMM,FSY_BYTEIMM,FSY_PORT
	dd	FSY_INTR,FSY_RETURN,FSY_ABSBRANCH,FSY_LONGBRANCH
	dd	FSY_SHORTBRANCH,FSY_SHIFT,FSY_SEGMENT
	mov	byte ptr [esi],0
	ret
FormatValue	ENDP	




































































END