;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
;°±²									     °±²
;°±²  486 DisAssembler v0.22, (C) 1995 Sami Kantoluoto a.k.a. TS/i303        °±²
;°±²  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  °±²
;°±²									     °±²
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
		.386P
;°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°
;Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û
;°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°
_PMODE_TEXT	Segment Para Public Use16 'CODE'
		Assume	CS:_PMODE_TEXT,DS:_PMODE_TEXT
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
Extrn   OpMap1:Word, Second:Word, Groups:Word, FSpecial:Word, FloatOps:Word
Public	UnAssemble,Instruction_Off,Instruction_Len,UBuf,SegSize,Real_Offset
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
o		equ	offset
Extrn		HexTable:Byte
SegSize 	db	16,0			; Code segment size
Instruction_Off dd	0
Real_Offset	dd	0
Instruction_Len db	0,0
OpSize		db	0,0
AddrSize	db	0,0
modRMV		dw	0
SIBV		dw	0
Prefix		db	0,0
WordOp		db	0,0
ShowZero	db	0,0
R		db	0,0
Extend		db	0
SExt		db	0

UBufP		dw	0
UBuf		db	128 dup (0)

PrefixStr	db	"%p:[",0
EF_Str		db	" %EF",0
Invalid 	db	"(Invalid)",0
Illegal 	db	"<Illegal>",0
BytePtr         db      "byte ptr ",0          ; These aren't included yet
WordPtr         db      "word ptr ",0
DWordPtr        db      "dword ptr ",0
FWordPtr        db      "fword ptr ",0
;ShortPtr	 db	 "short ptr ",0
;NearPtr	 db	 "near ptr ",0
;FarPtr 	 db	 "far ptr ",0

		Align	4
RegTable8	label	word
		db	"al","cl","dl","bl"
		db	"ah","ch","dh","bh"
RegTable16	label	word
		db	"ax","cx","dx","bx"
		db	"sp","bp","si","di"
SRegTable	label	word
		db	"es","cs","ss","ds"
		db	"fs","gs","?s","!s"
_Goto		Macro	A
		dw	(A-(($-o Per_Table) shr 1)-'1') dup (o Per_Illegal)
		EndM
Per_Table	label	word
		;_Goto	 '1'
		dw	o Per_Type_1,o Per_Type_2
		dw	o Per_Type_3
		_Goto	'A'
		dw	o Per_Type_A_,o Per_Illegal
		dw	o Per_Type_C_,o Per_Type_D_
                dw      o Per_Type_E_,o Per_Illegal
		dw	o Per_Type_G_,o Per_Illegal
		dw	o Per_Type_I_,o Per_Type_J_
		dw	o Per_Illegal,o Per_Illegal
		dw	o Per_Type_M_,o Per_Illegal
		dw	o Per_Type_O_,o Per_Illegal
		dw	o Per_Illegal,o Per_Type_R_
		dw	o Per_Type_S_,o Per_Type_T_
		_Goto	'X'
		dw	o Per_Type_X_,o Per_Type_Y_
                _Goto   'a'
                dw      o Per_Type_a
                dw      o Per_Type_b,o Per_Illegal
		dw	o Per_Type_d,o Per_Type_e
		dw	o Per_Type_f,o Per_Type_g
		_Goto	'p'
		dw	o Per_Type_p,o Per_Type_q
		dw	o Per_Type_r,o Per_Type_s
		_Goto	'w'
		dw	o Per_Type_w

RMRegTable32	dw	o REAX,o RECX,o REDX,o REBX,o RNOT,o REBP,o RESI,o REDI
RMRegTable16	dw	o BXSI,o BXDI,o BPSI,o BPDI,o RSI,o RDI,o RBP,o RBX
SIB_RegTable	dw	o REAX,o RECX,o REDX,o REBX,o RESP,o REBP,o RESI,o REDI

