4253 lines
95 KiB
PHP
4253 lines
95 KiB
PHP
|
|
struct ExpressionTerm
|
|
attributes dd ? ; EXPR_# in low byte, plus any EXPRF_#
|
|
metadata dd ?
|
|
value dd ?
|
|
ends
|
|
|
|
EXPR_NUMBER = 30h
|
|
EXPR_STRING = 22h
|
|
EXPR_FLOAT = 2Eh
|
|
|
|
EXPR_SYMBOL_VALUE = 10h
|
|
EXPR_OPERATOR = 20h
|
|
EXPR_SYMBOL = 40h
|
|
|
|
EXPR_POLYNOMIAL = 31h
|
|
|
|
EXPR_MISSING_ARGUMENT = 29h
|
|
EXPR_MISSING_PARENTHESIS = 28h
|
|
|
|
EXPRF_VALUE_IN_WORKSPACE = 100h
|
|
EXPRF_CALM_LITERAL = 200h
|
|
|
|
EXPRF_OPERATOR_UNARY = 1000h
|
|
|
|
convert_number:
|
|
; in:
|
|
; edx - 32-bit length followed by a string of that length
|
|
; out:
|
|
; cf set when number has no known prefix or suffix but is not a plain decimal number
|
|
; when cf = 0:
|
|
; edx - 32-bit length followed by binary data of that length, null when string did not represent a valid number
|
|
; when cf = 1:
|
|
; edx preserved
|
|
; preserves: esi
|
|
mov edi,[value_workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,[edx]
|
|
add edx,4
|
|
cmp byte [edx],'$'
|
|
je pascal_hexadecimal_number
|
|
cmp ecx,2
|
|
jb check_number_suffix
|
|
cmp word [edx],'0x'
|
|
je c_hexadecimal_number
|
|
check_number_suffix:
|
|
movzx eax,byte [edx+ecx-1]
|
|
mov al,[characters+eax]
|
|
cmp al,'h'
|
|
je suffixed_hexadecimal_number
|
|
cmp al,'b'
|
|
je suffixed_binary_number
|
|
cmp al,'o'
|
|
je suffixed_octal_number
|
|
cmp al,'q'
|
|
je suffixed_octal_number
|
|
cmp al,'d'
|
|
jne decimal_number
|
|
or ah,1
|
|
dec ecx
|
|
jz invalid_number
|
|
decimal_number:
|
|
mov ebx,ecx
|
|
check_decimal_digits:
|
|
mov al,[edx+ebx-1]
|
|
cmp al,27h
|
|
je check_next_decimal_digit
|
|
cmp al,'_'
|
|
je check_next_decimal_digit
|
|
cmp al,'0'
|
|
jb unknown_number
|
|
cmp al,'9'
|
|
ja unknown_number
|
|
check_next_decimal_digit:
|
|
dec ebx
|
|
jnz check_decimal_digits
|
|
push ecx edx
|
|
add ecx,12
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
xor eax,eax
|
|
mov dword [edi+4],eax
|
|
add eax,4
|
|
mov dword [edi],eax
|
|
pop edx ebx
|
|
convert_decimal_number:
|
|
mov al,[edx]
|
|
cmp al,27h
|
|
je skip_decimal_digit
|
|
cmp al,'_'
|
|
je skip_decimal_digit
|
|
sub al,'0'
|
|
mov ecx,[edi]
|
|
xor ecx,ecx
|
|
add_decimal_digit:
|
|
add ecx,4
|
|
movzx eax,al
|
|
add [edi+ecx],eax
|
|
setc al
|
|
sets ah
|
|
cmp ecx,[edi]
|
|
jb add_decimal_digit
|
|
or ah,al
|
|
jz decimal_digit_added
|
|
xor ah,ah
|
|
add ecx,4
|
|
mov [edi+ecx],eax
|
|
mov [edi],ecx
|
|
decimal_digit_added:
|
|
dec ebx
|
|
jz decimal_number_converted
|
|
next_decimal_digit:
|
|
inc edx
|
|
push ebx edx
|
|
mov ebx,10
|
|
xor ecx,ecx
|
|
xor edx,edx
|
|
multiply_decimal_number:
|
|
add ecx,4
|
|
mov eax,[edi+ecx]
|
|
mov [edi+ecx],edx
|
|
mul ebx
|
|
add [edi+ecx],eax
|
|
cmp ecx,[edi]
|
|
jb multiply_decimal_number
|
|
test edx,edx
|
|
jz decimal_number_multiplied
|
|
add ecx,4
|
|
mov [edi+ecx],edx
|
|
mov [edi],ecx
|
|
decimal_number_multiplied:
|
|
pop edx ebx
|
|
xor eax,eax
|
|
jmp convert_decimal_number
|
|
skip_decimal_digit:
|
|
inc edx
|
|
dec ebx
|
|
jnz convert_decimal_number
|
|
decimal_number_converted:
|
|
lea edx,[edi+4]
|
|
mov ecx,[edi]
|
|
dec ecx
|
|
optimize_number:
|
|
movsx eax,byte [edx+ecx-1]
|
|
cmp ah,[edx+ecx]
|
|
jne number_optimized
|
|
loop optimize_number
|
|
cmp byte [edx],0
|
|
je number_finished
|
|
number_optimized:
|
|
inc ecx
|
|
number_finished:
|
|
sub edx,4
|
|
mov [edx],ecx
|
|
lea edi,[edx+4+ecx]
|
|
sub edi,[value_workspace.memory_start]
|
|
mov [value_position],edi
|
|
; clc
|
|
retn
|
|
c_hexadecimal_number:
|
|
sub ecx,3
|
|
jc invalid_number
|
|
add edx,2
|
|
jmp hexadecimal_number
|
|
pascal_hexadecimal_number:
|
|
inc edx
|
|
suffixed_hexadecimal_number:
|
|
sub ecx,2
|
|
jc invalid_number
|
|
hexadecimal_number:
|
|
push edx ecx
|
|
shr ecx,1
|
|
add ecx,6
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
pop ebx edx
|
|
push edi
|
|
xor eax,eax
|
|
stosd
|
|
mov [edi],al
|
|
xor cl,cl
|
|
hexadecimal_digit:
|
|
movzx eax,byte [edx+ebx]
|
|
cmp al,27h
|
|
je skip_hexadecimal_digit
|
|
cmp al,'_'
|
|
je skip_hexadecimal_digit
|
|
mov al,[characters+eax]
|
|
sub al,'0'
|
|
jc invalid_digit
|
|
cmp al,10
|
|
jb hexadecimal_digit_ok
|
|
sub al,'a'-'0'
|
|
jc invalid_digit
|
|
add al,10
|
|
cmp al,16
|
|
jae invalid_digit
|
|
hexadecimal_digit_ok:
|
|
shl al,cl
|
|
or [edi],al
|
|
sub ebx,1
|
|
jc number_converted
|
|
xor cl,4
|
|
jnz hexadecimal_digit
|
|
inc edi
|
|
mov [edi],cl
|
|
jmp hexadecimal_digit
|
|
skip_hexadecimal_digit:
|
|
sub ebx,1
|
|
jnc hexadecimal_digit
|
|
number_converted:
|
|
pop edx
|
|
inc edi
|
|
and byte [edi],0
|
|
add edx,4
|
|
mov ecx,edi
|
|
sub ecx,edx
|
|
jmp optimize_number
|
|
suffixed_binary_number:
|
|
sub ecx,2
|
|
jc invalid_number
|
|
push edx ecx
|
|
shr ecx,3
|
|
add ecx,6
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
pop ebx edx
|
|
push edi
|
|
xor eax,eax
|
|
stosd
|
|
mov [edi],al
|
|
xor cl,cl
|
|
binary_digit:
|
|
mov al,[edx+ebx]
|
|
cmp al,27h
|
|
je skip_binary_digit
|
|
cmp al,'_'
|
|
je skip_binary_digit
|
|
sub al,'0'
|
|
jc invalid_digit
|
|
cmp al,2
|
|
jae invalid_digit
|
|
shl al,cl
|
|
or [edi],al
|
|
sub ebx,1
|
|
jc number_converted
|
|
inc cl
|
|
and cl,111b
|
|
jnz binary_digit
|
|
inc edi
|
|
mov [edi],cl
|
|
jmp binary_digit
|
|
skip_binary_digit:
|
|
sub ebx,1
|
|
jnc binary_digit
|
|
jmp number_converted
|
|
suffixed_octal_number:
|
|
sub ecx,2
|
|
jc invalid_number
|
|
push edx ecx
|
|
shr ecx,1
|
|
add ecx,6
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
pop ebx edx
|
|
push edi
|
|
xor eax,eax
|
|
stosd
|
|
mov [edi],al
|
|
xor cl,cl
|
|
octal_digit:
|
|
mov al,[edx+ebx]
|
|
cmp al,27h
|
|
je skip_octal_digit
|
|
cmp al,'_'
|
|
je skip_octal_digit
|
|
sub al,'0'
|
|
jc invalid_digit
|
|
cmp al,8
|
|
jae invalid_digit
|
|
shl eax,cl
|
|
or [edi],al
|
|
add cl,3
|
|
cmp cl,8
|
|
jb skip_octal_digit
|
|
sub cl,8
|
|
inc edi
|
|
mov [edi],ah
|
|
xor eax,eax
|
|
skip_octal_digit:
|
|
sub ebx,1
|
|
jnc octal_digit
|
|
jmp number_converted
|
|
unknown_number:
|
|
test ah,ah
|
|
jnz invalid_number
|
|
sub edx,4
|
|
stc
|
|
retn
|
|
invalid_digit:
|
|
pop edi
|
|
invalid_number:
|
|
xor edx,edx
|
|
mov al,30h
|
|
clc
|
|
retn
|
|
|
|
convert_number_back:
|
|
; in:
|
|
; edx - 32-bit length followed by binary data of that length
|
|
; out:
|
|
; edx - 32-bit length followed by a string of that length
|
|
; note:
|
|
; the number is treated as unsigned
|
|
; returned string is in temporary storage and should be copied out of it immediately
|
|
mov edi,[value_workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,[edx]
|
|
add ecx,2
|
|
shl ecx,2
|
|
mov esi,edx
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
lodsd
|
|
lea ebx,[edi+4+(eax+1)*4]
|
|
mov edx,edi
|
|
mov ecx,eax
|
|
rep movsb
|
|
xchg eax,ecx
|
|
stosd
|
|
jecxz highest_dword_offset_ok
|
|
dec ecx
|
|
and ecx,not 11b
|
|
highest_dword_offset_ok:
|
|
mov esi,edx
|
|
mov edi,ebx
|
|
push edi
|
|
obtain_digit:
|
|
xor edx,edx
|
|
divide_highest_dwords:
|
|
mov eax,[esi+ecx]
|
|
call div10
|
|
test eax,eax
|
|
jnz more_digits_to_come
|
|
sub ecx,4
|
|
jnc divide_highest_dwords
|
|
pop ecx
|
|
cmp ecx,edi
|
|
je store_final_digit
|
|
test dl,dl
|
|
jz finish_number
|
|
store_final_digit:
|
|
add dl,'0'
|
|
dec edi
|
|
mov [edi],dl
|
|
finish_number:
|
|
sub ecx,edi
|
|
sub edi,4
|
|
mov [edi],ecx
|
|
mov edx,edi
|
|
retn
|
|
more_digits_to_come:
|
|
mov ebx,ecx
|
|
divide_remaining_dwords:
|
|
mov [esi+ebx],eax
|
|
sub ebx,4
|
|
jc store_digit
|
|
mov eax,[esi+ebx]
|
|
call div10
|
|
jmp divide_remaining_dwords
|
|
store_digit:
|
|
add dl,'0'
|
|
dec edi
|
|
mov [edi],dl
|
|
jmp obtain_digit
|
|
div10:
|
|
; cmp edx,10
|
|
; jae internal_error
|
|
push ebx ecx
|
|
push eax
|
|
mov ebx,eax
|
|
mov ecx,edx
|
|
shld edx,eax,2
|
|
sub ebx,edx
|
|
sbb ecx,0
|
|
mov eax,ebx
|
|
mov ebx,1999999Ah
|
|
mul ebx
|
|
mov eax,ecx
|
|
imul eax,ebx
|
|
add eax,edx
|
|
pop edx
|
|
imul ecx,eax,10
|
|
sub edx,ecx
|
|
cmp edx,10
|
|
jb div10_done
|
|
sub edx,10
|
|
inc eax
|
|
div10_done:
|
|
pop ecx ebx
|
|
retn
|
|
|
|
fit_value:
|
|
; in:
|
|
; edx - 32-bit length followed by numeric data
|
|
; ecx = number of bytes that the value has to fit into
|
|
; edi - buffer for the specified amount of bytes, null when just checking whether value fits in range
|
|
; out:
|
|
; sf set when value is negative
|
|
; cf set if value does not fit into extended range for specified size
|
|
; when cf = 0:
|
|
; edi - value fit into specified amount of bytes
|
|
; preserves: edx, esi, edi
|
|
; note: when value is zero, it fits even into zero byte range
|
|
mov ebx,ecx
|
|
cmp [edx],ecx
|
|
jbe term_in_range
|
|
xor al,al
|
|
cmp [edx+4+ecx],al
|
|
je check_redundant_bytes
|
|
dec al
|
|
cmp [edx+4+ecx],al
|
|
jne term_out_of_range
|
|
jecxz term_out_of_range
|
|
check_redundant_bytes:
|
|
inc ecx
|
|
cmp ecx,[edx]
|
|
je term_in_range
|
|
cmp [edx+4+ecx],al
|
|
je check_redundant_bytes
|
|
term_out_of_range:
|
|
mov ecx,[edx]
|
|
mov al,[edx+4+ecx-1]
|
|
test al,al
|
|
stc
|
|
retn
|
|
term_in_range:
|
|
test edi,edi
|
|
jz value_fit
|
|
mov ecx,[edx]
|
|
cmp ecx,ebx
|
|
jbe copy_value
|
|
mov ecx,ebx
|
|
copy_value:
|
|
lea eax,[edx+4]
|
|
xchg eax,esi
|
|
rep movsb
|
|
mov esi,eax
|
|
mov ecx,[edx]
|
|
movsx eax,byte [edx+4+ecx-1]
|
|
mov al,ah
|
|
mov ecx,ebx
|
|
sub ecx,[edx]
|
|
jbe value_ready
|
|
rep stosb
|
|
value_ready:
|
|
sub edi,ebx
|
|
value_fit:
|
|
test al,al
|
|
clc
|
|
retn
|
|
|
|
start_decimal_converter:
|
|
; preserves: ebx
|
|
mov edx,value_workspace
|
|
mov edi,[value_position]
|
|
mov [converter_position],edi
|
|
add edi,[edx+Workspace.memory_start]
|
|
mov ecx,2*sizeof.FloatData
|
|
call reserve_workspace
|
|
lea ecx,[edi+2*sizeof.FloatData]
|
|
sub ecx,[edx+Workspace.memory_start]
|
|
mov [value_position],ecx
|
|
mov esi,edi
|
|
xor eax,eax
|
|
assert sizeof.FloatData and 11b = 0
|
|
mov ecx,sizeof.FloatData shr 2
|
|
rep stosd
|
|
mov edx,edi
|
|
mov ecx,sizeof.FloatData shr 2
|
|
rep stosd
|
|
mov [edx+FloatData.exponent],7
|
|
retn
|
|
|
|
convert_decimal_digit:
|
|
; in:
|
|
; al = value of subsequent digit
|
|
; ecx = number of zero digits to insert before
|
|
; out:
|
|
; edi - FloatData holding the value corresponding to digits converted so far
|
|
; note: start_decimal_converter should be called before converting the first digit
|
|
mov esi,[value_workspace.memory_start]
|
|
add esi,[converter_position]
|
|
mov edi,esi
|
|
shl eax,24
|
|
mov [esi+sizeof.FloatData+FloatData.mantissa],eax
|
|
jecxz multiply_by_ten
|
|
inc ecx
|
|
call multiply_float_by_power_of_ten
|
|
jmp add_subsequent_digit
|
|
multiply_by_ten:
|
|
mov ecx,10
|
|
call multiply_float_by_unsigned_int
|
|
add_subsequent_digit:
|
|
mov esi,edi
|
|
lea ebx,[esi+sizeof.FloatData]
|
|
call add_floats
|
|
retn
|
|
|
|
finish_decimal_conversion:
|
|
; out:
|
|
; edi - FloatData holding the converted value
|
|
; preserves: ebx, ecx, esi, edi
|
|
; note: this function should not be called before all the digits of a value have been processed by convert_decimal_digit
|
|
mov eax,[converter_position]
|
|
mov edi,[value_workspace.memory_start]
|
|
add edi,eax
|
|
add eax,2*sizeof.FloatData
|
|
cmp eax,[value_position]
|
|
jne decimal_conversion_finished
|
|
sub eax,sizeof.FloatData
|
|
mov [value_position],eax
|
|
decimal_conversion_finished:
|
|
retn
|
|
|
|
keep_value:
|
|
; in:
|
|
; edx - numeric or string data returned by source parsing or expression evaluating functions
|
|
; preserves: ebx, esi, edi
|
|
; note:
|
|
; this function should be used in conjunction with get_kept_value to retain access to data
|
|
; while calling other parsing or expression evaluating functions
|
|
xor al,al
|
|
cmp edx,[value_workspace.memory_end]
|
|
jae keep_value_pointer
|
|
mov ecx,edx
|
|
sub ecx,[value_workspace.memory_start]
|
|
jc keep_value_pointer
|
|
mov edx,ecx
|
|
inc al
|
|
keep_value_pointer:
|
|
mov [kept_value],edx
|
|
mov [kept_value_in_workspace],al
|
|
retn
|
|
|
|
get_kept_value:
|
|
; out:
|
|
; edx - numeric or string data previously passed to keep_value
|
|
; preserves: eax, ebx, ecx, esi, edi
|
|
mov edx,[kept_value]
|
|
cmp [kept_value_in_workspace],0
|
|
je kept_value_ok
|
|
add edx,[value_workspace.memory_start]
|
|
kept_value_ok:
|
|
retn
|
|
|
|
get_constant_value:
|
|
; in:
|
|
; esi = pointer into preprocessed line or the last embedded line
|
|
; out:
|
|
; esi = pointer advanced past the processed part of line
|
|
; al = type of value, zero when expression gave no result
|
|
; when al = 22h:
|
|
; edx - 32-bit length followed by string data
|
|
; when al = 30h:
|
|
; edx - 32-bit length followed by numeric data
|
|
; when al = 2Eh:
|
|
; edx - FloatData
|
|
call get_expression_value
|
|
jc return_empty_type
|
|
get_calculated_constant_value:
|
|
; in:
|
|
; edi - list of ExpressionTerm elements as returned by get_expression_value
|
|
; out:
|
|
; same as get_constant_value
|
|
; preserves: esi, edi
|
|
call forbid_variable_terms
|
|
call get_term_value
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
assert EXPR_STRING = 22h
|
|
assert EXPR_NUMBER = 30h
|
|
assert EXPR_FLOAT = 2Eh
|
|
retn
|
|
return_empty_type:
|
|
xor al,al
|
|
retn
|
|
forbid_variable_terms:
|
|
mov eax,edi
|
|
detect_variable_terms:
|
|
add eax,sizeof.ExpressionTerm
|
|
cmp [eax+ExpressionTerm.attributes],0
|
|
je expression_terms_ok
|
|
cmp [eax+ExpressionTerm.metadata],0
|
|
je detect_variable_terms
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
expression_terms_ok:
|
|
retn
|
|
|
|
get_numeric_constant_value:
|
|
; in:
|
|
; esi = pointer into preprocessed line or the last embedded line
|
|
; out:
|
|
; esi = pointer advanced past the processed part of line
|
|
; edx - 32-bit length followed by numeric data, null when expression gave no result
|
|
; edi - ExpressionTerm, null when expression gave no result
|
|
call get_expression_value
|
|
jc empty_numeric_constant
|
|
call forbid_variable_terms
|
|
call get_numeric_term_value
|
|
retn
|
|
empty_numeric_constant:
|
|
xor edx,edx
|
|
xor edi,edi
|
|
retn
|
|
|
|
get_expression_value:
|
|
; in:
|
|
; esi = pointer into preprocessed line or the last embedded line
|
|
; out:
|
|
; cf set if expression gave no result
|
|
; esi = pointer advanced past the processed part of line
|
|
; when cf = 0:
|
|
; edi - list of ExpressionTerm elements, the closing element has attributes set to zero
|
|
mov edi,[expression_workspace.memory_start]
|
|
and [leave_opening_parentheses],0
|
|
call parse_expression
|
|
push esi
|
|
mov esi,[expression_workspace.memory_start]
|
|
mov edi,[calculation_workspace.memory_start]
|
|
call calculate_parsed_expression
|
|
call pop_terms
|
|
pop esi
|
|
retn
|
|
|
|
convert_terms_to_numeric_value:
|
|
; in:
|
|
; edi - list of ExpressionTerm elements as returned by get_expression_value
|
|
; out:
|
|
; esi - value in VALTYPE_NUMERIC format
|
|
; ecx = length of value
|
|
; note: the returned value is placed in assembly workspace
|
|
mov edx,assembly_workspace
|
|
convert_terms_to_numeric_value_in_workspace:
|
|
; in:
|
|
; edx - Workspace
|
|
; edi - list of ExpressionTerm elements as returned by get_expression_value
|
|
; out:
|
|
; esi - value in VALTYPE_NUMERIC format (same as [edx+Workspace.memory_start])
|
|
; ecx = length of value
|
|
; preserves: edx
|
|
mov ebx,[edx+Workspace.memory_start]
|
|
copy_numeric_term_values:
|
|
mov esi,edx
|
|
call get_numeric_term_value
|
|
xchg esi,edx
|
|
xchg ebx,edi
|
|
mov ecx,[esi]
|
|
add ecx,8
|
|
call reserve_workspace
|
|
lodsd
|
|
stosd
|
|
mov ecx,eax
|
|
rep movsb
|
|
next_numeric_term:
|
|
add ebx,sizeof.ExpressionTerm
|
|
cmp [ebx+ExpressionTerm.attributes],0
|
|
je numeric_term_values_copied
|
|
mov eax,[ebx+ExpressionTerm.metadata]
|
|
test eax,eax
|
|
jz next_numeric_term
|
|
stosd
|
|
xchg ebx,edi
|
|
jmp copy_numeric_term_values
|
|
numeric_term_values_copied:
|
|
xor eax,eax
|
|
stosd
|
|
mov esi,[edx+Workspace.memory_start]
|
|
mov ecx,edi
|
|
sub ecx,esi
|
|
retn
|
|
|
|
update_predicted_shift:
|
|
; in:
|
|
; edx - ValueDefinition that is going to be updated
|
|
; esi - new value in VALTYPE_NUMERIC fomat
|
|
; preserves: ebx, ecx, edx, esi
|
|
test edx,edx
|
|
jz zero_shift
|
|
cmp [edx+ValueDefinition.type],VALTYPE_NUMERIC
|
|
jne zero_shift
|
|
mov eax,[current_pass]
|
|
dec eax
|
|
cmp eax,[edx+ValueDefinition.pass]
|
|
jne zero_shift
|
|
call get_low_dword
|
|
mov [predicted_shift],eax
|
|
mov edi,[edx+ValueDefinition.value]
|
|
xchg esi,edi
|
|
call get_low_dword
|
|
sub [predicted_shift],eax
|
|
test byte [predicted_shift+3],11000000b
|
|
mov esi,edi
|
|
jnp zero_shift
|
|
retn
|
|
zero_shift:
|
|
mov [predicted_shift],0
|
|
retn
|
|
get_low_dword:
|
|
mov eax,[esi]
|
|
cmp eax,1
|
|
jb low_dword_ready
|
|
je dword_from_single_byte
|
|
cmp eax,3
|
|
jb dword_from_two_bytes
|
|
je dword_from_three_bytes
|
|
mov eax,[esi+4]
|
|
low_dword_ready:
|
|
retn
|
|
dword_from_single_byte:
|
|
movsx eax,byte [esi+4]
|
|
retn
|
|
dword_from_two_bytes:
|
|
movsx eax,word [esi+4]
|
|
retn
|
|
dword_from_three_bytes:
|
|
mov eax,[esi+4-1]
|
|
sar eax,8
|
|
retn
|
|
|
|
get_area_value:
|
|
; in:
|
|
; edi - command sequence created by parse_expression
|
|
; out:
|
|
; cf set if expression does not yield a valid and accessible VALTYPE_AREA value
|
|
; when cf = 0:
|
|
; ebx - SymbolTree_Leaf
|
|
; edx - ValueDefinition
|
|
; preserves: esi
|
|
mov al,[edi]
|
|
cmp al,EXPR_SYMBOL
|
|
je check_for_plain_symbol
|
|
cmp al,EXPR_SYMBOL_VALUE
|
|
jne no_plain_area_symbol
|
|
cmp dword [edi+3*4],0
|
|
jne no_plain_area_symbol
|
|
mov edx,[edi+2*4]
|
|
test edx,edx
|
|
jz no_plain_area_symbol
|
|
check_area_symbol:
|
|
cmp [edx+ValueDefinition.type],VALTYPE_AREA
|
|
jne no_plain_area_symbol
|
|
mov ebx,[edi+4]
|
|
call mark_symbol_as_used
|
|
clc
|
|
retn
|
|
check_for_plain_symbol:
|
|
cmp dword [edi+2*4],0
|
|
jne no_plain_area_symbol
|
|
mov ebx,[edi+4]
|
|
call get_available_value
|
|
jnc check_area_symbol
|
|
no_plain_area_symbol:
|
|
push esi
|
|
mov esi,edi
|
|
mov edi,[calculation_workspace.memory_start]
|
|
call calculate_parsed_expression
|
|
jc invalid_area_expression
|
|
call pop_terms
|
|
jc invalid_area_expression
|
|
mov eax,edi
|
|
xor esi,esi
|
|
extract_variable_term:
|
|
add eax,sizeof.ExpressionTerm
|
|
cmp [eax+ExpressionTerm.attributes],0
|
|
je variable_term_extracted
|
|
cmp [eax+ExpressionTerm.metadata],0
|
|
je extract_variable_term
|
|
test esi,esi
|
|
jnz invalid_area_expression
|
|
mov esi,eax
|
|
jmp extract_variable_term
|
|
variable_term_extracted:
|
|
test esi,esi
|
|
jz invalid_area_expression
|
|
call get_term_value
|
|
xor ecx,ecx
|
|
mov edi,ecx
|
|
call fit_value
|
|
jc invalid_area_expression
|
|
mov edi,esi
|
|
call get_term_value
|
|
mov ecx,1
|
|
mov edi,value
|
|
call fit_value
|
|
jc invalid_area_expression
|
|
cmp byte [value],1
|
|
jne invalid_area_expression
|
|
mov ebx,[esi+ExpressionTerm.metadata]
|
|
mov edx,[ebx+SymbolTree_Leaf.definition]
|
|
test edx,edx
|
|
jz invalid_area_expression
|
|
cmp [edx+ValueDefinition.type],VALTYPE_AREA
|
|
jne invalid_area_expression
|
|
pop esi
|
|
clc
|
|
retn
|
|
invalid_area_expression:
|
|
pop esi
|
|
invalid_area_symbol:
|
|
stc
|
|
retn
|
|
|
|
get_constituent_value:
|
|
; same as get_processed_value
|
|
; note: after any expression evaluation functions have been used, only this function should be used to retrieve constituents of line
|
|
xor al,al
|
|
xchg al,[current_constituent]
|
|
test al,al
|
|
jz get_processed_value
|
|
get_constituent_components:
|
|
mov ebx,[constituent_symbol]
|
|
mov edx,[constituent_value]
|
|
mov ecx,[constituent_whitespace]
|
|
clc
|
|
retn
|
|
|
|
peek_at_constituent_value:
|
|
; same as get_constituent_value, but returned values are also kept in constituent variables
|
|
; note:
|
|
; the retrieved value is still going to be available to expression evaluation functions or to the next call of get_constituent_value
|
|
; to consume the value it is enough to set [current_constituent] to zero
|
|
cmp [current_constituent],0
|
|
jne get_current_constituent
|
|
call get_processed_value
|
|
jc constituent_value_ok
|
|
mov [current_constituent],al
|
|
mov [constituent_symbol],ebx
|
|
mov [constituent_value],edx
|
|
mov [constituent_whitespace],ecx
|
|
constituent_value_ok:
|
|
retn
|
|
get_current_constituent:
|
|
mov al,[current_constituent]
|
|
jmp get_constituent_components
|
|
|
|
parse_expression:
|
|
; in:
|
|
; esi = pointer into preprocessed line or the last embedded line
|
|
; edi = pointer to a place in expression workspace where the parsed command sequence should be stored
|
|
; [leave_opening_parentheses] = non-zero when parentheses opened in the beginning of expression that did not get closed should be returned to caller instead of being registered in parsed expression
|
|
; out:
|
|
; esi = pointer advanced past the processed part of line
|
|
; edi = pointer advanced past the created sequence in expression workspace
|
|
; ecx = number of parentheses opened in the beginning of expression that did not get closed (zero when [leave_opening_parentheses] was zero)
|
|
mov [expression_end],edi
|
|
sub edi,[expression_workspace.memory_start]
|
|
mov [expression_position],edi
|
|
mov eax,[operator_stack_base]
|
|
mov [operator_stack],eax
|
|
mov [operator_stack_position],eax
|
|
mov [operator_argument_expected],1
|
|
get_expression_element:
|
|
mov edi,[expression_end]
|
|
mov edx,expression_workspace
|
|
mov ecx,[operator_stack_position]
|
|
sub ecx,[operator_stack_base]
|
|
add ecx,16
|
|
call reserve_workspace
|
|
mov [expression_end],edi
|
|
call peek_at_constituent_value
|
|
mov edi,[expression_end]
|
|
jc expression_line_end
|
|
cmp al,'('
|
|
je open_subexpression
|
|
cmp al,')'
|
|
je close_subexpression
|
|
cmp al,30h
|
|
je store_expression_number
|
|
cmp al,22h
|
|
je store_expression_string
|
|
cmp al,2Eh
|
|
je store_expression_float
|
|
cmp al,1Ah
|
|
je expression_symbol
|
|
movzx eax,al
|
|
shl eax,2
|
|
add eax,[operator_table]
|
|
mov edx,[eax]
|
|
test edx,edx
|
|
jz terminate_expression
|
|
xor ebx,ebx
|
|
mov ecx,edx
|
|
jmp identify_operator
|
|
expression_symbol:
|
|
test edx,edx
|
|
jz store_expression_symbol
|
|
mov ecx,edx
|
|
identify_operator:
|
|
cmp [ecx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND
|
|
jne inspect_expression_symbol
|
|
test [ecx+ValueDefinition.attribute],OPERATOR_UNARY
|
|
setnz al
|
|
xor al,[operator_argument_expected]
|
|
jz store_expression_operator
|
|
mov ecx,[ecx+ValueDefinition.previous]
|
|
test ecx,ecx
|
|
jnz identify_operator
|
|
inspect_expression_symbol:
|
|
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMPARATOR
|
|
je terminate_expression
|
|
store_expression_symbol:
|
|
cmp [operator_argument_expected],0
|
|
je terminate_expression
|
|
mov eax,EXPR_SYMBOL_VALUE
|
|
stosd
|
|
mov eax,ebx
|
|
stosd
|
|
mov eax,edx
|
|
stosd
|
|
expression_symbol_stored:
|
|
mov [expression_end],edi
|
|
and [operator_argument_expected],0
|
|
and [current_constituent],0
|
|
jmp get_expression_element
|
|
store_expression_number:
|
|
cmp [operator_argument_expected],0
|
|
je terminate_expression
|
|
mov eax,EXPR_NUMBER
|
|
value_pointer_in_expression:
|
|
cmp edx,[value_workspace.memory_end]
|
|
jae value_pointer_in_expression_ok
|
|
mov ebx,edx
|
|
sub ebx,[value_workspace.memory_start]
|
|
jc value_pointer_in_expression_ok
|
|
mov edx,ebx
|
|
or eax,EXPRF_VALUE_IN_WORKSPACE
|
|
value_pointer_in_expression_ok:
|
|
stosd
|
|
mov eax,edx
|
|
stosd
|
|
jmp expression_symbol_stored
|
|
store_expression_string:
|
|
cmp [operator_argument_expected],0
|
|
je terminate_expression
|
|
mov eax,EXPR_STRING
|
|
jmp value_pointer_in_expression
|
|
store_expression_float:
|
|
cmp [operator_argument_expected],0
|
|
je terminate_expression
|
|
mov eax,EXPR_FLOAT
|
|
jmp value_pointer_in_expression
|
|
store_expression_operator:
|
|
mov edx,[ecx+ValueDefinition.value]
|
|
mov cl,[ecx+ValueDefinition.attribute]
|
|
mov ch,cl
|
|
and cl,OPERATOR_PRECEDENCE_MASK
|
|
mov ebx,[operator_stack_position]
|
|
cmp [operator_argument_expected],0
|
|
jne push_operator
|
|
establish_operator_precedence:
|
|
cmp ebx,[operator_stack]
|
|
je push_operator
|
|
cmp cl,[ebx-8]
|
|
ja push_operator
|
|
jb store_pending_operator
|
|
test ch,OPERATOR_RIGHT_ASSOCIATIVE
|
|
jnz push_operator
|
|
store_pending_operator:
|
|
sub ebx,8
|
|
xor eax,eax
|
|
test byte [ebx+1],OPERATOR_UNARY
|
|
setnz al
|
|
shl eax,bsf EXPRF_OPERATOR_UNARY
|
|
mov al,EXPR_OPERATOR
|
|
stosd
|
|
mov eax,[ebx+4]
|
|
stosd
|
|
jmp establish_operator_precedence
|
|
push_operator:
|
|
call reserve_operator_stack
|
|
mov [ebx],ecx
|
|
mov [ebx+4],edx
|
|
add ebx,8
|
|
mov [operator_stack_position],ebx
|
|
mov [expression_end],edi
|
|
or [operator_argument_expected],1
|
|
and [current_constituent],0
|
|
jmp get_expression_element
|
|
open_subexpression:
|
|
cmp [operator_argument_expected],0
|
|
je terminate_expression
|
|
mov ebx,[operator_stack_position]
|
|
call reserve_operator_stack
|
|
mov eax,[operator_stack]
|
|
sub eax,[operator_stack_base]
|
|
mov [ebx],eax
|
|
add ebx,4
|
|
mov [operator_stack],ebx
|
|
mov [operator_stack_position],ebx
|
|
and [current_constituent],0
|
|
jmp get_expression_element
|
|
close_subexpression:
|
|
mov eax,[operator_stack]
|
|
cmp eax,[operator_stack_base]
|
|
je terminate_expression
|
|
cmp [operator_argument_expected],0
|
|
je subexpression_closed
|
|
mov eax,EXPR_MISSING_ARGUMENT
|
|
stosd
|
|
subexpression_closed:
|
|
call store_remaining_operators
|
|
mov [expression_end],edi
|
|
sub ebx,4
|
|
mov eax,[ebx]
|
|
add eax,[operator_stack_base]
|
|
mov [operator_stack],eax
|
|
mov [operator_stack_position],ebx
|
|
and [current_constituent],0
|
|
jmp get_expression_element
|
|
expression_line_end:
|
|
and [current_constituent],0
|
|
terminate_expression:
|
|
cmp [operator_argument_expected],0
|
|
je close_expression
|
|
mov eax,[operator_stack_position]
|
|
cmp eax,[operator_stack]
|
|
jne expression_terminated_prematurely
|
|
mov eax,edi
|
|
sub eax,[expression_workspace.memory_start]
|
|
cmp eax,[expression_position]
|
|
je close_expression
|
|
expression_terminated_prematurely:
|
|
mov eax,EXPR_MISSING_ARGUMENT
|
|
stosd
|
|
close_expression:
|
|
call store_remaining_operators
|
|
xor ecx,ecx
|
|
cmp ebx,[operator_stack_base]
|
|
jne forcibly_close_subexpressions
|
|
expression_parsed:
|
|
xor eax,eax
|
|
stosd
|
|
retn
|
|
forcibly_close_subexpressions:
|
|
sub ebx,4
|
|
mov eax,[ebx]
|
|
add eax,[operator_stack_base]
|
|
mov [operator_stack],eax
|
|
cmp [leave_opening_parentheses],0
|
|
je internal_parenthesis
|
|
cmp eax,ebx
|
|
je external_parenthesis
|
|
internal_parenthesis:
|
|
mov eax,EXPR_MISSING_PARENTHESIS
|
|
inc ecx
|
|
rep stosd
|
|
mov [operator_stack_position],ebx
|
|
call store_remaining_operators
|
|
cmp ebx,[operator_stack_base]
|
|
jne forcibly_close_subexpressions
|
|
jmp expression_parsed
|
|
external_parenthesis:
|
|
inc ecx
|
|
cmp ebx,[operator_stack_base]
|
|
jne forcibly_close_subexpressions
|
|
jmp expression_parsed
|
|
reserve_operator_stack:
|
|
mov eax,[operator_stack_end]
|
|
sub eax,8
|
|
cmp ebx,eax
|
|
jbe operator_stack_ready
|
|
push edx
|
|
mov eax,[operator_stack_base]
|
|
sub ebx,eax
|
|
sub [operator_stack],eax
|
|
mov ecx,[operator_stack_end]
|
|
sub ecx,eax
|
|
add ecx,8
|
|
call grow_stack
|
|
add ebx,eax
|
|
add [operator_stack],eax
|
|
mov [operator_stack_base],eax
|
|
add eax,ecx
|
|
mov [operator_stack_end],eax
|
|
pop edx
|
|
operator_stack_ready:
|
|
retn
|
|
store_remaining_operators:
|
|
mov ebx,[operator_stack_position]
|
|
store_operator:
|
|
cmp ebx,[operator_stack]
|
|
je remaining_operators_stored
|
|
sub ebx,8
|
|
xor eax,eax
|
|
test byte [ebx+1],OPERATOR_UNARY
|
|
setnz al
|
|
shl eax,bsf EXPRF_OPERATOR_UNARY
|
|
mov al,EXPR_OPERATOR
|
|
stosd
|
|
mov eax,[ebx+4]
|
|
stosd
|
|
jmp store_operator
|
|
remaining_operators_stored:
|
|
retn
|
|
|
|
calculate_parsed_expression:
|
|
; in:
|
|
; esi - command sequence created by parse_expression
|
|
; edi - top of the stack in the calculation workspace
|
|
; out:
|
|
; cf set if expression had structural errors
|
|
; esi = pointer moved past the processed sequence
|
|
; edi - top of the updated stack
|
|
; when cf = 0:
|
|
; eax = non-zero if result is considered not yet known for resolving purposes
|
|
mov [expression_end],esi
|
|
mov eax,edi
|
|
sub eax,[calculation_workspace.memory_start]
|
|
mov [calculation_position],eax
|
|
cmp dword [esi],0
|
|
je invalid_expression
|
|
calculation_loop:
|
|
mov esi,[expression_end]
|
|
lodsd
|
|
cmp al,EXPR_OPERATOR
|
|
je execute_operator
|
|
cmp al,EXPR_NUMBER
|
|
je push_literal
|
|
cmp al,EXPR_STRING
|
|
je push_literal
|
|
cmp al,EXPR_FLOAT
|
|
je push_literal
|
|
cmp al,EXPR_SYMBOL_VALUE
|
|
je push_symbol_value
|
|
cmp al,EXPR_SYMBOL
|
|
je push_symbol_current_value
|
|
cmp al,EXPR_POLYNOMIAL
|
|
je push_polynomial_literal
|
|
test eax,eax
|
|
jnz structural_error
|
|
; clc
|
|
retn
|
|
execute_operator:
|
|
lodsd
|
|
mov [expression_end],esi
|
|
jmp eax
|
|
push_literal:
|
|
mov ebx,eax
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
lodsd
|
|
test ebx,EXPRF_CALM_LITERAL
|
|
jnz calm_literal_value
|
|
test ebx,EXPRF_VALUE_IN_WORKSPACE
|
|
jnz valid_literal_value
|
|
test eax,eax
|
|
jnz valid_literal_value
|
|
jmp invalid_number_in_expression
|
|
calm_literal_value:
|
|
add eax,[calm_literals]
|
|
valid_literal_value:
|
|
mov [edi+ExpressionTerm.attributes],ebx
|
|
mov [edi+ExpressionTerm.value],eax
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
mov [expression_end],esi
|
|
jmp calculation_loop
|
|
push_polynomial_literal:
|
|
; occurring only in reduced CALM expressions
|
|
mov ebx,eax
|
|
lodsd
|
|
mov [expression_end],esi
|
|
test ebx,EXPRF_CALM_LITERAL
|
|
jz polynomial_value_ready
|
|
add eax,[calm_literals]
|
|
polynomial_value_ready:
|
|
xor esi,esi
|
|
mov ebx,eax
|
|
jmp push_polynomial
|
|
push_symbol_current_value:
|
|
; occurring only in CALM expressions, entire expression workspace should be free to use
|
|
lodsd
|
|
test eax,eax
|
|
jz invalid_identifier_in_expression
|
|
mov ebx,eax
|
|
mov [expression_end],esi
|
|
call use_available_value
|
|
jc undefined_symbol_in_expression
|
|
mov al,[edx+ValueDefinition.type]
|
|
cmp al,VALTYPE_SYMBOLIC
|
|
jne identify_value_to_push
|
|
push esi edi
|
|
call clear_line_embeddings
|
|
xor esi,esi
|
|
xor ecx,ecx
|
|
call embed_symbolic_value
|
|
mov edi,[expression_workspace.memory_start]
|
|
and [leave_opening_parentheses],0
|
|
call parse_expression
|
|
pop edi
|
|
call get_constituent_value
|
|
jnc invalid_subexpression
|
|
mov esi,[expression_workspace.memory_start]
|
|
push [calculation_position]
|
|
call calculate_parsed_expression
|
|
pop [calculation_position]
|
|
jc invalid_subexpression
|
|
pop [expression_end]
|
|
test eax,eax
|
|
jnz unknown_result
|
|
jmp calculation_loop
|
|
invalid_subexpression:
|
|
pop [expression_end]
|
|
mov edx,_invalid_expression
|
|
call register_error
|
|
jmp unknown_result
|
|
push_symbol_value:
|
|
lodsd
|
|
test eax,eax
|
|
jz invalid_identifier_in_expression
|
|
mov ebx,eax
|
|
lodsd
|
|
mov edx,eax
|
|
call mark_symbol_as_used
|
|
mov [expression_end],esi
|
|
test edx,edx
|
|
jz undefined_symbol_in_expression
|
|
mov al,[edx+ValueDefinition.type]
|
|
identify_value_to_push:
|
|
cmp al,VALTYPE_NUMERIC
|
|
je push_numeric_symbol
|
|
cmp al,VALTYPE_ELEMENT
|
|
je push_element
|
|
cmp al,VALTYPE_AREA
|
|
je push_area
|
|
cmp al,VALTYPE_STRING
|
|
je push_string
|
|
cmp al,VALTYPE_FLOAT
|
|
je push_float
|
|
cmp al,VALTYPE_PLAIN
|
|
je push_plain_symbol
|
|
cmp al,VALTYPE_NATIVE_FUNCTION
|
|
jne invalid_symbol_in_expression
|
|
jmp [edx+ValueDefinition.value]
|
|
push_numeric_symbol:
|
|
xor esi,esi
|
|
test [edx+ValueDefinition.flags],VAL_SHIFTABLE
|
|
jz predicted_shift_ok
|
|
mov eax,[edx+ValueDefinition.pass]
|
|
cmp eax,[current_pass]
|
|
je predicted_shift_ok
|
|
mov esi,[predicted_shift]
|
|
predicted_shift_ok:
|
|
mov ebx,[edx+ValueDefinition.value]
|
|
mov eax,ebx
|
|
add eax,[edx+ValueDefinition.value_length]
|
|
push_polynomial:
|
|
push eax edi
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
test esi,esi
|
|
jz push_numeric_terms
|
|
or [next_pass_needed],1
|
|
mov ecx,temporary_value
|
|
mov dword [ecx],4
|
|
mov dword [ecx+4],esi
|
|
lea esi,[edi+sizeof.ExpressionTerm]
|
|
mov [esi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [esi+ExpressionTerm.value],ecx
|
|
push ebx
|
|
call add_term_values
|
|
pop ebx
|
|
push_numeric_terms:
|
|
add edi,sizeof.ExpressionTerm
|
|
mov edx,calculation_workspace
|
|
mov ecx,sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov eax,[ebx]
|
|
lea ebx,[ebx+4+eax]
|
|
mov eax,[ebx]
|
|
test eax,eax
|
|
jz numeric_terms_pushed
|
|
mov eax,[ebx]
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
add ebx,4
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
jmp push_numeric_terms
|
|
numeric_terms_pushed:
|
|
pop edx ecx
|
|
sub ecx,8
|
|
cmp ebx,ecx
|
|
jbe symbol_metadata_ok
|
|
xor ebx,ebx
|
|
symbol_metadata_ok:
|
|
mov [edx+ExpressionTerm.metadata],ebx
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
push_plain_symbol:
|
|
mov ebx,[edx+ValueDefinition.value]
|
|
push_plain_value:
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov esi,edi
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,4+4
|
|
call reserve_workspace
|
|
xor eax,eax
|
|
test ebx,ebx
|
|
jz number_length_ok
|
|
bsr eax,ebx
|
|
inc al
|
|
shr al,3
|
|
inc al
|
|
number_length_ok:
|
|
stosd
|
|
mov [edi],ebx
|
|
add eax,edi
|
|
sub eax,[value_workspace.memory_start]
|
|
xchg eax,[value_position]
|
|
mov edi,esi
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
mov [edi+ExpressionTerm.value],eax
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
push_string:
|
|
mov al,EXPR_STRING
|
|
push_value:
|
|
mov [term_type],al
|
|
mov ebx,[edx+ValueDefinition.value]
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
mov al,[term_type]
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
push_float:
|
|
mov al,EXPR_FLOAT
|
|
jmp push_value
|
|
push_area:
|
|
mov esi,edx
|
|
jmp push_variable_term
|
|
push_element:
|
|
xor esi,esi
|
|
push_variable_term:
|
|
mov edx,calculation_workspace
|
|
mov ecx,3*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov eax,EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.metadata],esi
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.value],singular_value
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.metadata],ebx
|
|
and [edi+2*sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
add edi,3*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
base_address_value:
|
|
mov edx,[current_area]
|
|
area_address_value:
|
|
mov ebx,[edx+ValueDefinition.value]
|
|
add ebx,sizeof.AreaHeader
|
|
push_numeric_value:
|
|
mov edx,calculation_workspace
|
|
mov ecx,sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
and [edi+ExpressionTerm.metadata],0
|
|
jmp push_variable_terms
|
|
truncated_address_value:
|
|
xor esi,esi
|
|
jmp push_current_address
|
|
current_address_value:
|
|
or esi,-1
|
|
push_current_address:
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov eax,[current_area]
|
|
mov ebx,[eax+ValueDefinition.value]
|
|
mov ecx,[eax+ValueDefinition.value_length]
|
|
sub ecx,[ebx+AreaHeader.base_address_length]
|
|
sub ecx,sizeof.AreaHeader
|
|
and esi,[ebx+AreaHeader.uninitialized_length]
|
|
add ecx,esi
|
|
add ebx,sizeof.AreaHeader
|
|
mov esi,temporary_value
|
|
mov dword [esi],4
|
|
mov [esi+4],ecx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],esi
|
|
and [edi+ExpressionTerm.metadata],0
|
|
lea esi,[edi+sizeof.ExpressionTerm]
|
|
mov [esi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [esi+ExpressionTerm.value],ebx
|
|
call add_term_values
|
|
mov ebx,[esi+ExpressionTerm.value]
|
|
push_variable_terms:
|
|
mov eax,[ebx]
|
|
lea ebx,[ebx+4+eax]
|
|
convert_variable_term:
|
|
add edi,sizeof.ExpressionTerm
|
|
mov edx,calculation_workspace
|
|
mov ecx,sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov eax,[ebx]
|
|
test eax,eax
|
|
jz variable_terms_converted
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
add ebx,4
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
mov eax,[ebx]
|
|
lea ebx,[ebx+4+eax]
|
|
jmp convert_variable_term
|
|
variable_terms_converted:
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
truncated_position_value:
|
|
call prepare_to_push_computed_value
|
|
call get_output_length
|
|
jmp push_output_position
|
|
prepare_to_push_computed_value:
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
mov esi,edi
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,4+8
|
|
call reserve_workspace
|
|
retn
|
|
current_position_value:
|
|
call prepare_to_push_computed_value
|
|
call get_output_position
|
|
push_output_position:
|
|
mov edi,[value_workspace.memory_start]
|
|
add edi,[value_position]
|
|
push_computed_value:
|
|
mov ecx,eax
|
|
or ecx,edx
|
|
jz computed_value_length_ok
|
|
bsr ecx,edx
|
|
jnz long_computed_value
|
|
bsr ecx,eax
|
|
inc cl
|
|
shr cl,3
|
|
inc cl
|
|
jmp computed_value_length_ok
|
|
long_computed_value:
|
|
inc cl
|
|
shr cl,3
|
|
add cl,1+4
|
|
computed_value_length_ok:
|
|
mov [edi],ecx
|
|
add edi,4
|
|
stosd
|
|
mov eax,edx
|
|
stosd
|
|
add ecx,edi
|
|
sub ecx,[value_workspace.memory_start]
|
|
xchg ecx,[value_position]
|
|
mov edi,esi
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
mov [edi+ExpressionTerm.value],ecx
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
current_time_value:
|
|
call prepare_to_push_computed_value
|
|
call get_timestamp
|
|
jmp push_computed_value
|
|
current_line_number_value:
|
|
call prepare_to_push_computed_value
|
|
call get_file_source_entry
|
|
mov eax,[ebx+SourceEntry.line_number]
|
|
xor edx,edx
|
|
jmp push_computed_value
|
|
current_file_name_value:
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
push edi
|
|
call get_file_source_entry
|
|
jmp push_file_name_value
|
|
main_file_name_value:
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
push edi
|
|
mov ebx,[source_context]
|
|
lea ebx,[ebx+sizeof.SourceContext]
|
|
push_file_name_value:
|
|
mov esi,[ebx+SourceEntry.name]
|
|
xor ecx,ecx
|
|
cmp [ebx+SourceEntry.type],SOURCE_FILE
|
|
jne file_name_length_ok
|
|
mov ecx,[ebx+SourceEntry.name_length]
|
|
test ecx,ecx
|
|
jnz file_name_length_ok
|
|
mov edi,esi
|
|
xor al,al
|
|
dec ecx
|
|
repne scasb
|
|
add ecx,2
|
|
neg ecx
|
|
file_name_length_ok:
|
|
mov ebx,ecx
|
|
add ecx,4
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
call reserve_workspace
|
|
mov eax,ebx
|
|
stosd
|
|
mov ecx,ebx
|
|
rep movsb
|
|
mov eax,edi
|
|
sub eax,[value_workspace.memory_start]
|
|
xchg eax,[value_position]
|
|
pop edi
|
|
mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE
|
|
mov [edi+ExpressionTerm.value],eax
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
structural_error:
|
|
cmp eax,EXPR_MISSING_PARENTHESIS
|
|
je expression_missing_parenthesis
|
|
invalid_expression:
|
|
mov edx,_invalid_expression
|
|
call register_error
|
|
stc
|
|
retn
|
|
expression_missing_parenthesis:
|
|
mov edx,_missing_closing_parenthesis
|
|
call register_error
|
|
stc
|
|
retn
|
|
undefined_symbol_in_expression:
|
|
cmp [next_pass_needed],0
|
|
jne unknown_result
|
|
mov edx,_undefined_symbol
|
|
jmp error_causing_unknown_result
|
|
invalid_identifier_in_expression:
|
|
mov edx,_invalid_identifier
|
|
jmp error_causing_unknown_result
|
|
invalid_number_in_expression:
|
|
mov edx,_invalid_number
|
|
jmp error_causing_unknown_result
|
|
invalid_symbol_in_expression:
|
|
mov edx,_invalid_symbol_value
|
|
error_causing_unknown_result:
|
|
call register_error
|
|
unknown_result:
|
|
mov eax,edi
|
|
mov edi,[calculation_position]
|
|
add edi,[calculation_workspace.memory_start]
|
|
cmp edi,eax
|
|
jb unknown_result_terms_ready
|
|
mov edi,eax
|
|
mov edx,calculation_workspace
|
|
mov ecx,2*sizeof.ExpressionTerm
|
|
call reserve_workspace
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
unknown_result_terms_ready:
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
add edi,2*sizeof.ExpressionTerm
|
|
mov esi,[expression_end]
|
|
skip_expression:
|
|
lodsd
|
|
cmp al,EXPR_OPERATOR
|
|
je skip_dword
|
|
cmp al,EXPR_NUMBER
|
|
je skip_dword
|
|
cmp al,EXPR_STRING
|
|
je skip_dword
|
|
cmp al,EXPR_FLOAT
|
|
je skip_dword
|
|
cmp al,EXPR_SYMBOL
|
|
je skip_dword
|
|
cmp al,EXPR_SYMBOL_VALUE
|
|
je skip_two_dwords
|
|
cmp al,EXPR_POLYNOMIAL
|
|
je skip_dword
|
|
test eax,eax
|
|
jnz invalid_expression
|
|
inc eax
|
|
; clc
|
|
retn
|
|
skip_two_dwords:
|
|
add esi,4
|
|
skip_dword:
|
|
add esi,4
|
|
jmp skip_expression
|
|
|
|
pop_terms:
|
|
; in:
|
|
; edi = top of the stack
|
|
; out:
|
|
; edi = new top of the stack, at the same time a pointer to the first term of retrieved linear polynomial
|
|
; cf set when there were no more entries on the stack
|
|
; preserves: eax, ebx, ecx, edx, esi
|
|
cmp edi,[calculation_workspace.memory_start]
|
|
je nothing_to_pop
|
|
sub edi,sizeof.ExpressionTerm
|
|
find_first_term:
|
|
cmp edi,[calculation_workspace.memory_start]
|
|
je first_term_found
|
|
cmp [edi-sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
je first_term_found
|
|
sub edi,sizeof.ExpressionTerm
|
|
jmp find_first_term
|
|
first_term_found:
|
|
clc
|
|
retn
|
|
nothing_to_pop:
|
|
and [edi+ExpressionTerm.metadata],0
|
|
and [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
stc
|
|
retn
|
|
|
|
calculate_to_number:
|
|
call pop_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je single_term_result
|
|
make_terms_numeric:
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
test eax,eax
|
|
jz all_terms_numeric
|
|
call get_numeric_term_value
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp make_terms_numeric
|
|
all_terms_numeric:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
|
|
calculate_to_string:
|
|
call pop_terms
|
|
call get_string_term_value
|
|
jmp single_term_result
|
|
|
|
calculate_to_float:
|
|
call pop_terms
|
|
call get_float_term_value
|
|
jmp single_term_result
|
|
|
|
extract_integer_part:
|
|
call pop_terms
|
|
call truncate_term_value
|
|
jmp single_term_result
|
|
|
|
calculate_neg:
|
|
call pop_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je negate_float_term
|
|
call negate_term_value
|
|
add edi,sizeof.ExpressionTerm
|
|
negate_element_terms:
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je all_terms_negated
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je negate_next_term
|
|
call negate_term_value
|
|
negate_next_term:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp negate_element_terms
|
|
all_terms_negated:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
negate_float_term:
|
|
call prepare_altered_float_term
|
|
xor [ebx+FloatData.attributes],FLOAT_NEGATIVE
|
|
single_term_result:
|
|
add edi,sizeof.ExpressionTerm
|
|
mov eax,edi
|
|
call check_for_excess_terms
|
|
jnc single_term_result_ok
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
single_term_result_ok:
|
|
and [edi+ExpressionTerm.attributes],0
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
check_for_excess_terms:
|
|
cmp [eax+ExpressionTerm.attributes],0
|
|
je no_excess_terms
|
|
cmp [eax+ExpressionTerm.metadata],0
|
|
jne excess_terms
|
|
add eax,sizeof.ExpressionTerm
|
|
jne check_for_excess_terms
|
|
no_excess_terms:
|
|
clc
|
|
retn
|
|
excess_terms:
|
|
stc
|
|
retn
|
|
prepare_altered_float_term:
|
|
mov ebx,edi
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,sizeof.FloatData
|
|
call reserve_workspace
|
|
xchg edi,ebx
|
|
call get_term_value
|
|
xchg edi,ebx
|
|
mov esi,edx
|
|
assert sizeof.FloatData and 11b = 0
|
|
mov ecx,sizeof.FloatData shr 2
|
|
rep movsd
|
|
mov eax,edi
|
|
sub eax,[value_workspace.memory_start]
|
|
xchg eax,[value_position]
|
|
sub edi,sizeof.FloatData
|
|
xchg edi,ebx
|
|
mov [edi+ExpressionTerm.value],eax
|
|
or [edi+ExpressionTerm.attributes],EXPRF_VALUE_IN_WORKSPACE
|
|
retn
|
|
|
|
calculate_add:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je add_float_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je add_float_terms
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
jne add_constant_terms
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
add_constant_terms:
|
|
call add_term_values
|
|
add esi,sizeof.ExpressionTerm
|
|
add_variable_terms:
|
|
cmp [esi+ExpressionTerm.attributes],0
|
|
je all_terms_added
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
test eax,eax
|
|
jz add_next_term
|
|
push edi
|
|
find_element_to_add_to:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je attach_new_element
|
|
cmp eax,[edi+ExpressionTerm.metadata]
|
|
jne find_element_to_add_to
|
|
push esi
|
|
call add_term_values
|
|
jnz variable_term_added
|
|
and [edi+ExpressionTerm.metadata],0
|
|
variable_term_added:
|
|
pop esi edi
|
|
add_next_term:
|
|
add esi,sizeof.ExpressionTerm
|
|
jmp add_variable_terms
|
|
attach_new_element:
|
|
assert sizeof.ExpressionTerm and 11b = 0
|
|
mov ecx,sizeof.ExpressionTerm shr 2
|
|
rep movsd
|
|
and [edi+ExpressionTerm.attributes],0
|
|
pop edi
|
|
jmp add_variable_terms
|
|
all_terms_added:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
jne all_terms_added
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
add_float_terms:
|
|
mov eax,add_floats
|
|
operation_on_float_terms:
|
|
push esi edi eax
|
|
mov ebx,edi
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,sizeof.FloatData
|
|
call reserve_workspace
|
|
lea ecx,[edi+sizeof.FloatData]
|
|
sub ecx,[edx+Workspace.memory_start]
|
|
mov [value_position],ecx
|
|
xchg edi,ebx
|
|
call get_float_term_value
|
|
xchg edi,esi
|
|
call get_float_term_value
|
|
mov edi,esi
|
|
mov esi,edx
|
|
call get_term_value
|
|
mov edi,ebx
|
|
mov ebx,edx
|
|
pop eax
|
|
call eax
|
|
mov ebx,edi
|
|
sub ebx,[value_workspace.memory_start]
|
|
test [edi+FloatData.attributes],FLOAT_INFINITE or FLOAT_INDETERMINATE or FLOAT_UNDERFLOW
|
|
jz operation_on_float_terms_ok
|
|
mov edx,_indeterminate_result
|
|
call register_error
|
|
xor eax,eax
|
|
mov [edi+FloatData.attributes],eax
|
|
add edi,FloatData.mantissa
|
|
mov ecx,MANTISSA_SEGMENTS
|
|
rep stosd
|
|
operation_on_float_terms_ok:
|
|
pop edi esi
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_FLOAT + EXPRF_VALUE_IN_WORKSPACE
|
|
and [edi+ExpressionTerm.metadata],0
|
|
finish_calculation_on_single_terms:
|
|
add edi,sizeof.ExpressionTerm
|
|
mov eax,edi
|
|
call check_for_excess_terms
|
|
jc single_terms_violation
|
|
lea eax,[esi+sizeof.ExpressionTerm]
|
|
call check_for_excess_terms
|
|
jnc single_terms_ok
|
|
single_terms_violation:
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
single_terms_ok:
|
|
and [edi+ExpressionTerm.attributes],0
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
|
|
calculate_sub:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je subtract_float_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je subtract_float_terms
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
jne subtract_constant_terms
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
subtract_constant_terms:
|
|
call subtract_term_values
|
|
add esi,sizeof.ExpressionTerm
|
|
subtract_variable_terms:
|
|
cmp [esi+ExpressionTerm.attributes],0
|
|
je all_terms_subtracted
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
test eax,eax
|
|
jz subtract_next_term
|
|
push edi
|
|
find_element_to_subtract_from:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je attach_negated_element
|
|
cmp eax,[edi+ExpressionTerm.metadata]
|
|
jne find_element_to_subtract_from
|
|
push esi
|
|
call subtract_term_values
|
|
jnz variable_term_subtracted
|
|
and [edi+ExpressionTerm.metadata],0
|
|
variable_term_subtracted:
|
|
pop esi edi
|
|
subtract_next_term:
|
|
add esi,sizeof.ExpressionTerm
|
|
jmp subtract_variable_terms
|
|
attach_negated_element:
|
|
assert sizeof.ExpressionTerm and 11b = 0
|
|
mov ecx,sizeof.ExpressionTerm shr 2
|
|
rep movsd
|
|
sub edi,sizeof.ExpressionTerm
|
|
call negate_term_value
|
|
add edi,sizeof.ExpressionTerm
|
|
and [edi+ExpressionTerm.attributes],0
|
|
pop edi
|
|
jmp subtract_variable_terms
|
|
all_terms_subtracted:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
jne all_terms_subtracted
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
subtract_float_terms:
|
|
mov eax,subtract_floats
|
|
jmp operation_on_float_terms
|
|
|
|
calculate_mul:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je multiply_float_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je multiply_float_terms
|
|
cmp [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
jne multiply_by_destination
|
|
multiply_terms:
|
|
call multiply_term_values
|
|
jnz multiply_next_term
|
|
and [edi+ExpressionTerm.metadata],0
|
|
multiply_next_term:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je terms_multiplied
|
|
jmp multiply_terms
|
|
terms_multiplied:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
multiply_by_destination:
|
|
and [esi+ExpressionTerm.metadata],0
|
|
cmp [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
je duplicate_destination_constant_term
|
|
mov edx,_nonlinear_polynomial
|
|
call register_error
|
|
duplicate_destination_constant_term:
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.value],edx
|
|
multiply_source_terms:
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
call multiply_term_values
|
|
jnz multiply_next_source_term
|
|
and [edi+ExpressionTerm.metadata],0
|
|
multiply_next_source_term:
|
|
add esi,sizeof.ExpressionTerm
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [esi+ExpressionTerm.attributes],0
|
|
je source_terms_multiplied
|
|
cmp [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
je multiply_source_terms
|
|
jmp duplicate_destination_constant_term
|
|
source_terms_multiplied:
|
|
and [edi+ExpressionTerm.attributes],0
|
|
jmp terms_multiplied
|
|
multiply_float_terms:
|
|
mov eax,multiply_floats
|
|
jmp operation_on_float_terms
|
|
|
|
calculate_div:
|
|
call pop_terms
|
|
mov eax,edi
|
|
call check_for_excess_terms
|
|
jnc divisor_ok
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
divisor_ok:
|
|
mov esi,edi
|
|
call pop_terms
|
|
cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je divide_float_terms
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je divide_float_terms
|
|
and [edi+ExpressionTerm.metadata],0
|
|
mov eax,[esi+ExpressionTerm.attributes]
|
|
mov edx,[esi+ExpressionTerm.value]
|
|
mov [esi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
mov [esi+sizeof.ExpressionTerm+ExpressionTerm.value],edx
|
|
call divide_term_values
|
|
divide_variable_term:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je division_done
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je divide_variable_term
|
|
mov eax,[esi+sizeof.ExpressionTerm+ExpressionTerm.attributes]
|
|
mov edx,[esi+sizeof.ExpressionTerm+ExpressionTerm.value]
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],edx
|
|
call divide_term_values
|
|
jz divide_variable_term
|
|
mov edx,_subdivided_variable_term
|
|
call register_error
|
|
jmp divide_variable_term
|
|
division_done:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
divide_float_terms:
|
|
mov eax,divide_floats
|
|
jmp operation_on_float_terms
|
|
|
|
calculate_mod:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
call divide_term_values
|
|
and [esi+ExpressionTerm.metadata],0
|
|
assert sizeof.ExpressionTerm and 11b = 0
|
|
mov ecx,sizeof.ExpressionTerm shr 2
|
|
rep movsd
|
|
mov eax,edi
|
|
call check_for_excess_terms
|
|
jc mod_variable_term
|
|
mov eax,esi
|
|
call check_for_excess_terms
|
|
jnc mod_terms_ok
|
|
mod_variable_term:
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
mod_terms_ok:
|
|
and [edi+ExpressionTerm.attributes],0
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
|
|
calculate_not:
|
|
call pop_terms
|
|
call invert_term_value_bits
|
|
jmp single_term_result
|
|
|
|
calculate_xor:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
call bitwise_add_term_values
|
|
finish_bitwise_calculation:
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
jne finish_calculation_on_single_terms
|
|
mov eax,[esi+ExpressionTerm.metadata]
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
jmp finish_calculation_on_single_terms
|
|
|
|
calculate_and:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
call bitwise_multiply_term_values
|
|
jmp finish_bitwise_calculation
|
|
|
|
calculate_or:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
call bitwise_inclusive_or_of_term_values
|
|
jmp finish_bitwise_calculation
|
|
|
|
calculate_shl:
|
|
call pop_terms
|
|
call get_numeric_term_value
|
|
mov ecx,5
|
|
call fit_value
|
|
js negative_shift_left
|
|
jc huge_shift_left
|
|
shift_left:
|
|
mov esi,edi
|
|
check_shift_left_argument:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je shift_left_argument_ok
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je check_shift_left_argument
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
shift_left_argument_ok:
|
|
mov edi,esi
|
|
call pop_terms
|
|
and [edi+ExpressionTerm.metadata],0
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je shift_floating_point_left
|
|
shift_term_left:
|
|
mov eax,[esi]
|
|
mov dl,[esi+4]
|
|
call shift_term_value_left
|
|
shift_variable_term_left:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je shift_done
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je shift_variable_term_left
|
|
jmp shift_term_left
|
|
shift_done:
|
|
add edi,sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
negative_shift_left:
|
|
jc huge_shift_right
|
|
not byte [edi+4]
|
|
neg dword [edi]
|
|
jc shift_right
|
|
inc byte [edi+4]
|
|
jnz shift_right
|
|
huge_shift_right:
|
|
or eax,-1
|
|
mov [edi],eax
|
|
mov [edi+4],al
|
|
jmp shift_right
|
|
shift_floating_point_left:
|
|
push esi
|
|
call prepare_altered_float_term
|
|
pop esi
|
|
xchg esi,ebx
|
|
call get_float_unnormalization
|
|
jc single_term_result
|
|
mov eax,[esi+FloatData.exponent]
|
|
cdq
|
|
add eax,[ebx]
|
|
movzx ebx,byte [ebx+4]
|
|
adc ebx,edx
|
|
mov [esi+FloatData.exponent],eax
|
|
cdq
|
|
cmp ebx,edx
|
|
jne floating_point_over_boundary
|
|
test ecx,ecx
|
|
jz single_term_result
|
|
push edi
|
|
mov edi,esi
|
|
and [mantissa_tail],0
|
|
call normalize_float
|
|
pop edi
|
|
jmp single_term_result
|
|
floating_point_over_boundary:
|
|
jecxz floating_point_out_of_range
|
|
test ebx,ebx
|
|
jnz floating_point_out_of_range
|
|
mov ecx,7FFFFFFFh
|
|
sub eax,ecx
|
|
mov [esi+FloatData.exponent],ecx
|
|
push eax edi
|
|
mov edi,esi
|
|
and [mantissa_tail],0
|
|
call normalize_float
|
|
pop edi ecx
|
|
mov eax,[esi+FloatData.exponent]
|
|
cdq
|
|
add eax,ecx
|
|
js floating_point_out_of_range
|
|
adc edx,0
|
|
jnz floating_point_out_of_range
|
|
mov [esi+FloatData.exponent],eax
|
|
jmp single_term_result
|
|
floating_point_out_of_range:
|
|
mov edx,_value_out_of_range
|
|
call register_error
|
|
jmp single_term_result
|
|
|
|
calculate_shr:
|
|
call pop_terms
|
|
call get_numeric_term_value
|
|
mov ecx,5
|
|
call fit_value
|
|
js negative_shift_right
|
|
jc huge_shift_right
|
|
shift_right:
|
|
mov esi,edi
|
|
check_shift_right_argument:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je shift_right_argument_ok
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je check_shift_right_argument
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
shift_right_argument_ok:
|
|
mov edi,esi
|
|
call pop_terms
|
|
and [edi+ExpressionTerm.metadata],0
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je shift_floating_point_right
|
|
shift_term_right:
|
|
mov eax,[esi]
|
|
mov dl,[esi+4]
|
|
call shift_term_value_right
|
|
shift_variable_term_right:
|
|
add edi,sizeof.ExpressionTerm
|
|
cmp [edi+ExpressionTerm.attributes],0
|
|
je shift_done
|
|
cmp [edi+ExpressionTerm.metadata],0
|
|
je shift_variable_term_right
|
|
call get_term_value
|
|
mov ecx,[esi]
|
|
mov bl,cl
|
|
mov al,[esi+4]
|
|
shrd ecx,eax,3
|
|
shr al,3
|
|
jnz not_exact_shift
|
|
cmp ecx,[edx]
|
|
jae not_exact_shift
|
|
xchg edi,edx
|
|
add edi,4
|
|
xor al,al
|
|
repe scasb
|
|
xchg edi,edx
|
|
jne not_exact_shift
|
|
mov cl,bl
|
|
and cl,8-1
|
|
jz shift_term_right
|
|
mov al,1
|
|
shl al,cl
|
|
dec al
|
|
test [edx],al
|
|
jz shift_term_right
|
|
not_exact_shift:
|
|
mov edx,_subdivided_variable_term
|
|
call register_error
|
|
jmp shift_variable_term_right
|
|
negative_shift_right:
|
|
jc huge_shift_left
|
|
not byte [edi+4]
|
|
neg dword [edi]
|
|
jc shift_left
|
|
inc byte [edi+4]
|
|
jnz shift_left
|
|
huge_shift_left:
|
|
or eax,-1
|
|
mov [edi],eax
|
|
mov [edi+4],al
|
|
jmp shift_left
|
|
shift_floating_point_right:
|
|
push esi
|
|
call prepare_altered_float_term
|
|
pop esi
|
|
xchg esi,ebx
|
|
call get_float_unnormalization
|
|
jc single_term_result
|
|
mov eax,[esi+FloatData.exponent]
|
|
cdq
|
|
sub eax,[ebx]
|
|
movzx ecx,byte [ebx+4]
|
|
sbb edx,ecx
|
|
mov ecx,edx
|
|
mov [esi+FloatData.exponent],eax
|
|
cdq
|
|
cmp ecx,edx
|
|
je single_term_result
|
|
cmp ecx,-1
|
|
jne floating_point_out_of_range
|
|
mov [esi+FloatData.exponent],-80000000h
|
|
mov ecx,eax
|
|
neg ecx
|
|
push edi
|
|
mov edi,esi
|
|
and [mantissa_tail],0
|
|
call unnormalize_float
|
|
pop edi
|
|
mov [esi+FloatData.exponent],-80000000h
|
|
call get_float_unnormalization
|
|
jc floating_point_out_of_range
|
|
jmp single_term_result
|
|
|
|
calculate_bsf:
|
|
call pop_terms
|
|
mov esi,edi
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,10
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
call find_first_set_bit_in_term_value
|
|
jz bit_scan_result_undefined
|
|
movzx edx,dl
|
|
bit_scan_result_ready:
|
|
mov ebx,edi
|
|
and dword [edi],0
|
|
add edi,4
|
|
stosd
|
|
mov ax,dx
|
|
stosw
|
|
mov ecx,6
|
|
optimize_result_value:
|
|
cmp [edi-1],dh
|
|
jne result_value_ready
|
|
movsx eax,byte [edi-2]
|
|
cmp ah,dh
|
|
jne result_value_ready
|
|
dec edi
|
|
loop optimize_result_value
|
|
result_value_ready:
|
|
mov [ebx],ecx
|
|
sub edi,[value_workspace.memory_start]
|
|
mov [value_position],edi
|
|
sub ebx,[value_workspace.memory_start]
|
|
mov edi,esi
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
and [edi+ExpressionTerm.metadata],0
|
|
jmp single_term_result
|
|
|
|
calculate_bsr:
|
|
call pop_terms
|
|
mov esi,edi
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,10
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
cmp byte [esi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
je extract_float_exponent
|
|
call find_last_set_bit_in_term_value
|
|
jc bit_scan_result_undefined
|
|
movzx edx,dl
|
|
jmp bit_scan_result_ready
|
|
bit_scan_result_undefined:
|
|
mov edi,esi
|
|
mov edx,_indeterminate_result
|
|
call register_error
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
and [edi+ExpressionTerm.metadata],0
|
|
jmp single_term_result
|
|
extract_float_exponent:
|
|
mov edi,esi
|
|
mov [destination_term],edi
|
|
call get_term_value
|
|
mov esi,edx
|
|
call get_float_unnormalization
|
|
jc exponent_indeterminate
|
|
mov eax,[esi+FloatData.exponent]
|
|
cdq
|
|
sub eax,ecx
|
|
sbb edx,0
|
|
exponent_extracted:
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov esi,[destination_term]
|
|
jmp bit_scan_result_ready
|
|
exponent_indeterminate:
|
|
mov edx,_indeterminate_result
|
|
call register_error
|
|
xor eax,eax
|
|
xor edx,edx
|
|
jmp exponent_extracted
|
|
|
|
calculate_bswap:
|
|
call pop_terms
|
|
call get_numeric_term_value
|
|
mov ecx,4
|
|
call fit_value
|
|
js bswap_argument_out_of_range
|
|
jc bswap_argument_out_of_range
|
|
mov esi,edi
|
|
mov eax,edi
|
|
call check_for_excess_terms
|
|
jnc bswap_argument_ok
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
bswap_argument_ok:
|
|
call pop_terms
|
|
and [edi+ExpressionTerm.metadata],0
|
|
mov ebx,[esi]
|
|
call reverse_term_value_bytes
|
|
jmp single_term_result
|
|
bswap_argument_out_of_range:
|
|
mov edx,_value_out_of_range
|
|
call register_error
|
|
call pop_terms
|
|
jmp single_term_result
|
|
|
|
calculate_bappend:
|
|
call pop_terms
|
|
mov [source_term],edi
|
|
call pop_terms
|
|
mov [destination_term],edi
|
|
call get_string_term_value
|
|
mov ecx,[edx]
|
|
mov edi,[source_term]
|
|
call get_string_term_value
|
|
add ecx,[edx]
|
|
add ecx,4
|
|
mov edi,[value_position]
|
|
mov edx,value_workspace
|
|
add edi,[edx+Workspace.memory_start]
|
|
call reserve_workspace
|
|
push edi
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE
|
|
mov eax,[value_position]
|
|
mov [edi+ExpressionTerm.value],eax
|
|
pop edi
|
|
mov esi,edx
|
|
mov ecx,[esi]
|
|
movsd
|
|
rep movsb
|
|
push edi
|
|
mov edi,[source_term]
|
|
call get_term_value
|
|
pop edi
|
|
mov esi,edx
|
|
lodsd
|
|
mov ecx,eax
|
|
rep movsb
|
|
mov edx,[value_workspace.memory_start]
|
|
sub edi,edx
|
|
xchg [value_position],edi
|
|
add edi,edx
|
|
add [edi],eax
|
|
mov esi,[source_term]
|
|
mov edi,[destination_term]
|
|
jmp finish_calculation_on_single_terms
|
|
|
|
count_bytes:
|
|
call pop_terms
|
|
call get_string_term_value
|
|
mov esi,edi
|
|
add esi,sizeof.ExpressionTerm
|
|
mov eax,esi
|
|
call check_for_excess_terms
|
|
mov ebx,[edx]
|
|
jnc push_plain_value
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
jmp push_plain_value
|
|
|
|
count_elements:
|
|
call pop_terms
|
|
mov edx,[edi+ExpressionTerm.metadata]
|
|
xor ebx,ebx
|
|
mov edx,edi
|
|
count_variable_terms:
|
|
add edx,sizeof.ExpressionTerm
|
|
cmp [edx+ExpressionTerm.attributes],0
|
|
je push_plain_value
|
|
cmp [edx+ExpressionTerm.metadata],0
|
|
je count_variable_terms
|
|
inc ebx
|
|
jmp count_variable_terms
|
|
|
|
extract_element_reverse:
|
|
xor eax,eax
|
|
extract_element:
|
|
call get_indexed_term
|
|
jc replace_with_zero
|
|
jecxz replace_with_constant_unit
|
|
mov ebx,[ebx+ExpressionTerm.metadata]
|
|
jmp push_element
|
|
get_indexed_term:
|
|
call pop_terms
|
|
mov esi,edi
|
|
call pop_terms
|
|
mov ebx,edi
|
|
test eax,eax
|
|
jnz process_term_indexing
|
|
xchg ebx,esi
|
|
process_term_indexing:
|
|
mov edx,esi
|
|
check_term_index:
|
|
add edx,sizeof.ExpressionTerm
|
|
cmp [edx+ExpressionTerm.attributes],0
|
|
je term_index_ok
|
|
cmp [edx+ExpressionTerm.metadata],0
|
|
je check_term_index
|
|
mov edx,_misused_variable_term
|
|
call register_error
|
|
term_index_ok:
|
|
push ebx
|
|
xchg edi,esi
|
|
call get_numeric_term_value
|
|
mov ecx,4
|
|
call fit_value
|
|
xchg esi,edi
|
|
pop ebx
|
|
js no_such_term
|
|
jc no_such_term
|
|
xor ecx,ecx
|
|
find_indexed_term:
|
|
cmp ecx,[esi]
|
|
je term_found
|
|
find_next_term:
|
|
add ebx,sizeof.ExpressionTerm
|
|
cmp [ebx+ExpressionTerm.attributes],0
|
|
je no_such_term
|
|
cmp [ebx+ExpressionTerm.metadata],0
|
|
je find_next_term
|
|
inc ecx
|
|
jmp find_indexed_term
|
|
term_found:
|
|
clc
|
|
retn
|
|
no_such_term:
|
|
stc
|
|
retn
|
|
replace_with_constant_unit:
|
|
mov edx,singular_value
|
|
jmp replace_with_simple_number
|
|
replace_with_zero:
|
|
mov edx,zero_value
|
|
replace_with_simple_number:
|
|
mov eax,EXPR_NUMBER
|
|
replace_with_simple_constant:
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.metadata],eax
|
|
mov [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],eax
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
|
|
extract_scale_reverse:
|
|
xor eax,eax
|
|
extract_scale:
|
|
call get_indexed_term
|
|
jc replace_with_zero
|
|
mov eax,[ebx+ExpressionTerm.attributes]
|
|
mov edx,[ebx+ExpressionTerm.value]
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
and [edi+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
|
add edi,2*sizeof.ExpressionTerm
|
|
jmp calculation_loop
|
|
|
|
extract_metadata_reverse:
|
|
xor eax,eax
|
|
extract_metadata:
|
|
call get_indexed_term
|
|
jc replace_with_zero
|
|
extract_term_metadata:
|
|
mov ebx,[ebx+ExpressionTerm.metadata]
|
|
test ebx,ebx
|
|
jz replace_with_zero
|
|
test ecx,ecx
|
|
jz extract_label_metadata
|
|
mov edx,[ebx+SymbolTree_Leaf.definition]
|
|
test edx,edx
|
|
jz replace_with_zero
|
|
cmp [edx+ValueDefinition.type],VALTYPE_AREA
|
|
je area_address_value
|
|
cmp [edx+ValueDefinition.type],VALTYPE_ELEMENT
|
|
jne replace_with_zero
|
|
mov ecx,[edx+ValueDefinition.value_length]
|
|
jecxz replace_with_zero
|
|
jmp push_numeric_symbol
|
|
extract_size:
|
|
call pop_terms
|
|
mov ebx,[edi+ExpressionTerm.metadata]
|
|
test ebx,ebx
|
|
jz replace_with_zero
|
|
extract_label_metadata:
|
|
cmp dword [ebx],0
|
|
jne extract_area_size
|
|
add ebx,4
|
|
jmp push_numeric_value
|
|
extract_area_size:
|
|
call prepare_to_push_computed_value
|
|
xor edx,edx
|
|
mov eax,[ebx+ValueDefinition.value_length]
|
|
mov edi,[ebx+ValueDefinition.value]
|
|
sub eax,sizeof.AreaHeader
|
|
sub eax,[edi+AreaHeader.base_address_length]
|
|
add eax,[edi+AreaHeader.uninitialized_length]
|
|
adc edx,0
|
|
jmp push_output_position
|
|
extract_first_term_metadata:
|
|
call pop_terms
|
|
lea ebx,[edi+sizeof.ExpressionTerm]
|
|
mov ecx,1
|
|
jmp extract_term_metadata
|
|
|
|
get_term_value:
|
|
; in: edi - ExpressionTerm
|
|
; out: edx - 32-bit length followed by data
|
|
; preserves: eax, ebx, ecx, esi, edi
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
test [edi+ExpressionTerm.attributes],EXPRF_VALUE_IN_WORKSPACE
|
|
jz value_pointer_ready
|
|
add edx,[value_workspace.memory_start]
|
|
value_pointer_ready:
|
|
retn
|
|
|
|
get_numeric_term_value:
|
|
; in: edi - ExpressionTerm
|
|
; out: edx - 32-bit length followed by numeric data
|
|
; preserves: ebx, esi, edi
|
|
; note:
|
|
; term is converted to numeric and the value workspace may be modified in process
|
|
; other pointers to term values may become invalidated
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
test eax,EXPRF_VALUE_IN_WORKSPACE
|
|
jz convert_to_numeric
|
|
add edx,[value_workspace.memory_start]
|
|
convert_to_numeric:
|
|
cmp al,EXPR_FLOAT
|
|
je wrong_numeric_type
|
|
cmp al,EXPR_NUMBER
|
|
je value_pointer_ready
|
|
mov eax,[edx]
|
|
test byte [edx+4+eax-1],80h
|
|
jnz extend_to_unsigned_value
|
|
mov byte [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
retn
|
|
wrong_numeric_type:
|
|
mov edx,_invalid_value
|
|
call register_error
|
|
mov edx,zero_value
|
|
mov [edi+ExpressionTerm.value],edx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
retn
|
|
extend_to_unsigned_value:
|
|
push esi edi
|
|
mov esi,edi
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,[edx]
|
|
add ecx,5
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointer_for_unsigned_value_ready
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointer_for_unsigned_value_ready:
|
|
mov eax,EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
xchg eax,[esi+ExpressionTerm.attributes]
|
|
mov edx,[value_position]
|
|
xchg edx,[esi+ExpressionTerm.value]
|
|
mov esi,edx
|
|
test eax,EXPRF_VALUE_IN_WORKSPACE
|
|
jz make_unsigned_value
|
|
add esi,[value_workspace.memory_start]
|
|
make_unsigned_value:
|
|
mov edx,edi
|
|
lodsd
|
|
stosd
|
|
mov ecx,eax
|
|
rep movsb
|
|
xor al,al
|
|
stosb
|
|
sub edi,[value_workspace.memory_start]
|
|
mov [value_position],edi
|
|
inc dword [edx]
|
|
pop edi esi
|
|
retn
|
|
|
|
get_string_term_value:
|
|
; in: edi - ExpressionTerm
|
|
; out: edx - 32-bit length followed by string data
|
|
; preserves: ebx, ecx, esi, edi
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
cmp al,EXPR_STRING
|
|
je string_value_available
|
|
mov byte [edi+ExpressionTerm.attributes],EXPR_STRING
|
|
cmp al,EXPR_NUMBER
|
|
je string_value_available
|
|
mov edx,_invalid_value
|
|
call register_error
|
|
mov edx,zero_value
|
|
mov [edi+ExpressionTerm.value],edx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_STRING
|
|
retn
|
|
string_value_available:
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
test eax,EXPRF_VALUE_IN_WORKSPACE
|
|
jz string_value_pointer_ready
|
|
add edx,[value_workspace.memory_start]
|
|
string_value_pointer_ready:
|
|
retn
|
|
|
|
get_float_term_value:
|
|
; in: edi - ExpressionTerm
|
|
; out: edx - FloatData
|
|
; preserves: ebx, esi, edi
|
|
; note:
|
|
; term is converted to float and the value workspace may be modified in process
|
|
; other pointers to term values may become invalidated
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
test eax,EXPRF_VALUE_IN_WORKSPACE
|
|
jz convert_to_float
|
|
add edx,[value_workspace.memory_start]
|
|
convert_to_float:
|
|
cmp al,EXPR_FLOAT
|
|
je value_pointer_ready
|
|
cmp al,EXPR_STRING
|
|
je convert_positive_to_float
|
|
mov eax,[edx]
|
|
test byte [edx+4+eax-1],80h
|
|
jnz convert_negative_to_float
|
|
convert_positive_to_float:
|
|
push ebx esi
|
|
mov ebx,edi
|
|
mov edx,value_workspace
|
|
mov edi,[edx+Workspace.memory_start]
|
|
add edi,[value_position]
|
|
mov ecx,sizeof.FloatData
|
|
call reserve_workspace
|
|
xchg edi,ebx
|
|
call get_term_value
|
|
mov esi,edx
|
|
lea eax,[ebx+sizeof.FloatData]
|
|
sub eax,[value_workspace.memory_start]
|
|
xchg eax,[value_position]
|
|
mov [edi+ExpressionTerm.value],eax
|
|
mov [edi+ExpressionTerm.attributes],EXPR_FLOAT + EXPRF_VALUE_IN_WORKSPACE
|
|
push edi
|
|
mov edi,ebx
|
|
call number_to_float
|
|
mov edx,edi
|
|
pop edi esi ebx
|
|
retn
|
|
convert_negative_to_float:
|
|
push ebx
|
|
call negate_term_value
|
|
pop ebx
|
|
call convert_positive_to_float
|
|
or [edx+FloatData.attributes],FLOAT_NEGATIVE
|
|
retn
|
|
|
|
negate_term_value:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
push esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,[esi]
|
|
add ecx,5
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_negation
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_negation:
|
|
mov edx,[esi]
|
|
and edx,not 11b
|
|
mov eax,1
|
|
xor ecx,ecx
|
|
add esi,4
|
|
add edi,4
|
|
negate_dwords:
|
|
cmp ecx,edx
|
|
je dwords_negated
|
|
mov ebx,[esi+ecx]
|
|
not ebx
|
|
add eax,ebx
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
movzx eax,al
|
|
add ecx,4
|
|
jmp negate_dwords
|
|
dwords_negated:
|
|
mov edx,[esi-4]
|
|
negate_bytes:
|
|
cmp ecx,edx
|
|
je bytes_negated
|
|
mov bl,[esi+ecx]
|
|
not bl
|
|
add al,bl
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp negate_bytes
|
|
bytes_negated:
|
|
movsx ebx,byte [esi+ecx-1]
|
|
not bh
|
|
add al,bh
|
|
mov [edi+ecx],al
|
|
pop esi
|
|
value_calculated:
|
|
jecxz check_for_zero
|
|
optimize_value:
|
|
movsx edx,byte [edi+ecx-1]
|
|
cmp dh,[edi+ecx]
|
|
jne value_optimized
|
|
loop optimize_value
|
|
check_for_zero:
|
|
cmp byte [edi],0
|
|
je finish_value
|
|
value_optimized:
|
|
inc ecx
|
|
finish_value:
|
|
sub edi,4
|
|
mov [edi],ecx
|
|
value_finished:
|
|
mov edx,edi
|
|
sub edx,[value_workspace.memory_start]
|
|
lea eax,[edx+4+ecx]
|
|
mov [value_position],eax
|
|
mov edi,[destination_term]
|
|
mov [edi+ExpressionTerm.value],edx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
test ecx,ecx
|
|
retn
|
|
|
|
add_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
call prepare_pointers_for_summation
|
|
mov edx,[ebx]
|
|
cmp edx,[esi]
|
|
jb shorter_addend_selected
|
|
mov edx,[esi]
|
|
xchg ebx,esi
|
|
shorter_addend_selected:
|
|
and edx,not 11b
|
|
add ebx,4
|
|
add esi,4
|
|
add edi,4
|
|
xor al,al
|
|
xor ecx,ecx
|
|
add_dwords:
|
|
cmp ecx,edx
|
|
je dwords_added
|
|
neg al
|
|
mov eax,[esi+ecx]
|
|
adc eax,[ebx+ecx]
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp add_dwords
|
|
dwords_added:
|
|
mov edx,[ebx-4]
|
|
add_bytes:
|
|
cmp ecx,edx
|
|
je bytes_added
|
|
neg al
|
|
mov al,[esi+ecx]
|
|
adc al,[ebx+ecx]
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp add_bytes
|
|
bytes_added:
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
carry_dwords:
|
|
cmp ecx,edx
|
|
je dwords_carried
|
|
neg al
|
|
mov eax,[esi+ecx]
|
|
adc eax,ebx
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp carry_dwords
|
|
dwords_carried:
|
|
mov edx,[esi-4]
|
|
carry_bytes:
|
|
cmp ecx,edx
|
|
je bytes_carried
|
|
neg al
|
|
mov al,[esi+ecx]
|
|
adc al,bl
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp carry_bytes
|
|
bytes_carried:
|
|
movsx edx,byte [esi+ecx-1]
|
|
neg al
|
|
mov al,dh
|
|
adc al,bl
|
|
mov [edi+ecx],al
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
prepare_pointers_for_summation:
|
|
mov [source_term],esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov ebx,[edx]
|
|
mov edi,esi
|
|
call get_numeric_term_value
|
|
mov ecx,[edx]
|
|
cmp ecx,ebx
|
|
jae sum_length_estimated
|
|
mov ecx,ebx
|
|
sum_length_estimated:
|
|
add ecx,5
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov ebx,edx
|
|
mov edi,esi
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
retn
|
|
|
|
subtract_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
call prepare_pointers_for_summation
|
|
mov edx,[esi]
|
|
cmp edx,[ebx]
|
|
jb shorter_length_selected
|
|
mov edx,[ebx]
|
|
shorter_length_selected:
|
|
push edx
|
|
and edx,not 11b
|
|
add ebx,4
|
|
add esi,4
|
|
add edi,4
|
|
xor al,al
|
|
xor ecx,ecx
|
|
subtract_dwords:
|
|
cmp ecx,edx
|
|
je dwords_subtracted
|
|
neg al
|
|
mov eax,[ebx+ecx]
|
|
sbb eax,[esi+ecx]
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp subtract_dwords
|
|
dwords_subtracted:
|
|
pop edx
|
|
subtract_bytes:
|
|
cmp ecx,edx
|
|
je bytes_subtracted
|
|
neg al
|
|
mov al,[ebx+ecx]
|
|
sbb al,[esi+ecx]
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp subtract_bytes
|
|
bytes_subtracted:
|
|
cmp ecx,[ebx-4]
|
|
je minuend_ended
|
|
xchg esi,ebx
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
borrow_dwords:
|
|
cmp ecx,edx
|
|
je dwords_borrowed
|
|
neg al
|
|
mov eax,[esi+ecx]
|
|
sbb eax,ebx
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp borrow_dwords
|
|
dwords_borrowed:
|
|
mov edx,[esi-4]
|
|
borrow_bytes:
|
|
cmp ecx,edx
|
|
je bytes_borrowed
|
|
neg al
|
|
mov al,[esi+ecx]
|
|
sbb al,bl
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp borrow_bytes
|
|
bytes_borrowed:
|
|
movsx edx,byte [esi+ecx-1]
|
|
neg al
|
|
mov al,dh
|
|
sbb al,bl
|
|
mov [edi+ecx],al
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
minuend_ended:
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
subtract_supernumerary_dwords:
|
|
cmp ecx,edx
|
|
je supernumerary_dwords_subtracted
|
|
neg al
|
|
mov eax,ebx
|
|
sbb eax,[esi+ecx]
|
|
mov [edi+ecx],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp subtract_supernumerary_dwords
|
|
supernumerary_dwords_subtracted:
|
|
mov edx,[esi-4]
|
|
subtract_supernumerary_bytes:
|
|
cmp ecx,edx
|
|
je supernumerary_bytes_subtracted
|
|
neg al
|
|
mov al,bl
|
|
sbb al,[esi+ecx]
|
|
mov [edi+ecx],al
|
|
setc al
|
|
inc ecx
|
|
jmp subtract_supernumerary_bytes
|
|
supernumerary_bytes_subtracted:
|
|
movsx edx,byte [esi+ecx-1]
|
|
neg al
|
|
mov al,bl
|
|
sbb al,dh
|
|
mov [edi+ecx],al
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
|
|
multiply_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
mov [source_term],esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov edi,multiplier
|
|
mov ecx,4
|
|
call fit_value
|
|
jnc multiply_by_dword
|
|
mov edi,esi
|
|
call get_numeric_term_value
|
|
mov esi,[destination_term]
|
|
mov edi,multiplier
|
|
mov ecx,4
|
|
call fit_value
|
|
jnc multiply_by_dword
|
|
mov edi,[source_term]
|
|
call get_term_value
|
|
mov ebx,[edx]
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov eax,[edx]
|
|
mov ecx,ebx
|
|
add ecx,eax
|
|
cmp ebx,eax
|
|
jae split_length_selected
|
|
xchg ebx,eax
|
|
split_length_selected:
|
|
shr ebx,1
|
|
add ecx,18
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
mov eax,edi
|
|
mov edi,[source_term]
|
|
push edi
|
|
call get_term_value
|
|
mov edi,eax
|
|
mov esi,edx
|
|
call split_value
|
|
mov eax,edi
|
|
mov edi,[destination_term]
|
|
push edi
|
|
call get_term_value
|
|
mov edi,eax
|
|
mov esi,edx
|
|
call split_value
|
|
sub edi,[value_workspace.memory_start]
|
|
mov edx,edi
|
|
mov edi,[free_temporary_terms]
|
|
add [free_temporary_terms],6*sizeof.ExpressionTerm
|
|
mov eax,EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
xchg edx,[value_position]
|
|
push edx
|
|
mov esi,[value_workspace.memory_start]
|
|
mov ecx,4
|
|
create_temporary_terms:
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
add edx,[esi+edx]
|
|
add edx,4
|
|
add edi,sizeof.ExpressionTerm
|
|
loop create_temporary_terms
|
|
mov ecx,2
|
|
duplicate_temporary_terms:
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov edx,[edi-4*sizeof.ExpressionTerm+ExpressionTerm.value]
|
|
mov [edi+ExpressionTerm.value],edx
|
|
add edi,sizeof.ExpressionTerm
|
|
loop duplicate_temporary_terms
|
|
push ebx
|
|
sub edi,6*sizeof.ExpressionTerm
|
|
lea esi,[edi+2*sizeof.ExpressionTerm]
|
|
call multiply_term_values
|
|
add esi,sizeof.ExpressionTerm
|
|
add edi,sizeof.ExpressionTerm
|
|
call multiply_term_values
|
|
add edi,sizeof.ExpressionTerm
|
|
call add_term_values
|
|
add esi,2*sizeof.ExpressionTerm
|
|
add edi,2*sizeof.ExpressionTerm
|
|
call add_term_values
|
|
mov esi,edi
|
|
sub edi,2*sizeof.ExpressionTerm
|
|
call multiply_term_values
|
|
add edi,sizeof.ExpressionTerm
|
|
mov eax,[esi-3*sizeof.ExpressionTerm+ExpressionTerm.attributes]
|
|
mov edx,[esi-3*sizeof.ExpressionTerm+ExpressionTerm.value]
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],edx
|
|
mov eax,[edi-3*sizeof.ExpressionTerm+ExpressionTerm.attributes]
|
|
mov edx,[edi-3*sizeof.ExpressionTerm+ExpressionTerm.value]
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
call add_term_values
|
|
sub edi,sizeof.ExpressionTerm
|
|
sub esi,sizeof.ExpressionTerm
|
|
call subtract_term_values
|
|
mov eax,[esp]
|
|
xor dl,dl
|
|
shld edx,eax,3
|
|
shl eax,3
|
|
call shift_term_value_left
|
|
mov esi,edi
|
|
sub edi,2*sizeof.ExpressionTerm
|
|
call add_term_values
|
|
mov esi,edi
|
|
add edi,sizeof.ExpressionTerm
|
|
pop eax
|
|
xor dl,dl
|
|
shld edx,eax,4
|
|
shl eax,4
|
|
call shift_term_value_left
|
|
pop [value_position]
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
pop edi
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
call add_term_values
|
|
mov [free_temporary_terms],esi
|
|
pop esi
|
|
test edi,edi
|
|
retn
|
|
split_value:
|
|
cmp ebx,[esi]
|
|
jae too_small_to_split
|
|
mov eax,ebx
|
|
inc eax
|
|
stosd
|
|
mov ecx,ebx
|
|
lodsd
|
|
rep movsb
|
|
mov ecx,eax
|
|
xor al,al
|
|
stosb
|
|
sub ecx,ebx
|
|
mov eax,ecx
|
|
stosd
|
|
rep movsb
|
|
retn
|
|
too_small_to_split:
|
|
lodsd
|
|
mov ecx,eax
|
|
stosd
|
|
rep movsb
|
|
xor eax,eax
|
|
stosd
|
|
retn
|
|
multiply_by_dword:
|
|
sets al
|
|
mov [multiplier_sign],al
|
|
movzx eax,al
|
|
or eax,[multiplier]
|
|
jz zero_product
|
|
mov ebx,esi
|
|
mov edi,esi
|
|
call get_numeric_term_value
|
|
mov esi,edx
|
|
mov ecx,[esi]
|
|
add ecx,16
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_multiplication_by_dword
|
|
mov edi,ebx
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_multiplication_by_dword:
|
|
mov eax,[esi]
|
|
and eax,not 11b
|
|
mov [edi],eax
|
|
add esi,4
|
|
add edi,4
|
|
xor ebx,ebx
|
|
xor ecx,ecx
|
|
multiply_dwords_by_dword:
|
|
cmp ecx,[edi-4]
|
|
je dwords_multiplied_by_dword
|
|
mov eax,[esi+ecx]
|
|
mul [multiplier]
|
|
add eax,ebx
|
|
adc edx,0
|
|
mov ebx,edx
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp multiply_dwords_by_dword
|
|
dwords_multiplied_by_dword:
|
|
mov edx,[esi-4]
|
|
and edx,11b
|
|
jz only_sign_in_last_dword
|
|
cmp edx,2
|
|
jb single_byte_in_last_dword
|
|
je two_bytes_in_last_dword
|
|
movsx eax,byte [esi+ecx+2]
|
|
shl eax,16
|
|
mov ax,[esi+ecx]
|
|
jmp last_dword_ready
|
|
two_bytes_in_last_dword:
|
|
movsx eax,word [esi+ecx]
|
|
jmp last_dword_ready
|
|
single_byte_in_last_dword:
|
|
movsx eax,byte [esi+ecx]
|
|
jmp last_dword_ready
|
|
only_sign_in_last_dword:
|
|
movsx eax,byte [esi+ecx-1]
|
|
sar eax,8
|
|
last_dword_ready:
|
|
mov [edi-4],eax
|
|
mul [multiplier]
|
|
add eax,ebx
|
|
adc edx,0
|
|
mov [edi+ecx],eax
|
|
xor eax,eax
|
|
mov ebx,[esi-4]
|
|
test byte [esi+ebx-1],80h
|
|
jz product_extension
|
|
sub edx,[multiplier]
|
|
sbb eax,0
|
|
product_extension:
|
|
mov [edi+ecx+4],edx
|
|
add ecx,8
|
|
mov [edi+ecx],eax
|
|
cmp [multiplier_sign],0
|
|
je product_ready
|
|
mov edx,[esi-4]
|
|
and edx,not 11b
|
|
xor ecx,ecx
|
|
xor al,al
|
|
adjust_product:
|
|
cmp ecx,edx
|
|
je finish_product_adjustment
|
|
neg al
|
|
mov eax,[esi+ecx]
|
|
sbb [edi+ecx+4],eax
|
|
setc al
|
|
add ecx,4
|
|
jmp adjust_product
|
|
finish_product_adjustment:
|
|
neg al
|
|
mov eax,[edi-4]
|
|
cdq
|
|
sbb [edi+ecx+4],eax
|
|
sbb [edi+ecx+8],edx
|
|
add ecx,8
|
|
product_ready:
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
zero_product:
|
|
; zf already set
|
|
mov esi,[source_term]
|
|
mov edi,[destination_term]
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
retn
|
|
|
|
divide_term_values:
|
|
; in:
|
|
; esi - divisor ExpressionTerm, to be replaced with remainder
|
|
; edi - dividend ExpressionTerm, to be replaced with quotient
|
|
; out:
|
|
; zf set if remainder is zero
|
|
; preserves: esi, edi
|
|
mov [source_term],esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov eax,[edx]
|
|
test byte [edx+4+eax-1],80h
|
|
jnz negative_dividend
|
|
xchg edi,esi
|
|
call get_numeric_term_value
|
|
mov eax,[edx]
|
|
test byte [edx+4+eax-1],80h
|
|
jnz negative_divisor
|
|
mov edi,divisor
|
|
mov ecx,4
|
|
call fit_value
|
|
jnc divide_by_dword
|
|
xor eax,eax
|
|
mov ebx,[edx]
|
|
find_divisor_length:
|
|
mov al,[edx+4+ebx-1]
|
|
test al,al
|
|
jnz divisor_length_ok
|
|
dec ebx
|
|
jmp find_divisor_length
|
|
divisor_length_ok:
|
|
bsr ecx,eax
|
|
inc cl
|
|
mov [long_divisor_length],ebx
|
|
mov [high_bits_count],cl
|
|
mov ebx,[edx+4+ebx-5]
|
|
shrd ebx,eax,cl
|
|
inc ebx
|
|
mov [divisor],ebx
|
|
mov eax,[source_term]
|
|
mov [long_divisor_term],eax
|
|
mov eax,[destination_term]
|
|
mov [long_dividend_term],eax
|
|
mov edi,[free_temporary_terms]
|
|
add [free_temporary_terms],4*sizeof.ExpressionTerm
|
|
mov [division_temporary_terms],edi
|
|
xor eax,eax
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
compare_dividend_with_divisor:
|
|
mov esi,edx
|
|
mov edi,[long_dividend_term]
|
|
call get_term_value
|
|
xor eax,eax
|
|
mov ebx,[edx]
|
|
find_dividend_length:
|
|
mov al,[edx+4+ebx-1]
|
|
test al,al
|
|
jnz dividend_length_ok
|
|
dec ebx
|
|
jmp find_dividend_length
|
|
dividend_length_ok:
|
|
cmp ebx,[long_divisor_length]
|
|
ja long_division
|
|
jb dividend_to_remainder
|
|
bsr ecx,eax
|
|
inc cl
|
|
cmp cl,[high_bits_count]
|
|
ja long_division
|
|
jb dividend_to_remainder
|
|
compare_with_divisor_bytes:
|
|
mov al,[edx+4+ebx-1]
|
|
cmp al,[esi+4+ebx-1]
|
|
ja subtract_divisor
|
|
jb dividend_to_remainder
|
|
dec ebx
|
|
jnz compare_with_divisor_bytes
|
|
mov esi,[long_divisor_term]
|
|
mov edi,[long_dividend_term]
|
|
mov eax,EXPR_NUMBER
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],zero_value
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],singular_value
|
|
jmp accomodate_quotient
|
|
dividend_to_remainder:
|
|
mov esi,[division_temporary_terms]
|
|
mov [free_temporary_terms],esi
|
|
mov eax,[esi+ExpressionTerm.attributes]
|
|
mov edx,[esi+ExpressionTerm.value]
|
|
test eax,eax
|
|
jnz quotient_ready
|
|
mov eax,EXPR_NUMBER
|
|
mov edx,zero_value
|
|
quotient_ready:
|
|
mov esi,[long_divisor_term]
|
|
mov edi,[long_dividend_term]
|
|
xchg eax,[edi+ExpressionTerm.attributes]
|
|
xchg edx,[edi+ExpressionTerm.value]
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],edx
|
|
jmp test_remainder
|
|
subtract_divisor:
|
|
mov esi,[long_divisor_term]
|
|
mov edi,[long_dividend_term]
|
|
call subtract_term_values
|
|
mov eax,EXPR_NUMBER
|
|
mov edx,singular_value
|
|
xchg eax,[edi+ExpressionTerm.attributes]
|
|
xchg edx,[edi+ExpressionTerm.value]
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],edx
|
|
accomodate_quotient:
|
|
mov esi,[division_temporary_terms]
|
|
mov [free_temporary_terms],esi
|
|
cmp [esi+ExpressionTerm.attributes],0
|
|
je quotient_complete
|
|
call add_term_values
|
|
quotient_complete:
|
|
mov esi,[long_divisor_term]
|
|
test_remainder:
|
|
cmp dword [esi],0
|
|
retn
|
|
long_division:
|
|
mov edi,[division_temporary_terms]
|
|
add edi,sizeof.ExpressionTerm
|
|
mov esi,[long_dividend_term]
|
|
mov eax,[esi+ExpressionTerm.attributes]
|
|
mov edx,[esi+ExpressionTerm.value]
|
|
mov [edi+ExpressionTerm.attributes],eax
|
|
mov [edi+ExpressionTerm.value],edx
|
|
mov ecx,8
|
|
cmp [divisor],0
|
|
je shift_dividend_right
|
|
add cl,32
|
|
shift_dividend_right:
|
|
xor edx,edx
|
|
mov eax,[long_divisor_length]
|
|
shld edx,eax,3
|
|
shl eax,3
|
|
sub cl,[high_bits_count]
|
|
sub eax,ecx
|
|
sbb edx,0
|
|
call shift_term_value_right
|
|
cmp [divisor],0
|
|
je quotient_approximation_ready
|
|
mov esi,edi
|
|
mov [destination_term],esi
|
|
add edi,sizeof.ExpressionTerm
|
|
mov [source_term],edi
|
|
call divide_by_dword
|
|
quotient_approximation_ready:
|
|
mov esi,[division_temporary_terms]
|
|
cmp [esi+ExpressionTerm.attributes],0
|
|
jne accumulate_quotient
|
|
mov eax,[edi+ExpressionTerm.attributes]
|
|
mov edx,[edi+ExpressionTerm.value]
|
|
mov [esi+ExpressionTerm.attributes],eax
|
|
mov [esi+ExpressionTerm.value],edx
|
|
jmp calculate_remainder
|
|
accumulate_quotient:
|
|
xchg esi,edi
|
|
call add_term_values
|
|
mov edi,esi
|
|
calculate_remainder:
|
|
mov esi,[long_divisor_term]
|
|
call multiply_term_values
|
|
mov esi,edi
|
|
mov edi,[long_dividend_term]
|
|
call subtract_term_values
|
|
mov edi,[long_divisor_term]
|
|
call get_term_value
|
|
jmp compare_dividend_with_divisor
|
|
negative_divisor:
|
|
call negate_term_value
|
|
xchg edi,esi
|
|
call divide_term_values
|
|
pushf
|
|
call negate_term_value
|
|
popf
|
|
retn
|
|
negative_dividend:
|
|
call negate_term_value
|
|
xchg edi,esi
|
|
call get_numeric_term_value
|
|
mov eax,[edx]
|
|
test byte [edx+4+eax-1],80h
|
|
jnz negative_dividend_and_divisor
|
|
xchg edi,esi
|
|
call divide_term_values
|
|
call negate_term_value
|
|
jmp negative_remainder
|
|
negative_dividend_and_divisor:
|
|
call negate_term_value
|
|
xchg edi,esi
|
|
call divide_term_values
|
|
negative_remainder:
|
|
xchg edi,esi
|
|
call negate_term_value
|
|
xchg edi,esi
|
|
retn
|
|
divide_by_dword:
|
|
cmp [divisor],0
|
|
je division_by_zero
|
|
mov ebx,esi
|
|
mov edi,esi
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov ecx,[esi]
|
|
add ecx,4+9
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_division_by_dword
|
|
mov edi,ebx
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_division_by_dword:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
add edi,4
|
|
mov ecx,eax
|
|
and ecx,not 11b
|
|
xor edx,edx
|
|
and eax,11b
|
|
jz first_dword_for_division_ready
|
|
cmp eax,2
|
|
jb single_byte_in_first_dword
|
|
je two_bytes_in_first_dword
|
|
mov dl,[esi+ecx+2]
|
|
shl edx,16
|
|
two_bytes_in_first_dword:
|
|
mov dh,[esi+ecx+1]
|
|
single_byte_in_first_dword:
|
|
mov dl,[esi+ecx]
|
|
first_dword_for_division_ready:
|
|
mov eax,edx
|
|
xor edx,edx
|
|
div [divisor]
|
|
mov [edi+ecx],eax
|
|
divide_dwords:
|
|
sub ecx,4
|
|
jc dwords_divided
|
|
mov eax,[esi+ecx]
|
|
div [divisor]
|
|
mov [edi+ecx],eax
|
|
jmp divide_dwords
|
|
dwords_divided:
|
|
mov ecx,[esi-4]
|
|
and ecx,not 11b
|
|
add ecx,4
|
|
call optimize_positive_value
|
|
lea ebx,[edi-4]
|
|
mov [ebx],ecx
|
|
lea edi,[edi+ecx+4]
|
|
mov ecx,5
|
|
mov [edi],edx
|
|
mov [edi+4],ch
|
|
call optimize_positive_value
|
|
lea eax,[edi-4]
|
|
mov [eax],ecx
|
|
sub ebx,[value_workspace.memory_start]
|
|
mov edi,[destination_term]
|
|
mov [edi+ExpressionTerm.value],ebx
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
sub eax,[value_workspace.memory_start]
|
|
mov esi,[source_term]
|
|
mov [esi+ExpressionTerm.value],eax
|
|
mov [esi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
add eax,4
|
|
add eax,ecx
|
|
mov [value_position],eax
|
|
test ecx,ecx
|
|
retn
|
|
optimize_positive_value:
|
|
mov al,[edi+ecx-1]
|
|
test al,al
|
|
js zero_extension_needed
|
|
jnz positive_value_optimized
|
|
dec ecx
|
|
jnz optimize_positive_value
|
|
positive_value_optimized:
|
|
retn
|
|
zero_extension_needed:
|
|
inc ecx
|
|
retn
|
|
division_by_zero:
|
|
mov edx,_indeterminate_result
|
|
call register_error
|
|
xor eax,eax
|
|
jmp zero_product
|
|
|
|
invert_term_value_bits:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,[esi]
|
|
add ecx,4
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_bit_inversion
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_bit_inversion:
|
|
mov edx,[esi]
|
|
xor ecx,ecx
|
|
test edx,edx
|
|
jz invert_zero
|
|
and edx,not 11b
|
|
add esi,4
|
|
add edi,4
|
|
invert_bits_in_dwords:
|
|
cmp ecx,edx
|
|
je bits_in_dwords_inverted
|
|
mov eax,[esi+ecx]
|
|
not eax
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp invert_bits_in_dwords
|
|
bits_in_dwords_inverted:
|
|
mov edx,[esi-4]
|
|
invert_bits_in_bytes:
|
|
cmp ecx,edx
|
|
je bits_in_bytes_inverted
|
|
mov al,[esi+ecx]
|
|
not al
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp invert_bits_in_bytes
|
|
bits_in_bytes_inverted:
|
|
sub edi,4
|
|
mov [edi],ecx
|
|
jmp value_finished
|
|
invert_zero:
|
|
inc ecx
|
|
mov [edi],ecx
|
|
neg cl
|
|
mov [edi+4],cl
|
|
jmp value_finished
|
|
|
|
bitwise_add_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
call set_up_bitwise_operation
|
|
jc zero_product
|
|
bitwise_add_dwords:
|
|
cmp ecx,edx
|
|
je dwords_added_bitwise
|
|
mov eax,[esi+ecx]
|
|
xor eax,[ebx+ecx]
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp bitwise_add_dwords
|
|
dwords_added_bitwise:
|
|
mov edx,[ebx-4]
|
|
bitwise_add_bytes:
|
|
cmp ecx,edx
|
|
je bytes_added_bitwise
|
|
mov al,[esi+ecx]
|
|
xor al,[ebx+ecx]
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp bitwise_add_bytes
|
|
bytes_added_bitwise:
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
bitwise_add_supernumerary_dwords:
|
|
cmp ecx,edx
|
|
je supernumerary_dwords_added_bitwise
|
|
mov eax,[esi+ecx]
|
|
xor eax,ebx
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp bitwise_add_supernumerary_dwords
|
|
supernumerary_dwords_added_bitwise:
|
|
mov edx,[esi-4]
|
|
bitwise_add_supernumerary_bytes:
|
|
cmp ecx,edx
|
|
je supernumerary_bytes_added_bitwise
|
|
mov al,[esi+ecx]
|
|
xor al,bl
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp bitwise_add_supernumerary_bytes
|
|
supernumerary_bytes_added_bitwise:
|
|
dec ecx
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
set_up_bitwise_operation:
|
|
mov [source_term],esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov ebx,[edx]
|
|
mov edi,esi
|
|
call get_numeric_term_value
|
|
mov ecx,[edx]
|
|
mov eax,ecx
|
|
or eax,ebx
|
|
jz bitwise_zero_with_zero
|
|
cmp ecx,ebx
|
|
jae bitwise_result_length_estimated
|
|
mov ecx,ebx
|
|
bitwise_result_length_estimated:
|
|
add ecx,4
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov ebx,edx
|
|
mov edi,esi
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov edx,[ebx]
|
|
cmp edx,[esi]
|
|
jb shorter_value_selected
|
|
mov edx,[esi]
|
|
xchg ebx,esi
|
|
shorter_value_selected:
|
|
and edx,not 11b
|
|
add ebx,4
|
|
add esi,4
|
|
add edi,4
|
|
xor al,al
|
|
xor ecx,ecx
|
|
retn
|
|
bitwise_zero_with_zero:
|
|
stc
|
|
retn
|
|
|
|
bitwise_multiply_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
call set_up_bitwise_operation
|
|
jc zero_product
|
|
bitwise_multiply_dwords:
|
|
cmp ecx,edx
|
|
je dwords_multiplied_bitwise
|
|
mov eax,[esi+ecx]
|
|
and eax,[ebx+ecx]
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp bitwise_multiply_dwords
|
|
dwords_multiplied_bitwise:
|
|
mov edx,[ebx-4]
|
|
bitwise_multiply_bytes:
|
|
cmp ecx,edx
|
|
je bytes_multiplied_bitwise
|
|
mov al,[esi+ecx]
|
|
and al,[ebx+ecx]
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp bitwise_multiply_bytes
|
|
bytes_multiplied_bitwise:
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
bitwise_multiply_supernumerary_dwords:
|
|
cmp ecx,edx
|
|
je supernumerary_dwords_multiplied_bitwise
|
|
mov eax,[esi+ecx]
|
|
and eax,ebx
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp bitwise_multiply_supernumerary_dwords
|
|
supernumerary_dwords_multiplied_bitwise:
|
|
mov edx,[esi-4]
|
|
bitwise_multiply_supernumerary_bytes:
|
|
cmp ecx,edx
|
|
je supernumerary_bytes_multiplied_bitwise
|
|
mov al,[esi+ecx]
|
|
and al,bl
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp bitwise_multiply_supernumerary_bytes
|
|
supernumerary_bytes_multiplied_bitwise:
|
|
dec ecx
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
|
|
bitwise_inclusive_or_of_term_values:
|
|
; in:
|
|
; esi - source ExpressionTerm
|
|
; edi - destination ExpressionTerm
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
call set_up_bitwise_operation
|
|
jc zero_product
|
|
inclusive_or_of_dwords:
|
|
cmp ecx,edx
|
|
je performed_inclusive_or_of_dwords
|
|
mov eax,[esi+ecx]
|
|
or eax,[ebx+ecx]
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp inclusive_or_of_dwords
|
|
performed_inclusive_or_of_dwords:
|
|
mov edx,[ebx-4]
|
|
inclusive_or_of_bytes:
|
|
cmp ecx,edx
|
|
je performed_inclusive_or_of_bytes
|
|
mov al,[esi+ecx]
|
|
or al,[ebx+ecx]
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp inclusive_or_of_bytes
|
|
performed_inclusive_or_of_bytes:
|
|
movsx ebx,byte [ebx+ecx-1]
|
|
sar ebx,8
|
|
mov edx,[esi-4]
|
|
sub edx,ecx
|
|
and edx,not 11b
|
|
add edx,ecx
|
|
inclusive_or_of_supernumerary_dwords:
|
|
cmp ecx,edx
|
|
je performed_inclusive_or_of_supernumerary_dwords
|
|
mov eax,[esi+ecx]
|
|
or eax,ebx
|
|
mov [edi+ecx],eax
|
|
add ecx,4
|
|
jmp inclusive_or_of_supernumerary_dwords
|
|
performed_inclusive_or_of_supernumerary_dwords:
|
|
mov edx,[esi-4]
|
|
inclusive_or_of_supernumerary_bytes:
|
|
cmp ecx,edx
|
|
je performed_inclusive_or_of_supernumerary_bytes
|
|
mov al,[esi+ecx]
|
|
or al,bl
|
|
mov [edi+ecx],al
|
|
inc ecx
|
|
jmp inclusive_or_of_supernumerary_bytes
|
|
performed_inclusive_or_of_supernumerary_bytes:
|
|
dec ecx
|
|
mov esi,[source_term]
|
|
jmp value_calculated
|
|
|
|
shift_term_value_left:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; dl:eax = number of bits
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
mov ebx,eax
|
|
and al,8-1
|
|
mov [bit_shift],al
|
|
shrd ebx,edx,3
|
|
shr dl,3
|
|
mov [shift_overflow],dl
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov eax,[edx]
|
|
check_for_shifted_zero:
|
|
test eax,eax
|
|
jz shift_left_ok
|
|
cmp byte [edx+4+eax-1],0
|
|
jne reserve_memory_for_shift_left
|
|
dec eax
|
|
jmp check_for_shifted_zero
|
|
reserve_memory_for_shift_left:
|
|
cmp [shift_overflow],0
|
|
jne out_of_memory
|
|
push esi
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,[esi]
|
|
add ecx,ebx
|
|
jc out_of_memory
|
|
add ecx,5
|
|
jc out_of_memory
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_shift_left
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_shift_left:
|
|
add edi,4
|
|
mov ecx,ebx
|
|
push ecx
|
|
xor al,al
|
|
rep stosb
|
|
mov cl,[bit_shift]
|
|
mov edx,[esi]
|
|
add esi,4
|
|
xor ebx,ebx
|
|
shift_bytes_left:
|
|
cmp ebx,edx
|
|
je bytes_shifted_left
|
|
mov ah,[esi+ebx]
|
|
shl eax,cl
|
|
mov [edi+ebx],ah
|
|
mov al,[esi+ebx]
|
|
inc ebx
|
|
jmp shift_bytes_left
|
|
bytes_shifted_left:
|
|
movsx eax,byte [esi+ebx-1]
|
|
shl eax,cl
|
|
mov [edi+ebx],ah
|
|
pop ecx
|
|
sub edi,ecx
|
|
add ecx,ebx
|
|
pop esi
|
|
jmp value_calculated
|
|
shift_left_ok:
|
|
retn
|
|
|
|
shift_term_value_right:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; dl:eax = number of bits
|
|
; out:
|
|
; zf set if result is zero
|
|
; preserves: esi, edi
|
|
push esi
|
|
mov ebx,eax
|
|
and al,8-1
|
|
mov [bit_shift],al
|
|
shrd ebx,edx,3
|
|
shr dl,3
|
|
jz byte_shift_ok
|
|
or ebx,-1
|
|
byte_shift_ok:
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,[esi]
|
|
sub ecx,ebx
|
|
jnc size_of_shift_result_estimated
|
|
xor ecx,ecx
|
|
size_of_shift_result_estimated:
|
|
add ecx,5
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_shift_right
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_shift_right:
|
|
add edi,4
|
|
mov cl,[bit_shift]
|
|
mov edx,[esi]
|
|
sub edx,ebx
|
|
jbe value_dissipated
|
|
lea esi,[esi+4+ebx]
|
|
xor ebx,ebx
|
|
shift_bytes_right:
|
|
inc ebx
|
|
cmp ebx,edx
|
|
je bytes_shifted_right
|
|
mov ax,[esi+ebx-1]
|
|
shr ax,cl
|
|
mov [edi+ebx-1],al
|
|
jmp shift_bytes_right
|
|
bytes_shifted_right:
|
|
dec ebx
|
|
movsx eax,byte [esi+ebx]
|
|
shr eax,cl
|
|
mov [edi+ebx],al
|
|
mov ecx,ebx
|
|
pop esi
|
|
jmp value_calculated
|
|
value_dissipated:
|
|
mov edx,[esi]
|
|
movsx eax,byte [esi+4+edx-1]
|
|
mov [edi],ah
|
|
xor ecx,ecx
|
|
pop esi
|
|
jmp value_calculated
|
|
|
|
find_first_set_bit_in_term_value:
|
|
; in:
|
|
; esi - ExpressionTerm
|
|
; out:
|
|
; zf set when value is zero
|
|
; when zf = 0:
|
|
; dl:eax = index of first set bit
|
|
; preserves: esi, edi
|
|
xchg edi,esi
|
|
call get_numeric_term_value
|
|
xchg edi,esi
|
|
mov ebx,edx
|
|
mov edx,[ebx]
|
|
and edx,not 11b
|
|
xor ecx,ecx
|
|
add ebx,4
|
|
find_first_set_bit_in_dwords:
|
|
cmp ecx,edx
|
|
je no_set_bit_found_in_dwords
|
|
bsf eax,[ebx+ecx]
|
|
jnz first_set_bit_found
|
|
add ecx,4
|
|
jmp find_first_set_bit_in_dwords
|
|
no_set_bit_found_in_dwords:
|
|
mov edx,[ebx-4]
|
|
find_first_set_bit_in_bytes:
|
|
cmp ecx,edx
|
|
je no_set_bit_found
|
|
movzx eax,byte [ebx+ecx]
|
|
bsf eax,eax
|
|
jnz first_set_bit_found
|
|
inc ecx
|
|
jmp find_first_set_bit_in_bytes
|
|
no_set_bit_found:
|
|
retn
|
|
first_set_bit_found:
|
|
xor dl,dl
|
|
shld edx,ecx,3
|
|
shl ecx,3
|
|
add eax,ecx
|
|
adc dl,0
|
|
inc dh
|
|
retn
|
|
|
|
find_last_set_bit_in_term_value:
|
|
; in:
|
|
; esi - ExpressionTerm
|
|
; out:
|
|
; cf set when value is zero or negative
|
|
; when cf = 0:
|
|
; dl:eax = index of last set bit
|
|
; preserves: esi, edi
|
|
xchg edi,esi
|
|
call get_numeric_term_value
|
|
xchg edi,esi
|
|
mov ebx,edx
|
|
mov edx,[ebx]
|
|
add ebx,4
|
|
test byte [ebx+edx-1],80h
|
|
jnz last_set_bit_unreachable
|
|
mov ecx,edx
|
|
and edx,11b
|
|
find_last_set_bit_in_dwords:
|
|
cmp ecx,edx
|
|
je find_last_set_bit_in_bytes
|
|
sub ecx,4
|
|
bsr eax,[ebx+ecx]
|
|
jnz last_set_bit_found
|
|
jmp find_last_set_bit_in_dwords
|
|
find_last_set_bit_in_bytes:
|
|
jecxz last_set_bit_unreachable
|
|
dec ecx
|
|
movzx eax,byte [ebx+ecx]
|
|
bsr eax,eax
|
|
jnz last_set_bit_found
|
|
jmp find_last_set_bit_in_bytes
|
|
last_set_bit_unreachable:
|
|
stc
|
|
retn
|
|
last_set_bit_found:
|
|
xor dl,dl
|
|
shld edx,ecx,3
|
|
shl ecx,3
|
|
add eax,ecx
|
|
adc dl,0
|
|
; clc
|
|
retn
|
|
|
|
truncate_term_value:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; preserves: edi
|
|
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
|
jne get_numeric_term_value
|
|
mov [destination_term],edi
|
|
call get_term_value
|
|
mov ecx,[edx+FloatData.exponent]
|
|
cmp ecx,0
|
|
jl no_integer_part
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
shr ecx,5
|
|
lea ecx,[4+(ecx+1)*4]
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
jnc pointers_ready_for_truncation
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov esi,edx
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
pointers_ready_for_truncation:
|
|
add edi,4
|
|
mov ecx,32*MANTISSA_SEGMENTS
|
|
sub ecx,[esi+FloatData.exponent]
|
|
jbe integer_precision_loss
|
|
dec ecx
|
|
mov edx,ecx
|
|
and ecx,11111b
|
|
shr edx,5
|
|
neg edx
|
|
add edx,MANTISSA_SEGMENTS
|
|
mov ebx,[esi+FloatData.mantissa+(edx-1)*4]
|
|
extract_integer_bits:
|
|
mov eax,ebx
|
|
dec edx
|
|
jz extract_highest_integer_bits
|
|
mov ebx,[esi+FloatData.mantissa+(edx-1)*4]
|
|
shrd eax,ebx,cl
|
|
stosd
|
|
jmp extract_integer_bits
|
|
extract_highest_integer_bits:
|
|
shr eax,cl
|
|
stosd
|
|
integer_part_ready:
|
|
and byte [edi],0
|
|
dec ecx
|
|
sar ecx,3
|
|
neg ecx
|
|
add ecx,edi
|
|
mov edi,[destination_term]
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER + EXPRF_VALUE_IN_WORKSPACE
|
|
mov edx,[value_position]
|
|
mov [edi+ExpressionTerm.value],edx
|
|
sub ecx,[value_workspace.memory_start]
|
|
mov [value_position],ecx
|
|
sub ecx,edx
|
|
sub ecx,4
|
|
add edx,[value_workspace.memory_start]
|
|
mov [edx],ecx
|
|
test [esi+FloatData.attributes],FLOAT_NEGATIVE
|
|
jnz negate_term_value
|
|
retn
|
|
integer_precision_loss:
|
|
neg ecx
|
|
inc ecx
|
|
mov edx,ecx
|
|
shr ecx,5
|
|
xor eax,eax
|
|
rep stosd
|
|
mov ecx,edx
|
|
and ecx,11111b
|
|
mov edx,MANTISSA_SEGMENTS-1
|
|
mov eax,[esi+FloatData.mantissa+edx*4]
|
|
shl eax,cl
|
|
stosd
|
|
extract_significant_bits:
|
|
mov eax,[esi+FloatData.mantissa+(edx-1)*4]
|
|
mov ebx,[esi+FloatData.mantissa+edx*4]
|
|
shld eax,ebx,cl
|
|
stosd
|
|
dec edx
|
|
jnz extract_significant_bits
|
|
mov eax,[esi+FloatData.mantissa+edx*4]
|
|
neg ecx
|
|
and ecx,11111b
|
|
jnz extract_highest_integer_bits
|
|
xor eax,eax
|
|
jmp integer_part_ready
|
|
no_integer_part:
|
|
mov [edi+ExpressionTerm.value],zero_value
|
|
mov [edi+ExpressionTerm.attributes],EXPR_NUMBER
|
|
retn
|
|
|
|
reverse_term_value_bytes:
|
|
; in:
|
|
; edi - ExpressionTerm
|
|
; ebx = number of bytes
|
|
; preserves: esi, edi
|
|
push esi
|
|
mov [destination_term],edi
|
|
call get_numeric_term_value
|
|
mov edi,[value_position]
|
|
add edi,[value_workspace.memory_start]
|
|
mov ecx,ebx
|
|
add ecx,4
|
|
mov edx,value_workspace
|
|
call reserve_workspace
|
|
mov edi,[destination_term]
|
|
call get_term_value
|
|
mov [edi+ExpressionTerm.attributes],EXPR_STRING + EXPRF_VALUE_IN_WORKSPACE
|
|
mov esi,[value_position]
|
|
mov [edi+ExpressionTerm.value],esi
|
|
lea eax,[esi+4+ebx]
|
|
mov [value_position],eax
|
|
add esi,[value_workspace.memory_start]
|
|
mov [esi],ebx
|
|
xor ecx,ecx
|
|
test ebx,ebx
|
|
jz reversed_bytes_ready
|
|
store_reversed_bytes:
|
|
cmp ecx,[edx]
|
|
jae extend_reversed_bytes
|
|
mov al,[edx+4+ecx]
|
|
mov [esi+4+ebx-1],al
|
|
inc ecx
|
|
dec ebx
|
|
jnz store_reversed_bytes
|
|
reversed_bytes_ready:
|
|
cmp ecx,[edx]
|
|
jae reversed_bytes_ok
|
|
mov al,[edx+4+ecx]
|
|
cbw
|
|
mov al,ah
|
|
lea edi,[edx+4+ecx]
|
|
neg ecx
|
|
add ecx,[edx]
|
|
repe scasb
|
|
je reversed_bytes_ok
|
|
mov edx,_value_out_of_range
|
|
call register_error
|
|
jmp reversed_bytes_ok
|
|
extend_reversed_bytes:
|
|
mov al,[edx+4+ecx-1]
|
|
cbw
|
|
mov al,ah
|
|
lea edi,[esi+4]
|
|
mov ecx,ebx
|
|
rep stosb
|
|
reversed_bytes_ok:
|
|
mov edi,[destination_term]
|
|
pop esi
|
|
retn
|