
; flat assembler core
; Copyright (c) 1999-2011, Tomasz Grysztar.
; All rights reserved.

calculate_expression:
	mov	[current_offset],edi
	mov	[value_undefined],0
	cmp	byte [esi],0
	je	get_string_value
	cmp	byte [esi],'.'
	je	convert_fp
      calculation_loop:
	lods	byte [esi]
	cmp	al,1
	je	get_byte_number
	cmp	al,2
	je	get_word_number
	cmp	al,4
	je	get_dword_number
	cmp	al,8
	je	get_qword_number
	cmp	al,0Fh
	je	value_out_of_range
	cmp	al,10h
	je	get_register
	cmp	al,11h
	je	get_label
	cmp	al,')'
	je	expression_calculated
	cmp	al,']'
	je	expression_calculated
	cmp	al,'!'
	je	invalid_expression
	sub	edi,14h
	mov	ebx,edi
	sub	ebx,14h
	cmp	al,0E0h
	je	calculate_rva
	cmp	al,0E1h
	je	calculate_plt
	cmp	al,0D0h
	je	calculate_not
	cmp	al,083h
	je	calculate_neg
	mov	dx,[ebx+8]
	or	dx,[edi+8]
	cmp	al,80h
	je	calculate_add
	cmp	al,81h
	je	calculate_sub
	mov	ah,[ebx+12]
	or	ah,[edi+12]
	jz	absolute_values_calculation
	cmp	[error_line],0
	jne	absolute_values_calculation
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      absolute_values_calculation:
	cmp	al,90h
	je	calculate_mul
	cmp	al,91h
	je	calculate_div
	or	dx,dx
	jnz	invalid_expression
	cmp	al,0A0h
	je	calculate_mod
	cmp	al,0B0h
	je	calculate_and
	cmp	al,0B1h
	je	calculate_or
	cmp	al,0B2h
	je	calculate_xor
	cmp	al,0C0h
	je	calculate_shl
	cmp	al,0C1h
	je	calculate_shr
	jmp	invalid_expression
      expression_calculated:
	sub	edi,14h
	cmp	[value_undefined],0
	je	expression_value_ok
	xor	eax,eax
	mov	[edi],eax
	mov	[edi+4],eax
	mov	[edi+12],al
      expression_value_ok:
	ret
      get_byte_number:
	xor	eax,eax
	lods	byte [esi]
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
      got_number:
	mov	word [edi-8+8],0
	mov	byte [edi-8+12],0
	mov	dword [edi-8+16],0
	add	edi,0Ch
	jmp	calculation_loop
      get_word_number:
	xor	eax,eax
	lods	word [esi]
	stos	dword [edi]
	xor	ax,ax
	stos	dword [edi]
	jmp	got_number
      get_dword_number:
	movs	dword [edi],[esi]
	xor	eax,eax
	stos	dword [edi]
	jmp	got_number
      get_qword_number:
	movs	dword [edi],[esi]
	movs	dword [edi],[esi]
	jmp	got_number
      get_register:
	mov	byte [edi+9],0
	mov	byte [edi+12],0
	lods	byte [esi]
	mov	[edi+8],al
	mov	byte [edi+10],1
	xor	eax,eax
	mov	[edi+16],eax
	stos	dword [edi]
	stos	dword [edi]
	add	edi,0Ch
	jmp	calculation_loop
      get_label:
	xor	eax,eax
	mov	[edi+8],eax
	mov	[edi+12],al
	mov	[edi+20],eax
	lods	dword [esi]
	cmp	eax,0Fh
	jb	predefined_label
	je	reserved_word_used_as_symbol
	mov	ebx,eax
	mov	ax,[current_pass]
	mov	[ebx+18],ax
	or	byte [ebx+8],8
	test	byte [ebx+8],1
	jz	label_undefined
	cmp	ax,[ebx+16]
	je	label_defined
	test	byte [ebx+8],4
	jnz	label_out_of_scope
	test	byte [ebx+9],1
	jz	label_defined
	mov	eax,[ebx]
	sub	eax,dword [adjustment]
	stos	dword [edi]
	mov	eax,[ebx+4]
	sbb	eax,dword [adjustment+4]
	stos	dword [edi]
	mov	eax,dword [adjustment]
	or	eax,dword [adjustment+4]
	jz	got_label
	or	[next_pass_needed],-1
	jmp	got_label
      label_defined:
	mov	eax,[ebx]
	stos	dword [edi]
	mov	eax,[ebx+4]
	stos	dword [edi]
      got_label:
	mov	al,[ebx+11]
	mov	[edi-8+12],al
	mov	eax,[ebx+12]
	mov	[edi-8+8],eax
	mov	eax,[ebx+20]
	mov	[edi-8+16],eax
	add	edi,0Ch
	mov	al,[ebx+10]
	or	al,al
	jz	calculation_loop
	cmp	[size_override],-1
	je	calculation_loop
	cmp	[size_override],0
	je	check_size
	cmp	[operand_size],0
	jne	calculation_loop
	mov	[operand_size],al
	jmp	calculation_loop
      check_size:
	xchg	[operand_size],al
	or	al,al
	jz	calculation_loop
	cmp	al,[operand_size]
	jne	operand_sizes_do_not_match
	jmp	calculation_loop
      current_offset_label:
	mov	eax,[current_offset]
      make_current_offset_label:
	xor	edx,edx
	sub	eax,dword [org_origin]
	sbb	edx,dword [org_origin+4]
	stos	dword [edi]
	mov	eax,edx
	stos	dword [edi]
	mov	eax,[org_registers]
	stos	dword [edi]
	mov	al,[labels_type]
	mov	[edi-12+12],al
	mov	eax,[org_symbol]
	mov	[edi-12+16],eax
	add	edi,8
	jmp	calculation_loop
      org_origin_label:
	mov	eax,[org_start]
	jmp	make_current_offset_label
      counter_label:
	mov	eax,[counter]
      make_dword_label_value:
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	add	edi,0Ch
	jmp	calculation_loop
      timestamp_label:
	call	make_timestamp
      make_qword_label_value:
	stos	dword [edi]
	mov	eax,edx
	stos	dword [edi]
	add	edi,0Ch
	jmp	calculation_loop
      predefined_label:
	or	eax,eax
	jz	current_offset_label
	cmp	eax,1
	je	counter_label
	cmp	eax,2
	je	timestamp_label
	cmp	eax,3
	je	org_origin_label
	mov	edx,invalid_value
	jmp	error_undefined
      label_out_of_scope:
	mov	edx,symbol_out_of_scope
	mov	eax,[ebx+24]
	cmp	[error_line],0
	jne	error_undefined
	mov	[error_info],eax
	jmp	error_undefined
      label_undefined:
	mov	edx,undefined_symbol
	cmp	[error_line],0
	jne	error_undefined
	mov	eax,[ebx+24]
	mov	[error_info],eax
      error_undefined:
	cmp	[current_pass],1
	ja	undefined_value
      force_next_pass:
	or	[next_pass_needed],-1
      undefined_value:
	mov	byte [edi+12],0
	or	[value_undefined],-1
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	add	edi,0Ch
	cmp	[error_line],0
	jne	calculation_loop
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],edx
	jmp	calculation_loop
      calculate_add:
	mov	ecx,[ebx+16]
	cmp	byte [edi+12],0
	je	add_values
	mov	ecx,[edi+16]
	cmp	byte [ebx+12],0
	je	add_values
	cmp	[error_line],0
	jne	add_values
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      add_values:
	mov	al,[edi+12]
	or	[ebx+12],al
	mov	[ebx+16],ecx
	mov	eax,[edi]
	add	[ebx],eax
	mov	eax,[edi+4]
	adc	[ebx+4],eax
	or	dx,dx
	jz	calculation_loop
	push	esi
	mov	esi,ebx
	lea	ebx,[edi+10]
	mov	cl,[edi+8]
	call	add_register
	lea	ebx,[edi+11]
	mov	cl,[edi+9]
	call	add_register
	pop	esi
	jmp	calculation_loop
      add_register:
	or	cl,cl
	jz	add_register_done
      add_register_start:
	cmp	[esi+8],cl
	jne	add_in_second_slot
	mov	al,[ebx]
	add	[esi+10],al
	jnz	add_register_done
	mov	byte [esi+8],0
	ret
      add_in_second_slot:
	cmp	[esi+9],cl
	jne	create_in_first_slot
	mov	al,[ebx]
	add	[esi+11],al
	jnz	add_register_done
	mov	byte [esi+9],0
	ret
      create_in_first_slot:
	cmp	byte [esi+8],0
	jne	create_in_second_slot
	mov	[esi+8],cl
	mov	al,[ebx]
	mov	[esi+10],al
	ret
      create_in_second_slot:
	cmp	byte [esi+9],0
	jne	invalid_expression
	mov	[esi+9],cl
	mov	al,[ebx]
	mov	[esi+11],al
      add_register_done:
	ret
      calculate_sub:
	xor	ah,ah
	mov	ah,[ebx+12]
	mov	al,[edi+12]
	or	al,al
	jz	sub_values
	cmp	al,ah
	jne	invalid_sub
	xor	ah,ah
	mov	ecx,[edi+16]
	cmp	ecx,[ebx+16]
	jne	invalid_sub
      sub_values:
	mov	[ebx+12],ah
	mov	eax,[edi]
	sub	[ebx],eax
	mov	eax,[edi+4]
	sbb	[ebx+4],eax
	or	dx,dx
	jz	calculation_loop
	push	esi
	mov	esi,ebx
	lea	ebx,[edi+10]
	mov	cl,[edi+8]
	call	sub_register
	lea	ebx,[edi+11]
	mov	cl,[edi+9]
	call	sub_register
	pop	esi
	jmp	calculation_loop
      invalid_sub:
	cmp	[error_line],0
	jne	sub_values
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
	jmp	sub_values
      sub_register:
	or	cl,cl
	jz	add_register_done
	neg	byte [ebx]
	jmp	add_register_start
      calculate_mul:
	or	dx,dx
	jz	mul_start
	cmp	word [ebx+8],0
	jne	mul_start
	mov	eax,[ebx]
	xchg	eax,[edi]
	mov	[ebx],eax
	mov	eax,[ebx+4]
	xchg	eax,[edi+4]
	mov	[ebx+4],eax
	mov	eax,[ebx+8]
	xchg	eax,[edi+8]
	mov	[ebx+8],eax
	mov	eax,[ebx+12]
	xchg	eax,[edi+12]
	mov	[ebx+12],eax
      mul_start:
	push	esi edx
	mov	esi,ebx
	xor	bl,bl
	bt	dword [esi+4],31
	jnc	mul_first_sign_ok
	not	dword [esi]
	not	dword [esi+4]
	add	dword [esi],1
	adc	dword [esi+4],0
	not	bl
      mul_first_sign_ok:
	bt	dword [edi+4],31
	jnc	mul_second_sign_ok
	not	dword [edi]
	not	dword [edi+4]
	add	dword [edi],1
	adc	dword [edi+4],0
	not	bl
      mul_second_sign_ok:
	cmp	dword [esi+4],0
	jz	mul_numbers
	cmp	dword [edi+4],0
	jnz	value_out_of_range
      mul_numbers:
	mov	eax,[esi+4]
	mul	dword [edi]
	or	edx,edx
	jnz	value_out_of_range
	mov	ecx,eax
	mov	eax,[esi]
	mul	dword [edi+4]
	or	edx,edx
	jnz	value_out_of_range
	add	ecx,eax
	jc	value_out_of_range
	mov	eax,[esi]
	mul	dword [edi]
	add	edx,ecx
	jc	value_out_of_range
	test	edx,1 shl 31
	jnz	value_out_of_range
	mov	[esi],eax
	mov	[esi+4],edx
	or	bl,bl
	jz	mul_ok
	not	dword [esi]
	not	dword [esi+4]
	add	dword [esi],1
	adc	dword [esi+4],0
      mul_ok:
	pop	edx
	or	dx,dx
	jz	mul_calculated
	cmp	word [edi+8],0
	jne	invalid_value
	cmp	byte [esi+8],0
	je	mul_first_register_ok
	mov	al,[edi]
	cbw
	cwde
	cdq
	cmp	edx,[edi+4]
	jne	value_out_of_range
	cmp	eax,[edi]
	jne	value_out_of_range
	imul	byte [esi+10]
	mov	dl,ah
	cbw
	cmp	ah,dl
	jne	value_out_of_range
	mov	[esi+10],al
	or	al,al
	jnz	mul_first_register_ok
	mov	[esi+8],al
      mul_first_register_ok:
	cmp	byte [esi+9],0
	je	mul_calculated
	mov	al,[edi]
	cbw
	cwde
	cdq
	cmp	edx,[edi+4]
	jne	value_out_of_range
	cmp	eax,[edi]
	jne	value_out_of_range
	imul	byte [esi+11]
	mov	dl,ah
	cbw
	cmp	ah,dl
	jne	value_out_of_range
	mov	[esi+11],al
	or	al,al
	jnz	mul_calculated
	mov	[esi+9],al
      mul_calculated:
	pop	esi
	jmp	calculation_loop
      calculate_div:
	push	esi edx
	mov	esi,ebx
	call	div_64
	pop	edx
	or	dx,dx
	jz	div_calculated
	cmp	byte [esi+8],0
	je	div_first_register_ok
	mov	al,[edi]
	cbw
	cwde
	cdq
	cmp	edx,[edi+4]
	jne	value_out_of_range
	cmp	eax,[edi]
	jne	value_out_of_range
	or	al,al
	jz	value_out_of_range
	mov	al,[esi+10]
	cbw
	idiv	byte [edi]
	or	ah,ah
	jnz	invalid_use_of_symbol
	mov	[esi+10],al
      div_first_register_ok:
	cmp	byte [esi+9],0
	je	div_calculated
	mov	al,[edi]
	cbw
	cwde
	cdq
	cmp	edx,[edi+4]
	jne	value_out_of_range
	cmp	eax,[edi]
	jne	value_out_of_range
	or	al,al
	jz	value_out_of_range
	mov	al,[esi+11]
	cbw
	idiv	byte [edi]
	or	ah,ah
	jnz	invalid_use_of_symbol
	mov	[esi+11],al
      div_calculated:
	pop	esi
	jmp	calculation_loop
      calculate_mod:
	push	esi
	mov	esi,ebx
	call	div_64
	mov	[esi],eax
	mov	[esi+4],edx
	pop	esi
	jmp	calculation_loop
      calculate_and:
	mov	eax,[edi]
	and	[ebx],eax
	mov	eax,[edi+4]
	and	[ebx+4],eax
	jmp	calculation_loop
      calculate_or:
	mov	eax,[edi]
	or	[ebx],eax
	mov	eax,[edi+4]
	or	[ebx+4],eax
	jmp	calculation_loop
      calculate_xor:
	mov	eax,[edi]
	xor	[ebx],eax
	mov	edx,[edi+4]
	xor	[ebx+4],edx
	cmp	[value_size],1
	je	xor_byte
	cmp	[value_size],2
	je	xor_word
	cmp	[value_size],4
	je	xor_dword
	cmp	[value_size],6
	je	xor_pword
      xor_calculated:
	jmp	calculation_loop
      prepare_xor_check:
	cmp	edx,-1
	je	xor_check_ready
	xor	edx,[ebx+4]
	xor	eax,[ebx]
	cmp	edx,-1
      xor_check_ready:
	ret
      xor_byte:
	call	prepare_xor_check
	jne	xor_calculated
	xor	edx,[ebx+4]
	jnz	xor_calculated
	cmp	eax,0FFFFFF80h
	jb	xor_calculated
	xor	eax,[ebx]
	cmp	eax,0FFh
	ja	xor_calculated
	mov	[ebx+4],edx
	and	dword [ebx],0FFh
	jmp	xor_calculated
      xor_word:
	call	prepare_xor_check
	jne	xor_calculated
	xor	edx,[ebx+4]
	jnz	xor_calculated
	cmp	eax,0FFFF8000h
	jb	xor_calculated
	xor	eax,[ebx]
	cmp	eax,0FFFFh
	ja	xor_calculated
	mov	[ebx+4],edx
	and	dword [ebx],0FFFFh
	jmp	xor_calculated
      xor_dword:
	call	prepare_xor_check
	jne	xor_calculated
	xor	edx,[ebx+4]
	jnz	xor_calculated
	cmp	eax,80000000h
	jb	xor_calculated
	mov	[ebx+4],edx
	jmp	xor_calculated
      xor_pword:
	cmp	edx,0FFFF8000h
	jae	xor_pword_check
	xor	edx,[ebx+4]
	xor	eax,[ebx]
	cmp	edx,0FFFF8000h
	jb	xor_calculated
      xor_pword_check:
	xor	edx,[ebx+4]
	cmp	edx,0FFFFh
	ja	xor_calculated
	and	dword [ebx+4],0FFFFh
	jmp	xor_calculated
      shr_negative:
	not	dword [edi]
	not	dword [edi+4]
	add	dword [edi],1
	adc	dword [edi+4],0
      calculate_shl:
	mov	eax,dword [edi+4]
	bt	eax,31
	jc	shl_negative
	or	eax,eax
	jnz	zero_value
	mov	ecx,[edi]
	cmp	ecx,64
	jae	zero_value
	mov	edx,[ebx+4]
	mov	eax,[ebx]
	cmp	ecx,32
	jae	shl_high
	shld	edx,eax,cl
	shl	eax,cl
	mov	[ebx],eax
	mov	[ebx+4],edx
	jmp	calculation_loop
      shl_high:
	sub	cl,32
	shl	eax,cl
	mov	[ebx+4],eax
	mov	dword [ebx],0
	jmp	calculation_loop
      shl_negative:
	not	dword [edi]
	not	dword [edi+4]
	add	dword [edi],1
	adc	dword [edi+4],0
      calculate_shr:
	mov	eax,dword [edi+4]
	bt	eax,31
	jc	shr_negative
	or	eax,eax
	jnz	zero_value
	mov	ecx,[edi]
	cmp	ecx,64
	jae	zero_value
	mov	edx,[ebx+4]
	mov	eax,[ebx]
	cmp	ecx,32
	jae	shr_high
	cmp	[value_size],1
	je	shr_byte
	cmp	[value_size],2
	je	shr_word
	cmp	[value_size],4
	je	shr_dword
	cmp	[value_size],6
	je	shr_pword
      shr_regular:
	shrd	eax,edx,cl
	shr	edx,cl
	mov	[ebx],eax
	mov	[ebx+4],edx
	jmp	calculation_loop
      shr_byte:
	cmp	edx,-1
	jne	shr_regular
	cmp	eax,0FFFFFF80h
	jb	shr_regular
	and	eax,0FFh
	xor	edx,edx
	jmp	shr_regular
      shr_word:
	cmp	edx,-1
	jne	shr_regular
	cmp	eax,0FFFF8000h
	jb	shr_regular
	and	eax,0FFFFh
	xor	edx,edx
	jmp	shr_regular
      shr_dword:
	cmp	edx,-1
	jne	shr_regular
	cmp	eax,80000000h
	jb	shr_regular
	xor	edx,edx
	jmp	shr_regular
      shr_pword:
	cmp	edx,0FFFF8000h
	jb	shr_regular
	and	edx,0FFFFh
	jmp	shr_regular
      shr_high:
	sub	cl,32
	cmp	[value_size],1
	je	shr_byte_32plus
	cmp	[value_size],2
	je	shr_word_32plus
	cmp	[value_size],4
	je	shr_dword_32plus
	cmp	[value_size],6
	je	shr_pword_32plus
      shr_32plus:
	shr	edx,cl
	mov	[ebx],edx
	mov	dword [ebx+4],0
	jmp	calculation_loop
      shr_byte_32plus:
	cmp	edx,-1
	jne	shr_32plus
	cmp	eax,-80h
	jb	shr_32plus
	jmp	zero_value
      shr_word_32plus:
	cmp	edx,-1
	jne	shr_32plus
	cmp	eax,-8000h
	jb	shr_32plus
	jmp	zero_value
      shr_dword_32plus:
	cmp	edx,-1
	jne	shr_32plus
	cmp	eax,-80000000h
	jb	shr_32plus
	jmp	zero_value
      shr_pword_32plus:
	cmp	edx,-8000h
	jb	shr_32plus
	and	edx,0FFFFh
	jmp	shr_32plus
      zero_value:
	mov	dword [ebx],0
	mov	dword [ebx+4],0
	jmp	calculation_loop
      calculate_not:
	cmp	word [edi+8],0
	jne	invalid_expression
	cmp	byte [edi+12],0
	je	not_ok
	cmp	[error_line],0
	jne	not_ok
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      not_ok:
	cmp	[value_size],1
	je	not_byte
	cmp	[value_size],2
	je	not_word
	cmp	[value_size],4
	je	not_dword
	cmp	[value_size],6
	je	not_pword
      not_qword:
	not	dword [edi]
	not	dword [edi+4]
	add	edi,14h
	jmp	calculation_loop
      not_byte:
	cmp	dword [edi+4],0
	jne	not_qword
	cmp	word [edi+2],0
	jne	not_qword
	cmp	byte [edi+1],0
	jne	not_qword
	not	byte [edi]
	add	edi,14h
	jmp	calculation_loop
      not_word:
	cmp	dword [edi+4],0
	jne	not_qword
	cmp	word [edi+2],0
	jne	not_qword
	not	word [edi]
	add	edi,14h
	jmp	calculation_loop
      not_dword:
	cmp	dword [edi+4],0
	jne	not_qword
	not	dword [edi]
	add	edi,14h
	jmp	calculation_loop
      not_pword:
	cmp	word [edi+6],0
	jne	not_qword
	not	dword [edi]
	not	word [edi+4]
	add	edi,14h
	jmp	calculation_loop
      calculate_neg:
	cmp	word [edi+8],0
	jne	invalid_expression
	cmp	byte [edi+12],0
	je	neg_ok
	cmp	[error_line],0
	jne	neg_ok
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      neg_ok:
	mov	eax,[edi]
	mov	edx,[edi+4]
	mov	dword [edi],0
	mov	dword [edi+4],0
	sub	[edi],eax
	sbb	[edi+4],edx
	add	edi,14h
	jmp	calculation_loop
      calculate_rva:
	cmp	word [edi+8],0
	jne	invalid_expression
	cmp	[output_format],5
	je	calculate_gotoff
	cmp	[output_format],4
	je	calculate_coff_rva
	cmp	[output_format],3
	jne	invalid_expression
	test	[format_flags],8
	jnz	pe64_rva
	mov	al,2
	bt	[resolver_flags],0
	jc	rva_type_ok
	xor	al,al
      rva_type_ok:
	cmp	byte [edi+12],al
	je	rva_ok
	cmp	[error_line],0
	jne	rva_ok
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      rva_ok:
	mov	byte [edi+12],0
	mov	eax,[code_start]
	mov	eax,[eax+34h]
	cdq
	sub	[edi],eax
	sbb	[edi+4],edx
	add	edi,14h
	jmp	calculation_loop
      pe64_rva:
	mov	al,4
	bt	[resolver_flags],0
	jc	pe64_rva_type_ok
	xor	al,al
      pe64_rva_type_ok:
	cmp	byte [edi+12],al
	je	pe64_rva_ok
	cmp	[error_line],0
	jne	pe64_rva_ok
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      pe64_rva_ok:
	mov	byte [edi+12],0
	mov	eax,[code_start]
	mov	edx,[eax+34h]
	mov	eax,[eax+30h]
	sub	[edi],eax
	sbb	[edi+4],edx
	add	edi,14h
	jmp	calculation_loop
      calculate_gotoff:
	test	[format_flags],8+1
	jnz	invalid_expression
      calculate_coff_rva:
	mov	dl,5
	cmp	byte [edi+12],2
	je	change_value_type
      incorrect_change_of_value_type:
	cmp	[error_line],0
	jne	change_value_type
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      change_value_type:
	mov	byte [edi+12],dl
	add	edi,14h
	jmp	calculation_loop
      calculate_plt:
	cmp	word [edi+8],0
	jne	invalid_expression
	cmp	[output_format],5
	jne	invalid_expression
	test	[format_flags],1
	jnz	invalid_expression
	mov	dl,6
	mov	dh,2
	test	[format_flags],8
	jz	check_value_for_plt
	mov	dh,4
      check_value_for_plt:
	mov	eax,[edi]
	or	eax,[edi+4]
	jnz	incorrect_change_of_value_type
	cmp	byte [edi+12],dh
	jne	incorrect_change_of_value_type
	mov	eax,[edi+16]
	cmp	byte [eax],80h
	jne	incorrect_change_of_value_type
	jmp	change_value_type
      div_64:
	xor	ebx,ebx
	cmp	dword [edi],0
	jne	divider_ok
	cmp	dword [edi+4],0
	jne	divider_ok
	cmp	[next_pass_needed],0
	je	value_out_of_range
	jmp	div_done
      divider_ok:
	bt	dword [esi+4],31
	jnc	div_first_sign_ok
	not	dword [esi]
	not	dword [esi+4]
	add	dword [esi],1
	adc	dword [esi+4],0
	not	bx
      div_first_sign_ok:
	bt	dword [edi+4],31
	jnc	div_second_sign_ok
	not	dword [edi]
	not	dword [edi+4]
	add	dword [edi],1
	adc	dword [edi+4],0
	not	bl
      div_second_sign_ok:
	cmp	dword [edi+4],0
	jne	div_high
	mov	ecx,[edi]
	mov	eax,[esi+4]
	xor	edx,edx
	div	ecx
	mov	[esi+4],eax
	mov	eax,[esi]
	div	ecx
	mov	[esi],eax
	mov	eax,edx
	xor	edx,edx
	jmp	div_done
      div_high:
	mov	eax,[esi+4]
	xor	edx,edx
	div	dword [edi+4]
	mov	ebx,[esi]
	mov	[esi],eax
	mov	dword [esi+4],0
	mov	ecx,edx
	mul	dword [edi]
      div_high_loop:
	cmp	ecx,edx
	ja	div_high_done
	jb	div_high_large_correction
	cmp	ebx,eax
	jae	div_high_done
      div_high_correction:
	dec	dword [esi]
	sub	eax,[edi]
	sbb	edx,[edi+4]
	jnc	div_high_loop
      div_high_done:
	sub	ebx,eax
	sbb	ecx,edx
	mov	edx,ecx
	mov	eax,ebx
	ret
      div_high_large_correction:
	push	eax edx
	mov	eax,edx
	sub	eax,ecx
	xor	edx,edx
	div	dword [edi+4]
	shr	eax,1
	jz	div_high_small_correction
	sub	[esi],eax
	push	eax
	mul	dword [edi+4]
	sub	dword [esp+4],eax
	pop	eax
	mul	dword [edi]
	sub	dword [esp+4],eax
	sbb	dword [esp],edx
	pop	edx eax
	jmp	div_high_loop
      div_high_small_correction:
	pop	edx eax
	jmp	div_high_correction
      div_done:
	or	bh,bh
	jz	remainder_ok
	not	eax
	not	edx
	add	eax,1
	adc	edx,0
      remainder_ok:
	or	bl,bl
	jz	div_ok
	not	dword [esi]
	not	dword [esi+4]
	add	dword [esi],1
	adc	dword [esi+4],0
      div_ok:
	ret
      convert_fp:
	inc	esi
	mov	word [edi+8],0
	mov	byte [edi+12],0
	mov	al,[value_size]
	cmp	al,2
	je	convert_fp_word
	cmp	al,4
	je	convert_fp_dword
	cmp	al,8
	je	convert_fp_qword
	jmp	invalid_value
      convert_fp_word:
	xor	eax,eax
	cmp	word [esi+8],8000h
	je	fp_word_store
	mov	bx,[esi+8]
	mov	ax,[esi+6]
	shl	ax,1
	shr	ax,6
	jnc	fp_word_ok
	inc	ax
	bt	ax,10
	jnc	fp_word_ok
	and	ax,1 shl 10 - 1
	inc	bx
	shr	ax,1
      fp_word_ok:
	add	bx,0Fh
	cmp	bx,01Fh
	jge	value_out_of_range
	cmp	bx,0
	jg	fp_word_exp_ok
	or	ax,1 shl 10
	mov	cx,bx
	neg	cx
	inc	cx
	cmp	cx,10
	ja	value_out_of_range
	xor	bx,bx
	shr	ax,cl
	jnc	fp_word_exp_ok
	inc	ax
	test	ax,1 shl 10
	jz	fp_word_exp_ok
	and	ax,1 shl 10 - 1
	inc	bx
      fp_word_exp_ok:
	shl	bx,10
	or	ax,bx
      fp_word_store:
	mov	bl,[esi+11]
	shl	bx,15
	or	ax,bx
	mov	[edi],eax
	xor	eax,eax
	mov	[edi+4],eax
	add	esi,13
	ret
      convert_fp_dword:
	xor	eax,eax
	cmp	word [esi+8],8000h
	je	fp_dword_store
	mov	bx,[esi+8]
	mov	eax,[esi+4]
	shl	eax,1
	shr	eax,9
	jnc	fp_dword_ok
	inc	eax
	bt	eax,23
	jnc	fp_dword_ok
	and	eax,1 shl 23 - 1
	inc	bx
	shr	eax,1
      fp_dword_ok:
	add	bx,7Fh
	cmp	bx,0FFh
	jge	value_out_of_range
	cmp	bx,0
	jg	fp_dword_exp_ok
	or	eax,1 shl 23
	mov	cx,bx
	neg	cx
	inc	cx
	cmp	cx,23
	ja	value_out_of_range
	xor	bx,bx
	shr	eax,cl
	jnc	fp_dword_exp_ok
	inc	eax
	test	eax,1 shl 23
	jz	fp_dword_exp_ok
	and	eax,1 shl 23 - 1
	inc	bx
      fp_dword_exp_ok:
	shl	ebx,23
	or	eax,ebx
      fp_dword_store:
	mov	bl,[esi+11]
	shl	ebx,31
	or	eax,ebx
	mov	[edi],eax
	xor	eax,eax
	mov	[edi+4],eax
	add	esi,13
	ret
      convert_fp_qword:
	xor	eax,eax
	xor	edx,edx
	cmp	word [esi+8],8000h
	je	fp_qword_store
	mov	bx,[esi+8]
	mov	eax,[esi]
	mov	edx,[esi+4]
	add	eax,eax
	adc	edx,edx
	mov	ecx,edx
	shr	edx,12
	shrd	eax,ecx,12
	jnc	fp_qword_ok
	add	eax,1
	adc	edx,0
	bt	edx,20
	jnc	fp_qword_ok
	and	edx,1 shl 20 - 1
	inc	bx
	shr	edx,1
	rcr	eax,1
      fp_qword_ok:
	add	bx,3FFh
	cmp	bx,7FFh
	jge	value_out_of_range
	cmp	bx,0
	jg	fp_qword_exp_ok
	or	edx,1 shl 20
	mov	cx,bx
	neg	cx
	inc	cx
	cmp	cx,52
	ja	value_out_of_range
	cmp	cx,32
	jbe	fp_qword_small_shift
	sub	cx,32
	mov	eax,edx
	xor	edx,edx
	shr	eax,cl
	jmp	fp_qword_shift_done
      fp_qword_small_shift:
	mov	ebx,edx
	shr	edx,cl
	shrd	eax,ebx,cl
      fp_qword_shift_done:
	mov	bx,0
	jnc	fp_qword_exp_ok
	add	eax,1
	adc	edx,0
	test	edx,1 shl 20
	jz	fp_qword_exp_ok
	and	edx,1 shl 20 - 1
	inc	bx
      fp_qword_exp_ok:
	shl	ebx,20
	or	edx,ebx
      fp_qword_store:
	mov	bl,[esi+11]
	shl	ebx,31
	or	edx,ebx
	mov	[edi],eax
	mov	[edi+4],edx
	add	esi,13
	ret
      get_string_value:
	inc	esi
	lods	dword [esi]
	mov	ecx,eax
	cmp	ecx,8
	ja	value_out_of_range
	mov	edx,edi
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	mov	edi,edx
	rep	movs byte [edi],[esi]
	mov	edi,edx
	inc	esi
	mov	word [edi+8],0
	mov	byte [edi+12],0
	ret