REAX		db	"eax",0
RECX		db	"ecx",0
REDX		db	"edx",0
REBX		db	"ebx"
RNOT		db	0
RESP		db	"esp",0
REBP		db	"ebp",0
RESI		db	"esi",0
REDI		db	"edi",0
BXSI		db	"bx+si",0
BXDI		db	"bx+di",0
BPSI		db	"bp+si",0
BPDI		db	"bp+di",0
RSI		db	"si",0
RDI		db	"di",0
RBP		db	"bp",0
RBX		db	"bx",0
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
@MOD		Macro	A
		shr	A,6
		and	A,7
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
@REG		Macro	A
		shr	A,3
		and	A,7
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
@RM		Macro	A
		and	A,7
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
@SCALE		equ	@MOD
@INDEX		equ	@REG
@BASE		equ	@RM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetByteRS	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		inc	Instruction_Len
		inc	Instruction_Off
		inc	Real_Offset
		movsx	A,byte ptr fs:[esi]
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetByteR	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		inc	Instruction_Len
		inc	Instruction_Off
		inc	Real_Offset
		mov	A,fs:[esi]
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetByte 	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		inc	Instruction_Len
		inc	Instruction_Off
		inc	Real_Offset
		mov	al,fs:[esi]
		IFNB	<A>
		mov	A,al
		ENDIF
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetWordRS	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		add	Instruction_Len,2
		add	Instruction_Off,2
		add	Real_Offset,2
		movsx	A,word ptr fs:[esi]
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetWordR	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		add	Instruction_Len,2
		add	Instruction_Off,2
		add	Real_Offset,2
		mov	A,fs:[esi]
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetWord 	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		add	Instruction_Len,2
		add	Instruction_Off,2
		add	Real_Offset,2
		mov	ax,fs:[esi]
		IFNB	<A>
		mov	a,ax
		ENDIF
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetDWordR	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		add	Instruction_Len,4
		add	Instruction_Off,4
		add	Real_Offset,4
		mov	a,fs:[esi]
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
GetDWord	Macro	A,B
		IFNB	<B>
		push	esi
		ENDIF
		mov	esi,Instruction_Off
		add	Instruction_Len,4
		add	Instruction_Off,4
		add	Real_Offset,4
		mov	eax,fs:[esi]
		INFB	<A>
		mov	a,eax
		ENDIF
		IFNB	<B>
		pop	esi
		ENDIF
		EndM
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
ModRM		Proc	near
		mov	ax,modRMV
		cmp	ax,-1
		jne	ModRM_Exit
		xor	ah,ah
		GetByte
		mov	modRMV,ax
ModRM_Exit:	ret
ModRM		EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
SIB		Proc	near
		mov	ax,SIBV
		cmp	ax,-1
		jne	SIB_Exit
		xor	ah,ah
		GetByte
		mov	SIBV,ax
SIB_Exit:	ret
SIB		EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
Percent 	Proc	Pascal Near
		ARG	_Type:Byte,SubType:Byte

		mov	al,SubType
		mov	bx,word ptr _Type
		cmp	bx,'w'
		ja	Per_Illegal
		cmp	bx,'1'
		jb	Per_Illegal
		add	bx,bx
		jmp	ds:Per_Table[bx-62h]

Per_Type_A_:	cmp	OpSize,32
		jne	Per_A_16
		GetDWordR ebx
		GetWordR dx
		mov	di,UBufP
		add	UBufP,13
		mov	cl,4
		call	PrintHex
		mov	byte ptr ds:[di],':'
		inc	di
		mov	edx,ebx
		mov	cl,8
		call	PrintHex
		jmp	Per_Exit
Per_A_16:	GetWordR bx
		GetWordR dx
		mov	di,UBufP
		add	UBufP,9
		mov	cl,4
		call	PrintHex
		mov	byte ptr ds:[di],':'
		inc	di
		mov	dx,bx
		mov	cl,4
		call	PrintHex
		jmp	Per_Exit

Per_Type_C_:	mov	di,UBufP
		add	UBufP,3
		mov	word ptr ds:[di],'rc'
		call	modRM
		@REG	al
		add	al,'0'
		mov	ds:[di+2],al
		jmp	Per_Exit

Per_Type_D_:	mov	di,UBufP
		add	UBufP,3
		mov	word ptr ds:[di],'rd'
		call	modRM
		@REG	al
		add	al,'0'
		mov	ds:[di+2],al
		jmp	Per_Exit

Per_Type_E_:	cmp	al,'r'
		jne	Per_E_Call
		push	word ptr R
		call	do_modRM
		jmp	Per_Exit
Per_E_Call:	push	word ptr SubType
		call	do_modRM
		jmp	Per_Exit

Per_Type_G_:	cmp	al,'F'
		jne	Per_G_Cont
Per_FloatReg:	call	modRM
		@RM	al
		mov	ah,')'
		add	al,'0'
		mov	di,UBufP
		add	UBufP,5
		mov	dword ptr ds:[di],' (ts'
		mov	word ptr ds:[di+3],ax
		jmp	Per_Exit
