	include	basm.inc

	extrn	GetAsmSymbol:far
	extrn	GetAsmLabel:far
	extrn	EmitByte:far
	extrn	EmitFixup:far
	extrn	EmitJump:far
	extrn	EmitFloat:far

	.code	Basm_Text

	Argm	Text,dword,1
	Argm	Len,word,1
	Argm	Options,word,1
	Loc	Dummy,word,1
	Loc	SaveSI,word,1
	Loc	SaveDI,word,1
	Loc	StackLimit,word,1
	Loc	Prefixes,byte,6
	Loc	TextPtr,dword,1
	Loc	SaveTextPtr,word,1
	Loc	Oper1TextPtr,word,1
	Loc	Oper2TextPtr,word,1
	Loc	Mode,byte,1
	Loc	DataLength,byte,1
	Loc	InOpcode,byte,1
	Loc	OperCount,byte,1
	Loc	OpcodePtr,word,1
	Loc	RegNum,word,1
	Loc	Oper2Size,word,1
	Loc	HashValue,byte,1
	Loc	Opcode,byte,1
	Loc	Pending,byte,1
	Loc	RMBits,byte,1
	Loc	FixupAddr,dword,1
	Loc	PureMemFlag,byte,1
	Loc	SizeBit,byte,1
	Loc	DirectionBit,byte,1
	Loc	DefPrefix,byte,1
	Loc	FixupOffs,word,1
	Loc	DwordFixup,byte,1
	Loc	Dummy2,byte,1
	Loc	Value,dword,1
	Loc	Symbol,byte,<size TSymbol>
	Loc	IdentBuf,byte,34
	Loc	UpCaseIdent,byte,34
	Loc	StringBuf,byte,128
	Loc	CodeCount,word,1
	Loc	CodeBuffer,byte,<11*size TCodeBuffer>
	Loc	TempAddr,dword,1
	Loc	Operand1,byte,<size TAsmSymbol>
	Loc	Operand2,byte,<size TAsmSymbol>
	Loc	Operand3,byte,<size TAsmSymbol>
	Loc	Limit,word,1
	Entry	Assemble
	call	Init
	mov	InOpcode,1
	call	GetToken
	mov	ax,TextPtr.offs
	mov	SaveTextPtr,ax
	call	ProcessLabel
	call	ProcessPrefix
	dec	InOpcode
	call	ProcessData
	jz	@@2
	mov	al,';'
	call	CheckToken
	jz	@@1
	call	PutPrefixes
	jmp	short @@2
@@1:	mov	al,tOPCODE
	call	NeedToken
	call	ProcessOperands
	call	ProcessCommand
@@2:	call	Flush
	xor	ax,ax
@Exit:	mov	cx,TextPtr.Offs
	lds	bx,Text
	mov	[bx],cx
	mov	si,SaveSI
	mov	di,SaveDI
	Exit

Init	proc	near
	mov	SaveSI,si
	mov	SaveDI,di
	lea	ax,Limit[-1000]
	mov	StackLimit,ax
	les	bx,Text
	les	bx,es:[bx]
	mov	TextPtr.Offs,bx
	mov	TextPtr.Segm,es
	xor	ax,ax
	mov	SaveTextPtr,ax
	mov	Symbol.sParent.Offs,ax
	mov	Symbol.sParent.Segm,ax
	mov	word ptr Prefixes[0],ax
	mov	CodeCount,ax
	mov	Pending,al
	ret
Init	endp

Flush	proc	near
	lea	si,CodeBuffer
@@1:	sub	CodeCount,size TCodeBuffer
	jc	@@7
	cld
	push	si
	xor	ax,ax
	lodsb
	mov	bx,ax
	lodsb
	mov	cx,ax
	lodsw
	xchg	ax,dx
	lodsw
	xchg	ax,dx
	dec	bx
	js	@@2
	jz	@@3
	dec	bx
	jz	@@4
	push	ax
	mov	ax,cx
	and	cl,0feh
	push	cx
	and	al,1
	push	ax
	call	EmitFloat
	jmp	short @@5
@@2:	push	ax
	call	EmitByte
	jmp	short @@5
@@3:	push	cx dword ptr [si] dx ax
	call	EmitFixup
	jmp	short @@5
@@4:	push	ax dword ptr [si]
	call	EmitJump
@@5:	or	ax,ax
	jz	@@6
	jmp	Error
@@6:	pop	si
	add	si,size TCodeBuffer
	jmp	@@1
@@7:	mov	CodeCount,0
	ret
Flush	endp

ProcessPrefix	proc	near
@@1:	cmp	dh,tOPCODE
	jne	@@3
	mov	bx,OpcodePtr
	cmp	byte ptr cs:[bx],80h+cPrefix
	jne	@@3
	mov	al,cs:[bx+2]
	mov	cx,5
	lea	bx,Prefixes[-1]
@@2:	inc	bx
	cmp	byte ptr [bx],0
	loopne	@@2
	mov	ah,0
	mov	[bx],ax
	call	GetToken
	jmp	@@1
@@3:	ret
ProcessPrefix	endp

ProcessData	proc	near
	cmp	dh,tOPCODE
	jne	@@3
	mov	bx,OpcodePtr
	mov	ax,cs:[bx]
	cmp	al,80h+cDB
	jne	@@3
	mov	DataLength,ah
	cmp	word ptr Prefixes[0],0
	je	@@1
	jmp	SyntaxErr