get_byte_value:
	mov	[value_size],1
	mov	[size_override],-1
	call	calculate_expression
	mov	eax,[edi+16]
	mov	[symbol_identifier],eax
	mov	[value_type],0
	cmp	word [edi+8],0
	jne	invalid_value
	cmp	byte [edi+12],0
	je	check_byte_value
	cmp	[error_line],0
	jne	check_byte_value
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      check_byte_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	or	edx,edx
	jz	byte_positive
	cmp	edx,-1
	jne	range_exceeded
	cmp	eax,-80h
	jb	range_exceeded
	ret
      byte_positive:
	cmp	eax,100h
	jae	range_exceeded
      return_byte_value:
	ret
      range_exceeded:
	xor	eax,eax
	xor	edx,edx
	cmp	[error_line],0
	jne	return_byte_value
	mov	ecx,[current_line]
	mov	[error_line],ecx
	mov	[error],value_out_of_range
	ret
get_word_value:
	mov	[value_size],2
	mov	[size_override],-1
	call	calculate_expression
	cmp	word [edi+8],0
	jne	invalid_value
	mov	eax,[edi+16]
	mov	[symbol_identifier],eax
	mov	al,[edi+12]
	mov	[value_type],al
	cmp	al,2
	jb	check_word_value
	cmp	[error_line],0
	jne	check_word_value
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      check_word_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	or	edx,edx
	jz	word_positive
	cmp	edx,-1
	jne	range_exceeded
	cmp	eax,-8000h
	jb	range_exceeded
	ret
      word_positive:
	cmp	eax,10000h
	jae	range_exceeded
	ret