Per_G_Cont:	call	modRM
		mov	bx,ax
		@REG	bl
		add	bl,bl
		mov	al,SubType
		cmp	al,'b'
		je	Per_G_Sub_b
		or	WordOp,0
		jnz	Per_G_WOP
		cmp	al,'c'
		jne	Per_G_WOP
Per_G_Sub_b:	mov	di,UBufP
		add	UBufP,2
		mov	ax,RegTable8[bx]
		mov	ds:[di],ax
		jmp	Per_Exit
Per_G_WOP:	cmp	al,'d'
		je	Per_G_Ext
		cmp	OpSize,32
		jne	Per_G_16
		cmp	al,'v'
		jne	Per_G_16
Per_G_Ext:	mov	di,UBufP
		inc	UBufP
		mov	byte ptr ds:[di],'e'
Per_G_16:	mov	di,UBufP
		add	UBufP,2
		mov	ax,RegTable16[bx]
		mov	ds:[di],ax
		jmp	Per_Exit

Per_Type_I_:	mov	al,SubType
		cmp	al,'r'
		jne	Per_I_Cont
		mov	al,R
Per_I_Cont:	cmp	al,'d'
		je	Per_I_DD
		cmp	OpSize,32
		jne	Per_I_Not_DD
		cmp	al,'v'
		je	Per_I_DD
		cmp	al,'c'
		jne	Per_I_Not_DD
		or	WordOp,0
		jnz	Per_I_b
Per_I_DD:	mov	di,UBufP
		add	UBufP,8
		GetDWordR edx
		mov	cl,8
		call	PrintHex
		jmp	Per_Exit
Per_I_Not_DD:	cmp	al,'b'
		je	Per_I_b
		cmp	al,'w'
		je	Per_I_w
		cmp	al,'c'
		je	Per_I_c
		cmp	al,'v'
		jne	Per_Illegal
Per_I_w:	mov	di,UBufP
		add	UBufP,4
		GetWordR dx
		mov	cl,4
		call	PrintHex
		jmp	Per_Exit
Per_I_b:	xor	edx,edx
		GetByteR dl
		or	SExt,0
		jz	Per_I_b_
		movsx	edx,dl
Per_I_b_:	xor	ch,ch
		mov	cl,Extend
		mov	di,UBufP
		add	UBufP,cx
		call	PrintHex
		jmp	Per_Exit
Per_I_c:	or	WordOp,0
		jz	Per_I_b
		jmp	Per_I_w

Per_Type_J_:	xor	eax,eax
		mov	cx,1
		mov	bl,SubType
		cmp	bl,'b'
		je	Per_J_N_OK
		add	cl,cl
		cmp	bl,'w'
		je	Per_J_N_OK
		add	cl,cl
		cmp	bl,'d'
		je	Per_J_N_OK
		cmp	bl,'v'
		jne	Per_Illegal
		cmp	OpSize,32
		je	Per_J_N_OK
		mov	cl,2
		jmp	Per_J_N_OK
Per_J_N_OK:	mov	ch,cl
Per_J_Loop:	ror	eax,8
		GetByte
		dec	cl
		jnz	Per_J_Loop
		mov	cl,ch
		dec	cl
		shl	cl,3
		rol	eax,cl
		cmp	ch,1
		ja	Per_J_C1
		cbw
Per_J_C1:	cmp	ch,2
		ja	Per_J_C2
		cwde
Per_J_C2:	add	eax,Real_Offset
		mov	edx,eax
		mov	cx,4
		cmp	AddrSize,16
		je	Per_J_C3
		mov	cl,8
Per_J_C3:	mov	di,UBufP
		add	UBufP,cx
		call	PrintHex
		jmp	Per_Exit

;Per_Type_K_:	 mov	 di,UBufP
;		 mov	 al,SubType
;		 mov	 si,offset ShortPtr
;		 cmp	 al,'s'
;		 je	 Per_K_CStr
;		 mov	 si,offset NearPtr
;		 cmp	 al,'n'
;		 je	 Per_K_CStr
;		 mov	 si,offset FarPtr
;Per_K_CStr:	 call	 CopyStr
;		 mov	 UBufP,di
;		 jmp	 Per_Exit

Per_Type_M_:	call	modRM
		@MOD	al
		cmp	al,3
		jne	Per_M_Call
		call	PrintInv
Per_M_Call:	push	word ptr SubType
		call	do_modRM
		jmp	Per_Exit