@@1:	call	GetToken
@@2:	lea	si,Operand1
	call	Expression
	push	dx
	call	ProcessDataElem
	call	Flush
	pop	dx
	mov	al,','
	call	CheckToken
	jnz	@@2
	mov	al,';'
	call	NeedToken
	xor	ax,ax
@@3:	ret
ProcessData	endp

ProcessDataElem	proc	near
	mov	di,si
	mov	ax,[si].aValue.W0
	mov	dx,[si].aValue.W2
	mov	cx,[si].aAddr.Offs
	or	cx,[si].aAddr.Segm
	cmp	DataLength,2
	je	@@5
	ja	@@7
	or	cx,cx
	jz	@@1
	jmp	InvOperErr2
@@1:	lea	si,StringBuf
	cmp	byte ptr [si],0
	jne	@@2
	call	ByteOperand
	jnz	@@13
	jmp	short @@11
@@2:	xor	ax,ax
	cld
	lodsb
	xchg	ax,cx
	jcxz	@@4
@@3:	cld
	lodsb
	push	si cx
	call	@@11
	call	Flush
	pop	cx si
	loop	@@3
@@4:	ret
@@5:	cmp	StringBuf[0],2
	ja	@@14
	call	WordOperand
	jcxz	@@10
	mov	bx,fOffs*256+eFixup
	cmp	[si].aHalf,bh
	jb	@@6
	mov	bh,[si].aHalf
@@6:	xchg	ax,cx
	mov	ax,Operand1.aAddr.Offs
	mov	TempAddr.Offs,ax
	mov	ax,Operand1.aAddr.Segm
	mov	TempAddr.Segm,ax
	jmp	Put
@@7:	cmp	StringBuf[0],4
	ja	@@14
	jcxz	@@8
	xchg	ax,cx
	mov	bx,fPtr*256+eFixup
	cmp	[si].aHalf,0
	je	@@12
	mov	bh,[si].aHalf
	mov	ax,Operand1.aAddr.Offs
	mov	TempAddr.Offs,ax
	mov	ax,Operand1.aAddr.Segm
	mov	TempAddr.Segm,ax
	call	Put
	jmp	short @@9
@@8:	call	@@10
@@9:	xchg	ax,dx
@@10:	call	@@11
	xchg	al,ah
@@11:	mov	bl,eByte
	mov	cx,ax
@@12:	call	Put
	ret
@@13:	jmp	OutOfRangeErr
@@14:	jmp	StringConstErr
ProcessDataElem	endp

ProcessLabel	proc	near
	call	FilterChar
	cmp	al,':'
	jne	@@1
	lea	bx,IdentBuf
	push	ss bx
	call	GetAsmLabel
	jnz	Error
	call	GetToken
	mov	al,':'
	call	NeedToken
@@1:	ret
ProcessLabel	endp

ProcessOperands	proc	near
	mov	OperCount,0
	mov	ax,SaveTextPtr
	mov	Oper1TextPtr,ax
	mov	al,';'
	call	CheckToken
	jnz	@@3
	lea	si,Operand1
	call	Expression
	inc	OperCount
	mov	al,';'
	call	CheckToken
	jnz	@@3
	mov	al,','
	call	NeedToken
	mov	ax,SaveTextPtr
	mov	Oper2TextPtr,ax
	lea	si,Operand2
	call	Expression
	inc	OperCount
	lea	si,Operand1
	lea	di,Operand2
	mov	ax,[si].aSize
	mov	cx,[di].aSize
	mov	Oper2Size,cx
	jcxz	@@1
	or	ax,ax
	jnz	@@2
	xchg	cx,[si].aSize
	jmp	short @@2
@@1:	xchg	ax,[di].aSize
@@2:	mov	al,';'
	call	CheckToken
	jnz	@@3
	mov	al,','
	call	NeedToken
	lea	si,Operand3
	call	Expression
	inc	OperCount
	mov	al,';'
	call	NeedToken
@@3:	ret
ProcessOperands	endp

@Err:	cbw
Error		label near
	push	SaveTextPtr
	pop	TextPtr.offs
	jmp	@Exit
FieldErr	label near
	mov	al,-15
	jmp	@Err
ZeroDivErr	label near
	mov	al,-14
	jmp	@Err
Not286Err	label near
	mov	al,-13
	jmp	@Err
InvOperErr	label near
	mov	al,-12
	jmp	@Err
IntConstErr	label near
	mov	al,-11
	jmp	@Err
StringConstErr	label near
	mov	al,-10
	jmp	@Err
OutOfRangeErr	label near
	mov	al,-9
	jmp	@Err
InvRegErr	label near
	mov	al,-8
	jmp	@Err
RelSymErr	label near
	mov	al,-7
	jmp	@Err
TypeErr		label near
	mov	al,-6
	jmp	@Err
ConstErr	label near
	mov	al,-5
	jmp	@Err
MemRefErr	label near
	mov	al,-4
	jmp	@Err
InvOperErr2	label near
	mov	al,-3
	jmp	@Err
OutOfMemErr	label near
	mov	al,-2
	jmp	@Err
SyntaxErr	label near
	mov	al,-1
	jmp	@Err

CheckStack	proc near
	cmp	sp,StackLimit
	jbe	OutOfMemErr
	ret
CheckStack	endp

	include	asmexpr.inc

	include	asmlex.inc

	include	asminstr.inc

	extrn	OpcodeTable:near
	extrn	ResWordTable:near

	end