get_dword_value:
	mov	[value_size],4
	mov	[size_override],-1
	call	calculate_expression
	cmp	word [edi+8],0
	jne	invalid_value
	mov	eax,[edi+16]
	mov	[symbol_identifier],eax
	mov	al,[edi+12]
	mov	[value_type],al
	cmp	al,4
	jne	check_dword_value
	mov	[value_type],2
	mov	eax,[edi]
	cdq
	cmp	edx,[edi+4]
	jne	range_exceeded
	ret
      check_dword_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	or	edx,edx
	jz	dword_positive
	cmp	edx,-1
	jne	range_exceeded
	bt	eax,31
	jnc	range_exceeded
      dword_positive:
	ret
get_pword_value:
	mov	[value_size],6
	mov	[size_override],-1
	call	calculate_expression
	mov	eax,[edi+16]
	mov	[symbol_identifier],eax
	cmp	word [edi+8],0
	jne	invalid_value
	mov	al,[edi+12]
	mov	[value_type],al
	cmp	al,4
	jne	check_pword_value
	cmp	[error_line],0
	jne	check_pword_value
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      check_pword_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	cmp	edx,10000h
	jge	range_exceeded
	cmp	edx,-8000h
	jl	range_exceeded
	ret
get_qword_value:
	mov	[value_size],8
	mov	[size_override],-1
	call	calculate_expression
	cmp	word [edi+8],0
	jne	invalid_value
	mov	eax,[edi+16]
	mov	[symbol_identifier],eax
	mov	al,[edi+12]
	mov	[value_type],al
      check_qword_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	ret