Per_Type_O_:	push	offset PrefixStr
		call	UA_Str
		mov	di,UBufP
		cmp	AddrSize,32
		jne	Per_O_16
		add	UBufP,9
		GetDWordR edx
		mov	cl,8
		call	PrintHex
		mov	byte ptr ds:[di],']'
		jmp	Per_Exit
Per_O_16:	add	UBufP,5
		GetWordR dx
		mov	cl,4
		call	PrintHex
		mov	byte ptr ds:[di],']'
		jmp	Per_Exit

Per_Type_R_:	call	modRM
		@MOD	al
		cmp	al,3
		je	Per_R_Call
		call	PrintInv
Per_R_Call:	push	word ptr SubType
		call	do_modRM
		jmp	Per_Exit

Per_Type_S_:	mov	di,UBufP
		add	UBufP,2
		call	modRM
		@REG	al
		mov	bx,ax
		add	bx,ax
		mov	ax,ds:SRegTable[bx]
		mov	ds:[di],ax
		jmp	Per_Exit

Per_Type_T_:	mov	di,UBufP
		add	UBufP,3
		call	modRM
		mov	word ptr ds:[di],'rt'
		@REG	al
		add	al,'0'
		mov	ds:[di+2],al
		jmp	Per_Exit

Per_Type_X_:	mov	di,UBufP
		add	UBufP,7
		mov	eax,'[:sd'
		or	Prefix,0
		jz	Per_X_Cont
		mov	al,Prefix
Per_X_Cont:	mov	ds:[di],eax
		lea	di,[di+4]
		cmp	AddrSize,32
		jne	Per_X_Rest
		inc	UBufP
		mov	byte ptr ds:[di],'e'
		inc	di
Per_X_Rest:	mov	dword ptr ds:[di],']is'
		jmp	Per_Exit

Per_Type_Y_:	mov	di,UBufP
		add	UBufP,7
		mov	dword ptr ds:[di],'[:se'
		lea	di,[di+4]
		cmp	AddrSize,32
		jne	Per_Y_Rest
		inc	UBufP
		mov	byte ptr ds:[di],'e'
		inc	di
Per_Y_Rest:	mov	dword ptr ds:[di],']id'
		jmp	Per_Exit

Per_Type_1:	sub	al,'0'
		movzx	eax,al
		add	Instruction_Off,eax
		add	Real_Offset,eax
		jmp	Per_Exit

Per_Type_2:	xor	bh,bh
		GetByteR bl
		add	bx,bx
		push	ds:Second[bx]
		call	UA_Str
		jmp	Per_Exit

Per_Type_3:	cmp	al,'v'
		je	Per_T_v
		cmp	al,'w'
		jne	Per_T_v
Per_T_w:	mov	ah,OpSize
		shr	ah,2
		mov	Extend,ah
		jmp	Per_Exit
Per_T_v:	mov	ah,OpSize
		shr	ah,2
		mov	Extend,ah
		mov	SExt,1
		jmp	Per_Exit
Per_T_3:	sub	al,'0'
		mov	Extend,al
		mov	SExt,1
		jmp	Per_Exit

Per_Type_a:     cmp     AddrSize,32
                jne     Per_Exit
                mov     di,UBufP
                inc     UBufP
                mov     ds:[di],al
                jmp     Per_Exit

Per_Type_b:     mov     di,UBufP
		inc	UBufP
		mov	byte ptr ds:[di],'b'
		cmp	OpSize,16
		je	Per_Exit
		mov	al,SubType
		mov	ds:[di],al
		cmp	al,' '
		jne	Per_Exit
		dec	UBufP
		jmp	Per_Exit

Per_Type_d:	mov	di,UBufP
		inc	UBufP
		cmp	OpSize,32
		jne	Per_d_c
		inc	UBufP
		mov	byte ptr ds:[di],'d'
		inc	di
Per_d_c:	mov	al,SubType
		mov	ds:[di],al
		jmp	Per_Exit

Per_Type_e:	mov	di,UBufP
		inc	UBufP
		cmp	OpSize,32
		jne	Per_e_c
		inc	UBufP
		mov	byte ptr ds:[di],'e'
		inc	di
Per_e_c:	mov	al,SubType
		mov	ds:[di],al
		jmp	Per_Exit

