1290 lines
22 KiB
Plaintext
1290 lines
22 KiB
Plaintext
|
|
; flat assembler core
|
|
; Copyright (c) 1999-2022, Tomasz Grysztar.
|
|
; All rights reserved.
|
|
|
|
convert_expression:
|
|
push ebp
|
|
call get_fp_value
|
|
jnc fp_expression
|
|
mov [current_offset],esp
|
|
expression_loop:
|
|
push edi
|
|
mov edi,single_operand_operators
|
|
call get_operator
|
|
pop edi
|
|
or al,al
|
|
jz expression_element
|
|
cmp al,82h
|
|
je expression_loop
|
|
push eax
|
|
jmp expression_loop
|
|
expression_element:
|
|
mov al,[esi]
|
|
cmp al,1Ah
|
|
je expression_number
|
|
cmp al,22h
|
|
je expression_number
|
|
cmp al,'('
|
|
je expression_number
|
|
mov al,'!'
|
|
stos byte [edi]
|
|
jmp expression_operator
|
|
expression_number:
|
|
call convert_number
|
|
expression_operator:
|
|
push edi
|
|
mov edi,operators
|
|
call get_operator
|
|
pop edi
|
|
or al,al
|
|
jz expression_end
|
|
operators_loop:
|
|
cmp esp,[current_offset]
|
|
je push_operator
|
|
mov bl,al
|
|
and bl,0F0h
|
|
mov bh,byte [esp]
|
|
and bh,0F0h
|
|
cmp bl,bh
|
|
ja push_operator
|
|
pop ebx
|
|
mov byte [edi],bl
|
|
inc edi
|
|
jmp operators_loop
|
|
push_operator:
|
|
push eax
|
|
jmp expression_loop
|
|
expression_end:
|
|
cmp esp,[current_offset]
|
|
je expression_converted
|
|
pop eax
|
|
stos byte [edi]
|
|
jmp expression_end
|
|
expression_converted:
|
|
pop ebp
|
|
ret
|
|
fp_expression:
|
|
mov al,'.'
|
|
stos byte [edi]
|
|
mov eax,[fp_value]
|
|
stos dword [edi]
|
|
mov eax,[fp_value+4]
|
|
stos dword [edi]
|
|
mov eax,[fp_value+8]
|
|
stos dword [edi]
|
|
pop ebp
|
|
ret
|
|
|
|
convert_number:
|
|
lea eax,[edi+20h]
|
|
mov edx,[memory_end]
|
|
cmp [source_start],0
|
|
je check_memory_for_number
|
|
mov edx,[labels_list]
|
|
check_memory_for_number:
|
|
cmp eax,edx
|
|
jae out_of_memory
|
|
mov eax,esp
|
|
sub eax,[stack_limit]
|
|
cmp eax,100h
|
|
jb stack_overflow
|
|
cmp byte [esi],'('
|
|
je expression_value
|
|
inc edi
|
|
call get_number
|
|
jc symbol_value
|
|
or ebp,ebp
|
|
jz valid_number
|
|
mov byte [edi-1],0Fh
|
|
ret
|
|
valid_number:
|
|
cmp dword [edi+4],0
|
|
jne qword_number
|
|
cmp word [edi+2],0
|
|
jne dword_number
|
|
cmp byte [edi+1],0
|
|
jne word_number
|
|
byte_number:
|
|
mov byte [edi-1],1
|
|
inc edi
|
|
ret
|
|
qword_number:
|
|
mov byte [edi-1],8
|
|
add edi,8
|
|
ret
|
|
dword_number:
|
|
mov byte [edi-1],4
|
|
scas dword [edi]
|
|
ret
|
|
word_number:
|
|
mov byte [edi-1],2
|
|
scas word [edi]
|
|
ret
|
|
expression_value:
|
|
inc esi
|
|
push [current_offset]
|
|
call convert_expression
|
|
pop [current_offset]
|
|
lods byte [esi]
|
|
cmp al,')'
|
|
je subexpression_closed
|
|
dec esi
|
|
mov al,'!'
|
|
stosb
|
|
subexpression_closed:
|
|
ret
|
|
symbol_value:
|
|
mov eax,[source_start]
|
|
test eax,eax
|
|
jz preprocessor_value
|
|
cmp eax,-1
|
|
je invalid_value
|
|
push edi esi
|
|
lods word [esi]
|
|
cmp al,1Ah
|
|
jne no_address_register
|
|
movzx ecx,ah
|
|
call get_symbol
|
|
jc no_address_register
|
|
cmp al,10h
|
|
jne no_address_register
|
|
mov al,ah
|
|
shr ah,4
|
|
cmp ah,4
|
|
je register_value
|
|
and ah,not 1
|
|
cmp ah,8
|
|
je register_value
|
|
cmp ah,0Ch
|
|
jae register_value
|
|
cmp ah,6
|
|
je register_value
|
|
cmp al,23h
|
|
je register_value
|
|
cmp al,25h
|
|
je register_value
|
|
cmp al,26h
|
|
je register_value
|
|
cmp al,27h
|
|
je register_value
|
|
no_address_register:
|
|
pop esi
|
|
mov edi,directive_operators
|
|
call get_operator
|
|
pop edi
|
|
or al,al
|
|
jnz broken_value
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_value
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
call get_label_id
|
|
store_label_value:
|
|
mov byte [edi-1],11h
|
|
stos dword [edi]
|
|
ret
|
|
broken_value:
|
|
mov eax,0Fh
|
|
jmp store_label_value
|
|
register_value:
|
|
pop edx edi
|
|
mov byte [edi-1],10h
|
|
stos byte [edi]
|
|
ret
|
|
preprocessor_value:
|
|
dec edi
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_value
|
|
lods byte [esi]
|
|
mov cl,al
|
|
mov ch,10b
|
|
call get_preprocessor_symbol
|
|
jc invalid_value
|
|
test edx,edx
|
|
jz special_preprocessor_value
|
|
push esi
|
|
mov esi,[edx+8]
|
|
push [current_offset]
|
|
call convert_expression
|
|
pop [current_offset]
|
|
pop esi
|
|
ret
|
|
special_preprocessor_value:
|
|
cmp eax,preprocessed_line_value
|
|
jne invalid_value
|
|
call get_current_line_from_file
|
|
mov al,4
|
|
stos byte [edi]
|
|
mov eax,[ebx+4]
|
|
stos dword [edi]
|
|
ret
|
|
|
|
get_number:
|
|
xor ebp,ebp
|
|
lods byte [esi]
|
|
cmp al,22h
|
|
je get_text_number
|
|
cmp al,1Ah
|
|
jne not_number
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
mov [number_start],esi
|
|
mov al,[esi]
|
|
cmp al,'$'
|
|
je number_begin
|
|
sub al,30h
|
|
cmp al,9
|
|
ja invalid_number
|
|
number_begin:
|
|
mov ebx,esi
|
|
add esi,ecx
|
|
push esi
|
|
dec esi
|
|
mov dword [edi],0
|
|
mov dword [edi+4],0
|
|
cmp byte [ebx],'$'
|
|
je pascal_hex_number
|
|
cmp word [ebx],'0x'
|
|
je get_hex_number
|
|
mov al,[esi]
|
|
dec esi
|
|
cmp al,'h'
|
|
je get_hex_number
|
|
cmp al,'b'
|
|
je get_bin_number
|
|
cmp al,'d'
|
|
je get_dec_number
|
|
cmp al,'o'
|
|
je get_oct_number
|
|
cmp al,'q'
|
|
je get_oct_number
|
|
cmp al,'H'
|
|
je get_hex_number
|
|
cmp al,'B'
|
|
je get_bin_number
|
|
cmp al,'D'
|
|
je get_dec_number
|
|
cmp al,'O'
|
|
je get_oct_number
|
|
cmp al,'Q'
|
|
je get_oct_number
|
|
inc esi
|
|
get_dec_number:
|
|
mov ebx,esi
|
|
mov esi,[number_start]
|
|
get_dec_digit:
|
|
cmp esi,ebx
|
|
ja number_ok
|
|
cmp byte [esi],27h
|
|
je next_dec_digit
|
|
cmp byte [esi],'_'
|
|
je next_dec_digit
|
|
xor edx,edx
|
|
mov eax,[edi]
|
|
shld edx,eax,2
|
|
shl eax,2
|
|
add eax,[edi]
|
|
adc edx,0
|
|
add eax,eax
|
|
adc edx,edx
|
|
mov [edi],eax
|
|
mov eax,[edi+4]
|
|
add eax,eax
|
|
jc dec_out_of_range
|
|
add eax,eax
|
|
jc dec_out_of_range
|
|
add eax,[edi+4]
|
|
jc dec_out_of_range
|
|
add eax,eax
|
|
jc dec_out_of_range
|
|
add eax,edx
|
|
jc dec_out_of_range
|
|
mov [edi+4],eax
|
|
movzx eax,byte [esi]
|
|
sub al,30h
|
|
jc bad_number
|
|
cmp al,9
|
|
ja bad_number
|
|
add [edi],eax
|
|
adc dword [edi+4],0
|
|
jc dec_out_of_range
|
|
next_dec_digit:
|
|
inc esi
|
|
jmp get_dec_digit
|
|
dec_out_of_range:
|
|
cmp esi,ebx
|
|
ja dec_out_of_range_finished
|
|
lods byte [esi]
|
|
cmp al,27h
|
|
je bad_number
|
|
cmp al,'_'
|
|
je bad_number
|
|
sub al,30h
|
|
jc bad_number
|
|
cmp al,9
|
|
ja bad_number
|
|
jmp dec_out_of_range
|
|
dec_out_of_range_finished:
|
|
or ebp,-1
|
|
jmp number_ok
|
|
bad_number:
|
|
pop eax
|
|
invalid_number:
|
|
mov esi,[number_start]
|
|
dec esi
|
|
not_number:
|
|
dec esi
|
|
stc
|
|
ret
|
|
get_bin_number:
|
|
xor bl,bl
|
|
get_bin_digit:
|
|
cmp esi,[number_start]
|
|
jb number_ok
|
|
movzx eax,byte [esi]
|
|
cmp al,27h
|
|
je bin_digit_skip
|
|
cmp al,'_'
|
|
je bin_digit_skip
|
|
sub al,30h
|
|
cmp al,1
|
|
ja bad_number
|
|
xor edx,edx
|
|
mov cl,bl
|
|
dec esi
|
|
cmp bl,64
|
|
je bin_out_of_range
|
|
inc bl
|
|
cmp cl,32
|
|
jae bin_digit_high
|
|
shl eax,cl
|
|
or dword [edi],eax
|
|
jmp get_bin_digit
|
|
bin_digit_high:
|
|
sub cl,32
|
|
shl eax,cl
|
|
or dword [edi+4],eax
|
|
jmp get_bin_digit
|
|
bin_out_of_range:
|
|
or al,al
|
|
jz get_bin_digit
|
|
or ebp,-1
|
|
jmp get_bin_digit
|
|
bin_digit_skip:
|
|
dec esi
|
|
jmp get_bin_digit
|
|
pascal_hex_number:
|
|
cmp cl,1
|
|
je bad_number
|
|
get_hex_number:
|
|
xor bl,bl
|
|
get_hex_digit:
|
|
cmp esi,[number_start]
|
|
jb number_ok
|
|
movzx eax,byte [esi]
|
|
cmp al,27h
|
|
je hex_digit_skip
|
|
cmp al,'_'
|
|
je hex_digit_skip
|
|
cmp al,'x'
|
|
je hex_number_ok
|
|
cmp al,'$'
|
|
je pascal_hex_ok
|
|
sub al,30h
|
|
cmp al,9
|
|
jbe hex_digit_ok
|
|
sub al,7
|
|
cmp al,15
|
|
jbe hex_letter_digit_ok
|
|
sub al,20h
|
|
cmp al,15
|
|
ja bad_number
|
|
hex_letter_digit_ok:
|
|
cmp al,10
|
|
jb bad_number
|
|
hex_digit_ok:
|
|
xor edx,edx
|
|
mov cl,bl
|
|
dec esi
|
|
cmp bl,64
|
|
je hex_out_of_range
|
|
add bl,4
|
|
cmp cl,32
|
|
jae hex_digit_high
|
|
shl eax,cl
|
|
or dword [edi],eax
|
|
jmp get_hex_digit
|
|
hex_digit_high:
|
|
sub cl,32
|
|
shl eax,cl
|
|
or dword [edi+4],eax
|
|
jmp get_hex_digit
|
|
hex_out_of_range:
|
|
or al,al
|
|
jz get_hex_digit
|
|
or ebp,-1
|
|
jmp get_hex_digit
|
|
hex_digit_skip:
|
|
dec esi
|
|
jmp get_hex_digit
|
|
get_oct_number:
|
|
xor bl,bl
|
|
get_oct_digit:
|
|
cmp esi,[number_start]
|
|
jb number_ok
|
|
movzx eax,byte [esi]
|
|
cmp al,27h
|
|
je oct_digit_skip
|
|
cmp al,'_'
|
|
je oct_digit_skip
|
|
sub al,30h
|
|
cmp al,7
|
|
ja bad_number
|
|
oct_digit_ok:
|
|
xor edx,edx
|
|
mov cl,bl
|
|
dec esi
|
|
cmp bl,63
|
|
ja oct_out_of_range
|
|
jne oct_range_ok
|
|
cmp al,1
|
|
ja oct_out_of_range
|
|
oct_range_ok:
|
|
add bl,3
|
|
cmp cl,30
|
|
je oct_digit_wrap
|
|
ja oct_digit_high
|
|
shl eax,cl
|
|
or dword [edi],eax
|
|
jmp get_oct_digit
|
|
oct_digit_wrap:
|
|
shl eax,cl
|
|
adc dword [edi+4],0
|
|
or dword [edi],eax
|
|
jmp get_oct_digit
|
|
oct_digit_high:
|
|
sub cl,32
|
|
shl eax,cl
|
|
or dword [edi+4],eax
|
|
jmp get_oct_digit
|
|
oct_digit_skip:
|
|
dec esi
|
|
jmp get_oct_digit
|
|
oct_out_of_range:
|
|
or al,al
|
|
jz get_oct_digit
|
|
or ebp,-1
|
|
jmp get_oct_digit
|
|
hex_number_ok:
|
|
dec esi
|
|
pascal_hex_ok:
|
|
cmp esi,[number_start]
|
|
jne bad_number
|
|
number_ok:
|
|
pop esi
|
|
number_done:
|
|
clc
|
|
ret
|
|
get_text_number:
|
|
lods dword [esi]
|
|
mov edx,eax
|
|
xor bl,bl
|
|
mov dword [edi],0
|
|
mov dword [edi+4],0
|
|
get_text_character:
|
|
sub edx,1
|
|
jc number_done
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
mov cl,bl
|
|
cmp bl,64
|
|
je text_out_of_range
|
|
add bl,8
|
|
cmp cl,32
|
|
jae text_character_high
|
|
shl eax,cl
|
|
or dword [edi],eax
|
|
jmp get_text_character
|
|
text_character_high:
|
|
sub cl,32
|
|
shl eax,cl
|
|
or dword [edi+4],eax
|
|
jmp get_text_character
|
|
text_out_of_range:
|
|
or ebp,-1
|
|
jmp get_text_character
|
|
|
|
get_fp_value:
|
|
push edi esi
|
|
fp_value_start:
|
|
lods byte [esi]
|
|
cmp al,'-'
|
|
je fp_value_start
|
|
cmp al,'+'
|
|
je fp_value_start
|
|
cmp al,1Ah
|
|
jne not_fp_value
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
cmp cl,1
|
|
jbe not_fp_value
|
|
lea edx,[esi+1]
|
|
xor ah,ah
|
|
check_fp_value:
|
|
lods byte [esi]
|
|
cmp al,'.'
|
|
je fp_character_dot
|
|
cmp al,'E'
|
|
je fp_character_exp
|
|
cmp al,'e'
|
|
je fp_character_exp
|
|
cmp al,'F'
|
|
je fp_last_character
|
|
cmp al,'f'
|
|
je fp_last_character
|
|
digit_expected:
|
|
cmp al,'0'
|
|
jb not_fp_value
|
|
cmp al,'9'
|
|
ja not_fp_value
|
|
jmp fp_character_ok
|
|
fp_character_dot:
|
|
cmp esi,edx
|
|
je not_fp_value
|
|
or ah,ah
|
|
jnz not_fp_value
|
|
or ah,1
|
|
lods byte [esi]
|
|
loop digit_expected
|
|
not_fp_value:
|
|
pop esi edi
|
|
stc
|
|
ret
|
|
fp_last_character:
|
|
cmp cl,1
|
|
jne not_fp_value
|
|
or ah,4
|
|
jmp fp_character_ok
|
|
fp_character_exp:
|
|
cmp esi,edx
|
|
je not_fp_value
|
|
cmp ah,1
|
|
ja not_fp_value
|
|
or ah,2
|
|
cmp ecx,1
|
|
jne fp_character_ok
|
|
cmp byte [esi],'+'
|
|
je fp_exp_sign
|
|
cmp byte [esi],'-'
|
|
jne fp_character_ok
|
|
fp_exp_sign:
|
|
inc esi
|
|
cmp byte [esi],1Ah
|
|
jne not_fp_value
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
inc ecx
|
|
fp_character_ok:
|
|
dec ecx
|
|
jnz check_fp_value
|
|
or ah,ah
|
|
jz not_fp_value
|
|
pop esi
|
|
mov [fp_sign],0
|
|
fp_get_sign:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je fp_get
|
|
cmp al,'+'
|
|
je fp_get_sign
|
|
xor [fp_sign],1
|
|
jmp fp_get_sign
|
|
fp_get:
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
xor edx,edx
|
|
mov edi,fp_value
|
|
mov [edi],edx
|
|
mov [edi+4],edx
|
|
mov [edi+12],edx
|
|
call fp_optimize
|
|
mov [fp_format],0
|
|
mov al,[esi]
|
|
fp_before_dot:
|
|
lods byte [esi]
|
|
cmp al,'.'
|
|
je fp_dot
|
|
cmp al,'E'
|
|
je fp_exponent
|
|
cmp al,'e'
|
|
je fp_exponent
|
|
cmp al,'F'
|
|
je fp_done
|
|
cmp al,'f'
|
|
je fp_done
|
|
sub al,30h
|
|
mov edi,fp_value+16
|
|
xor edx,edx
|
|
mov dword [edi+12],edx
|
|
mov dword [edi],edx
|
|
mov dword [edi+4],edx
|
|
mov [edi+7],al
|
|
mov dl,7
|
|
mov dword [edi+8],edx
|
|
call fp_optimize
|
|
mov edi,fp_value
|
|
push ecx
|
|
mov ecx,10
|
|
call fp_mul
|
|
pop ecx
|
|
mov ebx,fp_value+16
|
|
call fp_add
|
|
loop fp_before_dot
|
|
fp_dot:
|
|
mov edi,fp_value+16
|
|
xor edx,edx
|
|
mov [edi],edx
|
|
mov [edi+4],edx
|
|
mov byte [edi+7],80h
|
|
mov [edi+8],edx
|
|
mov dword [edi+12],edx
|
|
dec ecx
|
|
jz fp_done
|
|
fp_after_dot:
|
|
lods byte [esi]
|
|
cmp al,'E'
|
|
je fp_exponent
|
|
cmp al,'e'
|
|
je fp_exponent
|
|
cmp al,'F'
|
|
je fp_done
|
|
cmp al,'f'
|
|
je fp_done
|
|
inc [fp_format]
|
|
cmp [fp_format],80h
|
|
jne fp_counter_ok
|
|
mov [fp_format],7Fh
|
|
fp_counter_ok:
|
|
dec esi
|
|
mov edi,fp_value+16
|
|
push ecx
|
|
mov ecx,10
|
|
call fp_div
|
|
push dword [edi]
|
|
push dword [edi+4]
|
|
push dword [edi+8]
|
|
push dword [edi+12]
|
|
lods byte [esi]
|
|
sub al,30h
|
|
movzx ecx,al
|
|
call fp_mul
|
|
mov ebx,edi
|
|
mov edi,fp_value
|
|
call fp_add
|
|
mov edi,fp_value+16
|
|
pop dword [edi+12]
|
|
pop dword [edi+8]
|
|
pop dword [edi+4]
|
|
pop dword [edi]
|
|
pop ecx
|
|
dec ecx
|
|
jnz fp_after_dot
|
|
jmp fp_done
|
|
fp_exponent:
|
|
or [fp_format],80h
|
|
xor edx,edx
|
|
xor ebp,ebp
|
|
dec ecx
|
|
jnz get_exponent
|
|
cmp byte [esi],'+'
|
|
je fp_exponent_sign
|
|
cmp byte [esi],'-'
|
|
jne fp_done
|
|
not ebp
|
|
fp_exponent_sign:
|
|
add esi,2
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
get_exponent:
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
sub al,30h
|
|
cmp al,10
|
|
jae exponent_ok
|
|
imul edx,10
|
|
cmp edx,8000h
|
|
jae value_out_of_range
|
|
add edx,eax
|
|
loop get_exponent
|
|
exponent_ok:
|
|
mov edi,fp_value
|
|
or edx,edx
|
|
jz fp_done
|
|
mov ecx,edx
|
|
or ebp,ebp
|
|
jnz fp_negative_power
|
|
fp_power:
|
|
push ecx
|
|
mov ecx,10
|
|
call fp_mul
|
|
pop ecx
|
|
loop fp_power
|
|
jmp fp_done
|
|
fp_negative_power:
|
|
push ecx
|
|
mov ecx,10
|
|
call fp_div
|
|
pop ecx
|
|
loop fp_negative_power
|
|
fp_done:
|
|
mov edi,fp_value
|
|
mov al,[fp_format]
|
|
mov [edi+10],al
|
|
mov al,[fp_sign]
|
|
mov [edi+11],al
|
|
test byte [edi+15],80h
|
|
jz fp_ok
|
|
add dword [edi],1
|
|
adc dword [edi+4],0
|
|
jnc fp_ok
|
|
mov eax,[edi+4]
|
|
shrd [edi],eax,1
|
|
shr eax,1
|
|
or eax,80000000h
|
|
mov [edi+4],eax
|
|
inc word [edi+8]
|
|
fp_ok:
|
|
pop edi
|
|
clc
|
|
ret
|
|
fp_mul:
|
|
or ecx,ecx
|
|
jz fp_zero
|
|
mov eax,[edi+12]
|
|
mul ecx
|
|
mov [edi+12],eax
|
|
mov ebx,edx
|
|
mov eax,[edi]
|
|
mul ecx
|
|
add eax,ebx
|
|
adc edx,0
|
|
mov [edi],eax
|
|
mov ebx,edx
|
|
mov eax,[edi+4]
|
|
mul ecx
|
|
add eax,ebx
|
|
adc edx,0
|
|
mov [edi+4],eax
|
|
.loop:
|
|
or edx,edx
|
|
jz .done
|
|
mov eax,[edi]
|
|
shrd [edi+12],eax,1
|
|
mov eax,[edi+4]
|
|
shrd [edi],eax,1
|
|
shrd eax,edx,1
|
|
mov [edi+4],eax
|
|
shr edx,1
|
|
inc dword [edi+8]
|
|
cmp dword [edi+8],8000h
|
|
jge value_out_of_range
|
|
jmp .loop
|
|
.done:
|
|
ret
|
|
fp_div:
|
|
mov eax,[edi+4]
|
|
xor edx,edx
|
|
div ecx
|
|
mov [edi+4],eax
|
|
mov eax,[edi]
|
|
div ecx
|
|
mov [edi],eax
|
|
mov eax,[edi+12]
|
|
div ecx
|
|
mov [edi+12],eax
|
|
mov ebx,eax
|
|
or ebx,[edi]
|
|
or ebx,[edi+4]
|
|
jz fp_zero
|
|
.loop:
|
|
test byte [edi+7],80h
|
|
jnz .exp_ok
|
|
mov eax,[edi]
|
|
shld [edi+4],eax,1
|
|
mov eax,[edi+12]
|
|
shld [edi],eax,1
|
|
add eax,eax
|
|
mov [edi+12],eax
|
|
dec dword [edi+8]
|
|
add edx,edx
|
|
jmp .loop
|
|
.exp_ok:
|
|
mov eax,edx
|
|
xor edx,edx
|
|
div ecx
|
|
add [edi+12],eax
|
|
adc dword [edi],0
|
|
adc dword [edi+4],0
|
|
jnc .done
|
|
mov eax,[edi+4]
|
|
mov ebx,[edi]
|
|
shrd [edi],eax,1
|
|
shrd [edi+12],ebx,1
|
|
shr eax,1
|
|
or eax,80000000h
|
|
mov [edi+4],eax
|
|
inc dword [edi+8]
|
|
.done:
|
|
ret
|
|
fp_add:
|
|
cmp dword [ebx+8],8000h
|
|
je .done
|
|
cmp dword [edi+8],8000h
|
|
je .copy
|
|
mov eax,[ebx+8]
|
|
cmp eax,[edi+8]
|
|
jge .exp_ok
|
|
mov eax,[edi+8]
|
|
.exp_ok:
|
|
call .change_exp
|
|
xchg ebx,edi
|
|
call .change_exp
|
|
xchg ebx,edi
|
|
mov edx,[ebx+12]
|
|
mov eax,[ebx]
|
|
mov ebx,[ebx+4]
|
|
add [edi+12],edx
|
|
adc [edi],eax
|
|
adc [edi+4],ebx
|
|
jnc .done
|
|
mov eax,[edi]
|
|
shrd [edi+12],eax,1
|
|
mov eax,[edi+4]
|
|
shrd [edi],eax,1
|
|
shr eax,1
|
|
or eax,80000000h
|
|
mov [edi+4],eax
|
|
inc dword [edi+8]
|
|
.done:
|
|
ret
|
|
.copy:
|
|
mov eax,[ebx]
|
|
mov [edi],eax
|
|
mov eax,[ebx+4]
|
|
mov [edi+4],eax
|
|
mov eax,[ebx+8]
|
|
mov [edi+8],eax
|
|
mov eax,[ebx+12]
|
|
mov [edi+12],eax
|
|
ret
|
|
.change_exp:
|
|
push ecx
|
|
mov ecx,eax
|
|
sub ecx,[ebx+8]
|
|
mov edx,[ebx+4]
|
|
jecxz .exp_done
|
|
.exp_loop:
|
|
mov ebp,[ebx]
|
|
shrd [ebx+12],ebp,1
|
|
shrd [ebx],edx,1
|
|
shr edx,1
|
|
inc dword [ebx+8]
|
|
loop .exp_loop
|
|
.exp_done:
|
|
mov [ebx+4],edx
|
|
pop ecx
|
|
ret
|
|
fp_optimize:
|
|
mov eax,[edi]
|
|
mov ebp,[edi+4]
|
|
or ebp,[edi]
|
|
or ebp,[edi+12]
|
|
jz fp_zero
|
|
.loop:
|
|
test byte [edi+7],80h
|
|
jnz .done
|
|
shld [edi+4],eax,1
|
|
mov ebp,[edi+12]
|
|
shld eax,ebp,1
|
|
mov [edi],eax
|
|
shl dword [edi+12],1
|
|
dec dword [edi+8]
|
|
jmp .loop
|
|
.done:
|
|
ret
|
|
fp_zero:
|
|
mov dword [edi+8],8000h
|
|
ret
|
|
|
|
preevaluate_logical_expression:
|
|
xor al,al
|
|
preevaluate_embedded_logical_expression:
|
|
mov [logical_value_wrapping],al
|
|
push edi
|
|
call preevaluate_logical_value
|
|
preevaluation_loop:
|
|
cmp al,0FFh
|
|
je invalid_logical_expression
|
|
mov dl,[esi]
|
|
inc esi
|
|
cmp dl,'|'
|
|
je preevaluate_or
|
|
cmp dl,'&'
|
|
je preevaluate_and
|
|
cmp dl,92h
|
|
je preevaluation_done
|
|
or dl,dl
|
|
jnz invalid_logical_expression
|
|
preevaluation_done:
|
|
pop edx
|
|
dec esi
|
|
ret
|
|
preevaluate_or:
|
|
cmp al,'1'
|
|
je quick_true
|
|
cmp al,'0'
|
|
je leave_only_following
|
|
push edi
|
|
mov al,dl
|
|
stos byte [edi]
|
|
call preevaluate_logical_value
|
|
pop ebx
|
|
cmp al,'0'
|
|
je leave_only_preceding
|
|
cmp al,'1'
|
|
jne preevaluation_loop
|
|
stos byte [edi]
|
|
xor al,al
|
|
jmp preevaluation_loop
|
|
preevaluate_and:
|
|
cmp al,'0'
|
|
je quick_false
|
|
cmp al,'1'
|
|
je leave_only_following
|
|
push edi
|
|
mov al,dl
|
|
stos byte [edi]
|
|
call preevaluate_logical_value
|
|
pop ebx
|
|
cmp al,'1'
|
|
je leave_only_preceding
|
|
cmp al,'0'
|
|
jne preevaluation_loop
|
|
stos byte [edi]
|
|
xor al,al
|
|
jmp preevaluation_loop
|
|
leave_only_following:
|
|
mov edi,[esp]
|
|
call preevaluate_logical_value
|
|
jmp preevaluation_loop
|
|
leave_only_preceding:
|
|
mov edi,ebx
|
|
xor al,al
|
|
jmp preevaluation_loop
|
|
quick_true:
|
|
call skip_logical_value
|
|
jc invalid_logical_expression
|
|
mov edi,[esp]
|
|
mov al,'1'
|
|
jmp preevaluation_loop
|
|
quick_false:
|
|
call skip_logical_value
|
|
jc invalid_logical_expression
|
|
mov edi,[esp]
|
|
mov al,'0'
|
|
jmp preevaluation_loop
|
|
invalid_logical_expression:
|
|
pop edi
|
|
mov esi,edi
|
|
mov al,0FFh
|
|
stos byte [edi]
|
|
ret
|
|
skip_logical_value:
|
|
cmp byte [esi],'~'
|
|
jne negation_skipped
|
|
inc esi
|
|
jmp skip_logical_value
|
|
negation_skipped:
|
|
mov al,[esi]
|
|
cmp al,91h
|
|
jne skip_simple_logical_value
|
|
inc esi
|
|
xchg al,[logical_value_wrapping]
|
|
push eax
|
|
skip_logical_expression:
|
|
call skip_logical_value
|
|
lods byte [esi]
|
|
or al,al
|
|
jz wrongly_structured_logical_expression
|
|
cmp al,0Fh
|
|
je wrongly_structured_logical_expression
|
|
cmp al,'|'
|
|
je skip_logical_expression
|
|
cmp al,'&'
|
|
je skip_logical_expression
|
|
cmp al,92h
|
|
jne wrongly_structured_logical_expression
|
|
pop eax
|
|
mov [logical_value_wrapping],al
|
|
logical_value_skipped:
|
|
clc
|
|
ret
|
|
wrongly_structured_logical_expression:
|
|
pop eax
|
|
stc
|
|
ret
|
|
skip_simple_logical_value:
|
|
mov [logical_value_parentheses],0
|
|
find_simple_logical_value_end:
|
|
mov al,[esi]
|
|
or al,al
|
|
jz logical_value_skipped
|
|
cmp al,0Fh
|
|
je logical_value_skipped
|
|
cmp al,'|'
|
|
je logical_value_skipped
|
|
cmp al,'&'
|
|
je logical_value_skipped
|
|
cmp al,91h
|
|
je skip_logical_value_internal_parenthesis
|
|
cmp al,92h
|
|
jne skip_logical_value_symbol
|
|
sub [logical_value_parentheses],1
|
|
jnc skip_logical_value_symbol
|
|
cmp [logical_value_wrapping],91h
|
|
jne skip_logical_value_symbol
|
|
jmp logical_value_skipped
|
|
skip_logical_value_internal_parenthesis:
|
|
inc [logical_value_parentheses]
|
|
skip_logical_value_symbol:
|
|
call skip_symbol
|
|
jmp find_simple_logical_value_end
|
|
preevaluate_logical_value:
|
|
mov ebp,edi
|
|
preevaluate_negation:
|
|
cmp byte [esi],'~'
|
|
jne preevaluate_negation_ok
|
|
movs byte [edi],[esi]
|
|
jmp preevaluate_negation
|
|
preevaluate_negation_ok:
|
|
mov ebx,esi
|
|
cmp byte [esi],91h
|
|
jne preevaluate_simple_logical_value
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
push ebp
|
|
mov dl,[logical_value_wrapping]
|
|
push edx
|
|
call preevaluate_embedded_logical_expression
|
|
pop edx
|
|
mov [logical_value_wrapping],dl
|
|
pop ebp
|
|
cmp al,0FFh
|
|
je invalid_logical_value
|
|
cmp byte [esi],92h
|
|
jne invalid_logical_value
|
|
or al,al
|
|
jnz preevaluated_expression_value
|
|
movs byte [edi],[esi]
|
|
ret
|
|
preevaluated_expression_value:
|
|
inc esi
|
|
lea edx,[edi-1]
|
|
sub edx,ebp
|
|
test edx,1
|
|
jz expression_negation_ok
|
|
xor al,1
|
|
expression_negation_ok:
|
|
mov edi,ebp
|
|
ret
|
|
invalid_logical_value:
|
|
mov edi,ebp
|
|
mov al,0FFh
|
|
ret
|
|
preevaluate_simple_logical_value:
|
|
xor edx,edx
|
|
mov [logical_value_parentheses],edx
|
|
find_logical_value_boundaries:
|
|
mov al,[esi]
|
|
or al,al
|
|
jz logical_value_boundaries_found
|
|
cmp al,91h
|
|
je logical_value_internal_parentheses
|
|
cmp al,92h
|
|
je logical_value_boundaries_parenthesis_close
|
|
cmp al,'|'
|
|
je logical_value_boundaries_found
|
|
cmp al,'&'
|
|
je logical_value_boundaries_found
|
|
or edx,edx
|
|
jnz next_symbol_in_logical_value
|
|
cmp al,0F0h
|
|
je preevaluable_logical_operator
|
|
cmp al,0F7h
|
|
je preevaluable_logical_operator
|
|
cmp al,0F6h
|
|
jne next_symbol_in_logical_value
|
|
preevaluable_logical_operator:
|
|
mov edx,esi
|
|
next_symbol_in_logical_value:
|
|
call skip_symbol
|
|
jmp find_logical_value_boundaries
|
|
logical_value_internal_parentheses:
|
|
inc [logical_value_parentheses]
|
|
jmp next_symbol_in_logical_value
|
|
logical_value_boundaries_parenthesis_close:
|
|
sub [logical_value_parentheses],1
|
|
jnc next_symbol_in_logical_value
|
|
cmp [logical_value_wrapping],91h
|
|
jne next_symbol_in_logical_value
|
|
logical_value_boundaries_found:
|
|
or edx,edx
|
|
jz non_preevaluable_logical_value
|
|
mov al,[edx]
|
|
cmp al,0F0h
|
|
je compare_symbols
|
|
cmp al,0F7h
|
|
je compare_symbol_types
|
|
cmp al,0F6h
|
|
je scan_symbols_list
|
|
non_preevaluable_logical_value:
|
|
mov ecx,esi
|
|
mov esi,ebx
|
|
sub ecx,esi
|
|
jz invalid_logical_value
|
|
cmp esi,edi
|
|
je leave_logical_value_intact
|
|
rep movs byte [edi],[esi]
|
|
xor al,al
|
|
ret
|
|
leave_logical_value_intact:
|
|
add edi,ecx
|
|
add esi,ecx
|
|
xor al,al
|
|
ret
|
|
compare_symbols:
|
|
lea ecx,[esi-1]
|
|
sub ecx,edx
|
|
mov eax,edx
|
|
sub eax,ebx
|
|
cmp ecx,eax
|
|
jne preevaluated_false
|
|
push esi edi
|
|
mov esi,ebx
|
|
lea edi,[edx+1]
|
|
repe cmps byte [esi],[edi]
|
|
pop edi esi
|
|
je preevaluated_true
|
|
preevaluated_false:
|
|
mov eax,edi
|
|
sub eax,ebp
|
|
test eax,1
|
|
jnz store_true
|
|
store_false:
|
|
mov edi,ebp
|
|
mov al,'0'
|
|
ret
|
|
preevaluated_true:
|
|
mov eax,edi
|
|
sub eax,ebp
|
|
test eax,1
|
|
jnz store_false
|
|
store_true:
|
|
mov edi,ebp
|
|
mov al,'1'
|
|
ret
|
|
compare_symbol_types:
|
|
push esi
|
|
lea esi,[edx+1]
|
|
type_comparison:
|
|
cmp esi,[esp]
|
|
je types_compared
|
|
mov al,[esi]
|
|
cmp al,[ebx]
|
|
jne different_type
|
|
cmp al,'('
|
|
jne equal_type
|
|
mov al,[esi+1]
|
|
mov ah,[ebx+1]
|
|
cmp al,ah
|
|
je equal_type
|
|
or al,al
|
|
jz different_type
|
|
or ah,ah
|
|
jz different_type
|
|
cmp al,'.'
|
|
je different_type
|
|
cmp ah,'.'
|
|
je different_type
|
|
equal_type:
|
|
call skip_symbol
|
|
xchg esi,ebx
|
|
call skip_symbol
|
|
xchg esi,ebx
|
|
jmp type_comparison
|
|
types_compared:
|
|
pop esi
|
|
cmp byte [ebx],0F7h
|
|
jne preevaluated_false
|
|
jmp preevaluated_true
|
|
different_type:
|
|
pop esi
|
|
jmp preevaluated_false
|
|
scan_symbols_list:
|
|
push edi esi
|
|
lea esi,[edx+1]
|
|
sub edx,ebx
|
|
lods byte [esi]
|
|
cmp al,'<'
|
|
jne invalid_symbols_list
|
|
get_next_from_list:
|
|
mov edi,esi
|
|
get_from_list:
|
|
cmp byte [esi],','
|
|
je compare_in_list
|
|
cmp byte [esi],'>'
|
|
je compare_in_list
|
|
cmp esi,[esp]
|
|
jae invalid_symbols_list
|
|
call skip_symbol
|
|
jmp get_from_list
|
|
compare_in_list:
|
|
mov ecx,esi
|
|
sub ecx,edi
|
|
cmp ecx,edx
|
|
jne not_equal_length_in_list
|
|
mov esi,ebx
|
|
repe cmps byte [esi],[edi]
|
|
mov esi,edi
|
|
jne not_equal_in_list
|
|
skip_rest_of_list:
|
|
cmp byte [esi],'>'
|
|
je check_list_end
|
|
cmp esi,[esp]
|
|
jae invalid_symbols_list
|
|
call skip_symbol
|
|
jmp skip_rest_of_list
|
|
check_list_end:
|
|
inc esi
|
|
cmp esi,[esp]
|
|
jne invalid_symbols_list
|
|
pop esi edi
|
|
jmp preevaluated_true
|
|
not_equal_in_list:
|
|
add esi,ecx
|
|
not_equal_length_in_list:
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je get_next_from_list
|
|
cmp esi,[esp]
|
|
jne invalid_symbols_list
|
|
pop esi edi
|
|
jmp preevaluated_false
|
|
invalid_symbols_list:
|
|
pop esi edi
|
|
jmp invalid_logical_value
|