get_count_value:
	mov	[value_size],8
	mov	[size_override],-1
	call	calculate_expression
	cmp	word [edi+8],0
	jne	invalid_value
	mov	al,[edi+12]
	or	al,al
	jz	check_count_value
	cmp	[error_line],0
	jne	check_count_value
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_use_of_symbol
      check_count_value:
	mov	eax,[edi]
	mov	edx,[edi+4]
	or	edx,edx
	jnz	invalid_count_value
	ret
      invalid_count_value:
	cmp	[error_line],0
	jne	zero_count
	mov	eax,[current_line]
	mov	[error_line],eax
	mov	[error],invalid_value
      zero_count:
	xor	eax,eax
	ret
get_value:
	mov	[operand_size],0
	lods	byte [esi]
	call	get_size_operator
	cmp	al,'('
	jne	invalid_value
	mov	al,[operand_size]
	cmp	al,1
	je	value_byte
	cmp	al,2
	je	value_word
	cmp	al,4
	je	value_dword
	cmp	al,6
	je	value_pword
	cmp	al,8
	je	value_qword
	or	al,al
	jnz	invalid_value
      value_qword:
	call	get_qword_value
	ret
      value_pword:
	call	get_pword_value
	movzx	edx,dx
	ret
      value_dword:
	call	get_dword_value
	xor	edx,edx
	ret
      value_word:
	call	get_word_value
	xor	edx,edx
	movzx	eax,ax
	ret
      value_byte:
	call	get_byte_value
	xor	edx,edx
	movzx	eax,al
	ret