Per_Type_f:	; Floating point Op.
		sub	al,'0'
		shl	al,3
		xor	bh,bh
		mov	bl,al
		call	modRM
		mov	cx,ax
		@REG	al
		add	bx,ax		; BX = Esc
		add	bx,bx
		@MOD	cl
		cmp	cl,3
		je	Per_f_Special
Per_f_normal:	push	FloatOps[bx]
		call	UA_Str
		push	offset EF_Str
		call	UA_Str
		jmp	Per_Exit
Per_f_Special:	or	FSpecial[bx],0
		jz	Per_f_normal
		mov	bx,FSpecial[bx]
		mov	si,[bx]
		cmp	byte ptr ds:[si],'*'
		jne	Per_f_spec_nast
		inc	si
		push	si
		call	UA_Str
		jmp	Per_Exit
Per_f_spec_nast:call	modRM
		@RM	al
		add	al,al
		add	bx,ax
		push	word ptr [bx]
		call	UA_Str
		jmp	Per_Exit

Per_Type_g:	mov	bx,word ptr SubType
		sub	bl,'0'
		shl	bx,4
		call	modRM
		@REG	al
		add	ax,ax
		add	bx,ax
		push	ds:Groups[bx]
		call	UA_Str
		jmp	Per_Exit

Per_Type_p:	mov	al,SubType
		cmp	al,':'
		je	Per_p_Prefix
		cmp	al,' '
		je	Per_Next_Op
		mov	Prefix,al
		jmp	Per_Next_Op
Per_p_Prefix:	mov	al,Prefix
		or	al,al
		jz	Per_Exit
		mov	di,UBufP
		add	UBufP,3
		mov	ds:[di],al
		mov	word ptr ds:[di+1],':s'
		jmp	Per_Exit
Per_Next_Op:	xor	ah,ah
		GetByte
		mov	bx,ax
		add	bx,ax
		and	al,1
		mov	WordOp,al
		push	OpMap1[bx]
		call	UA_Str
		jmp	Per_Exit

Per_Type_q:	cmp	OpSize,32
		jne	Per_Exit
		mov	al,SubType
		mov	di,UBufP
		inc	UBufP
		mov	ds:[di],al
		jmp	Per_Exit

Per_Type_r:	mov	al,SubType
		mov	R,al
		jmp	Per_Exit

Per_Type_s:	cmp	SubType,'a'
		je	Per_s_Addr
		or	OpSize+1,0
		jnz	Per_Next_Op
		or	OpSize+1,1
		mov	al,48
		sub	al,OpSize
		mov	OpSize,al
		jmp	Per_Next_Op
Per_s_Addr:	or	AddrSize+1,0
		jnz	Per_Next_Op
		or	AddrSize+1,1
		mov	al,48
		sub	al,AddrSize
		mov	AddrSize,al
		jmp	Per_Next_Op

Per_Type_w:	mov	di,UBufP
		inc	UBufP
		mov	al,SubType
		mov	byte ptr ds:[di],'w'
		cmp	OpSize,16
		je	Per_Exit
		mov	byte ptr ds:[di],al
		cmp	al,' '
		jne	Per_Exit
		dec	UBufP
		jmp	Per_Exit

Per_Illegal:	mov	di,UBufP
		mov	si,offset Illegal
		call	CopyStr
		mov	UBufP,di
Per_Exit:	ret
Percent 	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
do_modRM	Proc	Pascal Near
		ARG	SubType:Byte
		LOCAL	_MOD_:Word,_RM_:Word

		call	modRM
		mov	bx,ax

		@MOD	al
		@RM	bl

		mov	cl,SubType

		cmp	al,3
		jne	dmRM_MOD_n3
		; MOD = 3 (Specifies register)
		cmp	SubType,'F'
		je	dmRM_FloatReg
		cmp	cl,'b'
		je	dmRM_MOD3_b
		or	WordOp,0
		jnz	dmRM_MOD3_WOP
		cmp	cl,'c'
		jne	dmRM_MOD3_WOP2
dmRM_MOD3_b:	add	bx,bx
		mov	ax,ds:RegTable8[bx]
		mov	di,UBufP
		add	UBufP,2
		mov	ds:[di],ax
		jmp	dmRM_Exit
dmRM_FloatReg:	leave
		pop	ax
		jmp	Per_FloatReg

dmRM_MOD3_WOP:	cmp	cl,'c'
		je	dmRM_MOD3_c
dmRM_MOD3_WOP2: cmp	cl,'d'
		je	dmRM_MOD3_Ext
                cmp     cl,'W'
                je      dmRM_MOD3_c
                cmp     cl,'v'
		jne	dmRM_MOD3_PReg
dmRM_MOD3_c:	cmp	OpSize,32
		jne	dmRM_MOD3_PReg
dmRM_MOD3_Ext:	mov	di,UBufP
		inc	UBufP
		mov	byte ptr ds:[di],'e'
dmRM_MOD3_PReg: add	bx,bx
		mov	di,UBufP
		add	UBufP,2
		mov	ax,ds:RegTable16[bx]
		mov	ds:[di],ax
		jmp	dmRM_Exit

dmRM_MOD_n3:    cmp     cl,'b'
                mov     si,offset BytePtr
                je      dmRM_MOD_n3_ptr
                mov     si,offset WordPtr
                cmp     cl,'W'
                je      dmRM_MOD_n3_ptr
                cmp     cl,'w'
                je      dmRM_MOD_n3_ptr
                mov     si,offset DWordPtr
                cmp     cl,'d'
                je      dmRM_MOD_n3_ptr
                cmp     cl,'p'
                jne     dmRM_MODn3_subv

                cmp     OpSize,32
                jne     dmRM_MOD_n3_ptr
                mov     si,offset FWordPtr
                jmp     dmRM_MOD_n3_ptr

dmRM_MODn3_subv:cmp     OpSize,32
                je      dmRM_MOD_n3_ptr
                mov     si,offset WordPtr

dmRM_MOD_n3_ptr:mov     di,UBufP
                call    CopyStr
                mov     UBufP,di

                mov     _MOD_,ax
		mov	_RM_,bx
		push	offset PrefixStr
		call	UA_Str
		cmp	AddrSize,32
		jne	dmRM_16
		cmp	_RM_,4
		jne	dmRM_32_C
		push	_MOD_
		call	do_SIB
		jmp	dmRM_Exit2
dmRM_32_C:	mov	bx,_RM_
		add	bl,bl
		mov	al,byte ptr _MOD_
		or	al,al
		jz	dmRM_32_m0
		cmp	al,1
		je	dmRM_32_m1

dmRM_32_m2:	mov	di,UBufP
		mov	si,RMRegTable32[bx]
		call	CopyStr
		mov	UBufP,di
		GetDWordR edx
		mov	al,'+'
		or	ShowZero,0
		jnz	dmRM_32_m2SNum2
		or	edx,edx
		jz	dmRM_Exit2
dmRM_32_m2SNum2:or	edx,edx
		jns	dmRM_32_m2_SNum
		mov	al,'-'
		neg	edx
dmRM_32_m2_SNum:add	UBufP,9
		mov	ds:[di],al
		inc	di
		mov	cl,8
		call	PrintHex
		jmp	dmRM_Exit2

dmRM_32_m1:	mov	di,UBufP
		mov	si,RMRegTable32[bx]
		call	CopyStr
		mov	UBufP,di
		GetByteR dl
		mov	al,'+'
		or	ShowZero,0
		jnz	dmRM_m1_32SNum2
		or	dl,dl
		jz	dmRM_Exit2
dmRM_m1_32SNum2:or	dl,dl
		jns	dmRM_32_m1_SNum
		mov	al,'-'
		neg	dl
dmRM_32_m1_SNum:add	UBufP,3
		mov	ds:[di],al
		inc	di
		mov	cl,2
		call	PrintHex
		jmp	dmRM_Exit2

dmRM_32_m0:	mov	di,UBufP
		mov	si,RMRegTable32[bx]
		cmp	bl,5*2
		je	dmRM_32_m0_Addr
		call	CopyStr
		mov	UBufP,di
		jmp	dmRM_Exit2
dmRM_32_m0_Addr:add	UBufP,8
		GetDWordR edx
		mov	cl,8
		call	PrintHex
		jmp	dmRM_Exit2

dmRM_16:	mov	ax,_MOD_
		mov	bx,_RM_
		add	bl,bl
		or	al,al
		jz	dmRM_16_m0
		cmp	al,1
		je	dmRM_16_m1

dmRM_16_m2:	mov	di,UBufP
		mov	si,RMRegTable16[bx]
		call	CopyStr
		mov	UBufP,di
		mov	al,'+'
		GetWordR dx
		or	ShowZero,0
		jnz	dmRM_16_m2SNum2
		or	dx,dx
		jz	dmRM_Exit2