get_address_word_value:
	mov	[address_size],2
	mov	[value_size],2
	jmp	calculate_address
get_address_dword_value:
	mov	[address_size],4
	mov	[value_size],4
	jmp	calculate_address
get_address_qword_value:
	mov	[address_size],8
	mov	[value_size],8
	jmp	calculate_address
get_address_value:
	mov	[address_size],0
	mov	[value_size],8
      calculate_address:
	cmp	byte [esi],'.'
	je	invalid_address
	call	calculate_expression
	mov	eax,[edi+16]
	mov	[address_symbol],eax
	mov	al,[edi+12]
	mov	[value_type],al
	cmp	al,6
	je	special_address_type_32bit
	cmp	al,5
	je	special_address_type_32bit
	ja	invalid_use_of_symbol
	test	al,1
	jnz	invalid_use_of_symbol
	or	al,al
	jz	address_size_ok
	shl	al,5
	jmp	address_symbol_ok
      special_address_type_32bit:
	mov	al,40h
      address_symbol_ok:
	mov	ah,[address_size]
	or	[address_size],al
	shr	al,4
	or	ah,ah
	jz	address_size_ok
	cmp	al,ah
	je	address_size_ok
	cmp	ax,0804h
	jne	address_sizes_do_not_agree
	cmp	[value_type],2
	ja	value_type_correction_ok
	mov	[value_type],2
      value_type_correction_ok:
	mov	eax,[edi]
	cdq
	cmp	edx,[edi+4]
	je	address_size_ok
	cmp	[error_line],0
	jne	address_size_ok
	mov	ecx,[current_line]
	mov	[error_line],ecx
	mov	[error],value_out_of_range
      address_size_ok:
	xor	ebx,ebx
	xor	ecx,ecx
	mov	cl,[value_type]
	shl	ecx,16
	mov	ch,[address_size]
	cmp	word [edi+8],0
	je	check_immediate_address
	mov	al,[edi+8]
	mov	dl,[edi+10]
	call	get_address_register
	mov	al,[edi+9]
	mov	dl,[edi+11]
	call	get_address_register
	mov	ax,bx
	shr	ah,4
	shr	al,4
	or	bh,bh
	jz	check_address_registers
	or	bl,bl
	jz	check_address_registers
	cmp	al,ah
	jne	invalid_address
      check_address_registers:
	or	al,ah
	mov	ah,[address_size]
	and	ah,0Fh
	jz	address_registers_sizes_ok
	cmp	al,ah
	jne	address_sizes_do_not_match
      address_registers_sizes_ok:
	cmp	al,4
	je	sib_allowed
	cmp	al,8
	je	sib_allowed
	cmp	al,0Fh
	je	check_ip_relative_address
	or	cl,cl
	jz	check_word_value
	cmp	cl,1
	je	check_word_value
	jmp	invalid_address
      address_sizes_do_not_match:
	cmp	al,0Fh
	jne	invalid_address
	mov	al,bh
	and	al,0Fh
	cmp	al,ah
	jne	invalid_address
      check_ip_relative_address:
	cmp	bh,0F4h
	je	check_dword_value
	cmp	bh,0F8h
	jne	invalid_address
	mov	eax,[edi]
	cdq
	cmp	edx,[edi+4]
	jne	range_exceeded
	ret
      get_address_register:
	or	al,al
	jz	address_register_ok
	cmp	dl,1
	jne	scaled_register
	or	bh,bh
	jnz	scaled_register
	mov	bh,al
      address_register_ok:
	ret
      scaled_register:
	or	bl,bl
	jnz	invalid_address
	mov	bl,al
	mov	cl,dl
	jmp	address_register_ok
      sib_allowed:
	or	bh,bh
	jnz	check_index_with_base
	cmp	cl,3
	je	special_index_scale
	cmp	cl,5
	je	special_index_scale
	cmp	cl,9
	je	special_index_scale
	cmp	cl,2
	jne	check_index_scale
	cmp	bl,45h
	jne	special_index_scale
	cmp	[code_type],64
	je	special_index_scale
	cmp	[segment_register],4
	jne	special_index_scale
	cmp	[value_type],0
	jne	check_index_scale
	mov	al,[edi]
	cbw
	cwde
	cmp	eax,[edi]
	jne	check_index_scale
	cdq
	cmp	edx,[edi+4]
	jne	check_immediate_address
      special_index_scale:
	mov	bh,bl
	dec	cl
      check_immediate_address:
	mov	al,[address_size]
	and	al,0Fh
	cmp	al,2
	je	check_word_value
	cmp	al,4
	je	check_dword_value
	cmp	al,8
	je	check_qword_value
	or	al,al
	jnz	invalid_value
	cmp	[code_type],64
	jne	check_dword_value
	jmp	check_qword_value
      check_index_with_base:
	cmp	cl,1
	jne	check_index_scale
	cmp	bl,44h
	je	swap_base_with_index
	cmp	bl,84h
	je	swap_base_with_index
	cmp	[code_type],64
	je	check_for_rbp_base
	cmp	bl,45h
	jne	check_for_ebp_base
	cmp	[segment_register],3
	je	swap_base_with_index
	jmp	check_immediate_address
      check_for_ebp_base:
	cmp	bh,45h
	jne	check_immediate_address
	cmp	[segment_register],4
	jne	check_immediate_address
      swap_base_with_index:
	xchg	bl,bh
	jmp	check_immediate_address
      check_for_rbp_base:
	cmp	bh,45h
	je	swap_base_with_index
	cmp	bh,85h
	je	swap_base_with_index
	jmp	check_immediate_address
      check_index_scale:
	test	cl,not 1111b
	jnz	invalid_address
	mov	al,cl
	dec	al
	and	al,cl
	jz	check_immediate_address
	jmp	invalid_address