dmRM_16_m2SNum2:or	dx,dx
		jns	dmRM_16_m2_SNum
		mov	al,'-'
		neg	dx
dmRM_16_m2_SNum:add	UBufP,5
		mov	ds:[di],al
		inc	di
		mov	cl,4
		call	PrintHex
		jmp	dmRM_Exit2

dmRM_16_m1:	mov	di,UBufP
		mov	si,RMRegTable16[bx]
		call	CopyStr
		mov	UBufP,di
		mov	al,'+'
		GetByteR dl
		or	ShowZero,0
		jnz	dmRM_16_m1SNum2
		or	dl,dl
		jz	dmRM_Exit2
dmRM_16_m1SNum2:or	dl,dl
		jns	dmRM_16_m1_SNum
		mov	al,'-'
		neg	dl
dmRM_16_m1_SNum:add	UBufP,3
		mov	ds:[di],al
		inc	di
		mov	cl,2
		call	PrintHex
		jmp	dmRM_Exit2

dmRM_16_m0:	mov	di,UBufP
		mov	si,RMRegTable16[bx]
		cmp	bx,6*2
		je	dmRM_16_m0_Addr
		call	CopyStr
		mov	UBufP,di
		jmp	dmRM_Exit2
dmRM_16_m0_Addr:add	UBufP,4
		GetWordR dx
		mov	cl,4
		call	PrintHex

dmRM_Exit2:	mov	di,UBufP
		inc	UBufP
		mov	byte ptr ds:[di],']'
dmRM_Exit:	ret
do_modRM	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
do_SIB		Proc	Pascal Near
		ARG	_MOD_:Byte

		call	SIB
		mov	bx,ax
		mov	si,ax

		@SCALE	al
		@INDEX	bl
		@BASE	si

		add	si,si
		add	bx,bx

		mov	dl,_MOD_
		or	dl,dl
		jz	dSIB_m0
		cmp	dl,1
		jne	dSIB_m2

dSIB_m1:	mov	di,UBufP
		mov	si,ds:SIB_RegTable[si]
		call	CopyStr
		cmp	bl,4*2
		je	dSIB_m1_In_Done
		mov	byte ptr ds:[di],'+'
		inc	di
		mov	si,ds:SIB_RegTable[bx]
		call	CopyStr
		or	al,al
		jz	dSIB_m1_In_Done
		mov	cl,al
		mov	ah,1
		shl	ah,cl
		add	ah,'0'
		mov	al,'*'
		mov	ds:[di],ax
		lea	di,[di+2]
dSIB_m1_In_Done:mov	UBufP,di
		GetByte dl
		mov	al,'+'
		or	ShowZero,0
		jnz	dSIB_m1_SNum_2
		or	dl,dl
		jz	dSIB_Exit
dSIB_m1_SNum_2: or	dl,dl
		jns	dSIB_m1_SNum
		neg	dl
		mov	al,'-'
dSIB_m1_SNum:	mov	ds:[di],al
		inc	di
		mov	cl,2
		call	PrintHex
		mov	UBufP,di
		jmp	dSIB_Exit

dSIB_m2:	mov	di,UBufP
		mov	si,ds:SIB_RegTable[si]
		call	CopyStr
		cmp	bl,4*2
		je	dSIB_m2_In_Done
		mov	byte ptr ds:[di],'+'
		inc	di
		mov	si,ds:SIB_RegTable[bx]
		call	CopyStr
		or	al,al
		jz	dSIB_m2_In_Done
		mov	cl,al
		mov	ah,1
		shl	ah,cl
		add	ah,'0'
		mov	al,'*'
		mov	ds:[di],ax
		lea	di,[di+2]
dSIB_m2_In_Done:mov	UBufP,di
		GetDWordR edx
		mov	al,'+'
		or	ShowZero,0
		jnz	dSIB_m2_SNum_2
		or	edx,edx
		jz	dSIB_Exit
dSIB_m2_SNum_2: or	edx,edx
		jns	dSIB_m2_SNum
		neg	edx
		mov	al,'-'
dSIB_m2_SNum:	mov	ds:[di],al
		inc	di
		mov	cl,8
		call	PrintHex
		mov	UBufP,di
		jmp	dSIB_Exit

dSIB_m0:	mov	di,UBufP
		cmp	si,5*2
		mov	si,ds:SIB_RegTable[si]
		jne	dSIB_m0_Bn5
		GetDWordR edx
		or	edx,edx
		jnz	dSIB_m0_B5_SNum
		dec	di
		cmp	bl,4*2
		jne	dSIB_m0_Sn4_2
dSIB_m0_B5_SNum:mov	cl,8
		mov	ah,al
		call	PrintHex
		mov	al,ah
		jmp	dSIB_m0_Bx
dSIB_m0_Bn5:	call	CopyStr
dSIB_m0_Bx:	mov	UBufP,di
		cmp	bl,4*2
		je	dSIB_Exit
dSIB_m0_Sn4:	mov	byte ptr ds:[di],'+'
		inc	di
dSIB_m0_Sn4_2:	mov	si,ds:SIB_RegTable[bx]
		call	CopyStr
		or	al,al
		jz	dSIB_Exit2
		mov	cl,al
		mov	ah,1
		mov	al,'*'
		shl	ah,cl
		add	ah,'0'
		mov	ds:[di],ax
		lea	di,[di+2]
dSIB_Exit2:	mov	UBufP,di
dSIB_Exit:	ret
do_SIB		EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
UA_Str		Proc	Pascal Near
		ARG	_Str:Word
		mov	bx,_Str
		or	bx,bx
		jz	UA_Invalid

UA_StartScan:	mov	di,UBufP
		xor	ah,ah
UA_ScanStr:	mov	al,ds:[bx]
		or	al,al
		jz	UA_Exit
		inc	bx
		mov	ds:[di],al
		inc	di
		cmp	al,'%'
		jne	UA_ScanStr
		dec	di
		mov	UBufP,di
		mov	al,ds:[bx]
		inc	bx
		push	ax
		mov	al,ds:[bx]
		inc	bx
		push	ax
		mov	_Str,bx
		call	Percent
		mov	bx,_Str
		jmp	UA_StartScan

UA_Invalid:
UA_Exit:	mov	UBufP,di
		ret
UA_Str		EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
UnAssemble	Proc	Pascal Near
		ARG	Sel:Word,Offs:DWord,ROffs:DWord

		cld

		push	es ds
		pop	es

		mov	fs,Sel

		mov	eax,Offs
		mov	Instruction_Off,eax
		mov	eax,ROffs
		mov	Real_Offset,eax

		xor	ax,ax
		mov	Instruction_Len,al
		mov	Prefix,al
		mov	SExt,al

		mov	OpSize+1,al
		mov	AddrSize+1,al

		mov	al,SegSize
		mov	OpSize,al
		mov	AddrSize,al

		mov	ax,-1
		mov	modRMV,ax
		mov	SIBV,ax

		mov	Extend,2

		mov	UBufP,offset UBuf

		xor	ah,ah
		GetByte
		mov	bx,ax
		add	bx,ax
		mov	bx,OpMap1[bx]
		or	bx,bx			; Is pointer NULL?
		jz	UnA_NULL		; If so, we don't know the op.
		push	bx
		call	UA_Str
		jmp	UnA_Exit
UnA_NULL:	; Its NULL
UnA_Exit:	mov	di,UBufP
		mov	byte ptr ds:[di],0
		pop	es
		ret
UnAssemble	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
PrintInv	Proc	near
		mov	di,UBufP
		mov	si,offset Invalid
		call	CopyStr
		mov	UBufP,di
		ret
PrintInv	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
CopyStr 	Proc	near
		; DS:SI = Source (ES & DS must be same and DF must be clear)
		; ES:DI = Dest
		mov	cx,0FFFFh
		mov	ah,al
		xor	al,al
		xchg	si,di
		repne	scas byte ptr es:[di]
		xchg	si,di
		not	cx
		sub	si,cx
		dec	cx
		jz	CStr_Exit
		rep	movs byte ptr es:[di],ds:[si]
CStr_Exit:	mov	al,ah
		ret
CopyStr 	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
PrintHex	Proc	near
		;   EDX = Number
		;    CL = Width (# of nibbles)
		; DS:DI = Destination
		push	ebx
		mov	ebx,offset HexTable
		mov	ch,cl
		not	cl
		inc	cl
		and	cl,7
		shl	cl,2
		shl	edx,cl
PH_MainLoop:	rol	edx,4
		mov	al,dl
		and	al,0Fh
		xlat
		mov	ds:[di],al
		inc	di
		dec	ch
		jnz	PH_MainLoop
		pop	ebx
		ret
PrintHex	EndP
;°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²±°±²
_PMODE_TEXT	EndS
;°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°
;Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û
;°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°
		End