calculate_relative_offset:
	cmp	[value_undefined],0
	jne	relative_offset_ok
	test	bh,bh
	setne	ch
	cmp	bx,word [org_registers]
	je	origin_registers_ok
	xchg	bh,bl
	xchg	ch,cl
	cmp	bx,word [org_registers]
	jne	invalid_value
      origin_registers_ok:
	cmp	cx,word [org_registers+2]
	jne	invalid_value
	add	eax,dword [org_origin]
	adc	edx,dword [org_origin+4]
	sub	eax,edi
	sbb	edx,0
	mov	bl,[value_type]
	or	bl,bl
	je	relative_offset_ok
	test	bl,1
	jnz	invalid_use_of_symbol
	mov	ecx,[address_symbol]
	mov	[symbol_identifier],ecx
	cmp	bl,6
	je	plt_relative_offset
	cmp	bl,[labels_type]
	jne	invalid_use_of_symbol
	mov	[value_type],0
	cmp	ecx,[org_symbol]
	je	relative_offset_ok
	mov	[value_type],3
      relative_offset_ok:
	ret
      plt_relative_offset:
	mov	[value_type],7
	ret

calculate_logical_expression:
	xor	al,al
  calculate_embedded_logical_expression:
	mov	[logical_value_wrapping],al
	call	get_logical_value
      logical_loop:
	cmp	byte [esi],'|'
	je	logical_or
	cmp	byte [esi],'&'
	je	logical_and
	ret
      logical_or:
	inc	esi
	or	al,al
	jnz	logical_value_already_determined
	push	eax
	call	get_logical_value
	pop	ebx
	or	al,bl
	jmp	logical_loop
      logical_and:
	inc	esi
	or	al,al
	jz	logical_value_already_determined
	push	eax
	call	get_logical_value
	pop	ebx
	and	al,bl
	jmp	logical_loop
      logical_value_already_determined:
	push	eax
	call	skip_logical_value
	jc	invalid_expression
	pop	eax
	jmp	logical_loop
  get_logical_value:
	xor	al,al
      check_for_negation:
	cmp	byte [esi],'~'
	jne	negation_ok
	inc	esi
	xor	al,-1
	jmp	check_for_negation
      negation_ok:
	push	eax
	mov	al,[esi]
	cmp	al,'{'
	je	logical_expression
	cmp	al,0FFh
	je	invalid_expression
	cmp	al,88h
	je	check_for_defined
	cmp	al,89h
	je	check_for_used
	cmp	al,'0'
	je	given_false
	cmp	al,'1'
	je	given_true
	call	get_value
	mov	bl,[value_type]
	push	eax edx ebx
	mov	al,[esi]
	or	al,al
	jz	logical_number
	cmp	al,0Fh
	je	logical_number
	cmp	al,'}'
	je	logical_number
	cmp	al,'&'
	je	logical_number
	cmp	al,'|'
	je	logical_number
	inc	esi
	mov	[compare_type],al
	call	get_value
	pop	ebx
	cmp	[next_pass_needed],0
	jne	values_ok
	cmp	bl,[value_type]
	jne	invalid_use_of_symbol
      values_ok:
	pop	ecx ebx
	cmp	[compare_type],'='
	je	check_equal
	cmp	[compare_type],'>'
	je	check_greater
	cmp	[compare_type],'<'
	je	check_less
	cmp	[compare_type],0F1h
	je	check_not_equal
	cmp	[compare_type],0F2h
	je	check_not_less
	cmp	[compare_type],0F3h
	je	check_not_greater
	jmp	invalid_expression
      check_equal:
	cmp	eax,ebx
	jne	return_false
	cmp	edx,ecx
	jne	return_false
	jmp	return_true
      check_greater:
	cmp	edx,ecx
	jl	return_true
	jg	return_false
	cmp	eax,ebx
	jb	return_true
	jae	return_false
      check_less:
	cmp	edx,ecx
	jl	return_false
	jg	return_true
	cmp	eax,ebx
	jbe	return_false
	ja	return_true
      check_not_less:
	cmp	edx,ecx
	jl	return_true
	jg	return_false
	cmp	eax,ebx
	jbe	return_true
	ja	return_false
      check_not_greater:
	cmp	edx,ecx
	jl	return_false
	jg	return_true
	cmp	eax,ebx
	jb	return_false
	jae	return_true
      check_not_equal:
	cmp	eax,ebx
	jne	return_true
	cmp	edx,ecx
	jne	return_true
	jmp	return_false
      logical_number:
	pop	ebx edx eax
	or	bl,bl
	jnz	invalid_expression
	or	eax,edx
	jnz	return_true
	jmp	return_false
      check_for_defined:
	or	bl,-1
	lods	word [esi]
	cmp	ah,'('
	jne	invalid_expression
      check_expression:
	lods	byte [esi]
	or	al,al
	jz	defined_string
	cmp	al,'.'
	je	defined_fp_value
	cmp	al,')'
	je	expression_checked
	cmp	al,'!'
	je	invalid_expression
	cmp	al,0Fh
	je	check_expression
	cmp	al,10h
	je	defined_register
	cmp	al,11h
	je	check_if_symbol_defined
	cmp	al,80h
	jae	check_expression
	movzx	eax,al
	add	esi,eax
	jmp	check_expression
      defined_register:
	inc	esi
	jmp	check_expression
      defined_fp_value:
	add	esi,12
	jmp	expression_checked
      defined_string:
	lods	dword [esi]
	add	esi,eax
	inc	esi
	jmp	expression_checked
      check_if_symbol_defined:
	lods	dword [esi]
	cmp	eax,-1
	je	invalid_expression
	cmp	eax,0Fh
	jb	check_expression
	je	reserved_word_used_as_symbol
	test	byte [eax+8],4
	jnz	no_prediction
	test	byte [eax+8],1
	jz	symbol_predicted_undefined
	mov	cx,[current_pass]
	sub	cx,[eax+16]
	jz	check_expression
	cmp	cx,1
	ja	symbol_predicted_undefined
	or	byte [eax+8],40h+80h
	jmp	check_expression
      no_prediction:
	test	byte [eax+8],1
	jz	symbol_undefined
	mov	cx,[current_pass]
	sub	cx,[eax+16]
	jz	check_expression
	jmp	symbol_undefined
      symbol_predicted_undefined:
	or	byte [eax+8],40h
	and	byte [eax+8],not 80h
      symbol_undefined:
	xor	bl,bl
	jmp	check_expression
      expression_checked:
	mov	al,bl
	jmp	logical_value_ok
      check_for_used:
	lods	word [esi]
	cmp	ah,2
	jne	invalid_expression
	lods	dword [esi]
	cmp	eax,0Fh
	jb	invalid_use_of_symbol
	je	reserved_word_used_as_symbol
	inc	esi
	test	byte [eax+8],8
	jz	not_used
	mov	cx,[current_pass]
	sub	cx,[eax+18]
	jz	return_true
	cmp	cx,1
	ja	not_used
	or	byte [eax+8],10h+20h
	jmp	return_true
      not_used:
	or	byte [eax+8],10h
	and	byte [eax+8],not 20h
	jmp	return_false
      given_false:
	inc	esi
      return_false:
	xor	al,al
	jmp	logical_value_ok
      given_true:
	inc	esi
      return_true:
	or	al,-1
	jmp	logical_value_ok
      logical_expression:
	lods	byte [esi]
	mov	dl,[logical_value_wrapping]
	push	edx
	call	calculate_embedded_logical_expression
	pop	edx
	mov	[logical_value_wrapping],dl
	push	eax
	lods	byte [esi]
	cmp	al,'}'
	jne	invalid_expression
	pop	eax
      logical_value_ok:
	pop	ebx
	xor	al,bl
	ret

skip_symbol:
	lods	byte [esi]
	or	al,al
	jz	nothing_to_skip
	cmp	al,0Fh
	je	nothing_to_skip
	cmp	al,1
	je	skip_instruction
	cmp	al,2
	je	skip_label
	cmp	al,3
	je	skip_label
	cmp	al,20h
	jb	skip_assembler_symbol
	cmp	al,'('
	je	skip_expression
	cmp	al,'['
	je	skip_address
      skip_done:
	clc
	ret
      skip_label:
	add	esi,2
      skip_instruction:
	add	esi,2
      skip_assembler_symbol:
	inc	esi
	jmp	skip_done
      skip_address:
	mov	al,[esi]
	and	al,11110000b
	cmp	al,60h
	jb	skip_expression
	cmp	al,70h
	ja	skip_expression
	inc	esi
	jmp	skip_address
      skip_expression:
	lods	byte [esi]
	or	al,al
	jz	skip_string
	cmp	al,'.'
	je	skip_fp_value
	cmp	al,')'
	je	skip_done
	cmp	al,']'
	je	skip_done
	cmp	al,'!'
	je	skip_expression
	cmp	al,0Fh
	je	skip_expression
	cmp	al,10h
	je	skip_register
	cmp	al,11h
	je	skip_label_value
	cmp	al,80h
	jae	skip_expression
	movzx	eax,al
	add	esi,eax
	jmp	skip_expression
      skip_label_value:
	add	esi,3
      skip_register:
	inc	esi
	jmp	skip_expression
      skip_fp_value:
	add	esi,12
	jmp	skip_done
      skip_string:
	lods	dword [esi]
	add	esi,eax
	inc	esi
	jmp	skip_done
      nothing_to_skip:
	dec	esi
	stc
	ret
