905b52e8ee
fasm 1.69.06 in trunk git-svn-id: svn://kolibrios.org@1189 a494cfbc-eb01-0410-851d-a64ba20cac60
2908 lines
50 KiB
PHP
2908 lines
50 KiB
PHP
|
|
; flat assembler core
|
|
; Copyright (c) 1999-2009, 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
|
|
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-10h]
|
|
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,100h
|
|
jc stack_overflow
|
|
cmp eax,[stack_limit]
|
|
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,')'
|
|
jne invalid_expression
|
|
ret
|
|
symbol_value:
|
|
cmp [source_start],0
|
|
je preprocessor_value
|
|
push edi
|
|
mov edi,address_registers
|
|
call get_operator
|
|
or al,al
|
|
jnz register_value
|
|
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 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
|
|
push esi
|
|
mov esi,[edx+8]
|
|
push [current_offset]
|
|
call convert_expression
|
|
pop [current_offset]
|
|
pop esi
|
|
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,'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
|
|
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
|
|
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
|
|
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:
|
|
or ebp,-1
|
|
inc esi
|
|
jmp get_dec_digit
|
|
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
|
|
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,'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
|
|
sub al,30h
|
|
cmp al,7
|
|
ja bad_number
|
|
oct_digit_ok:
|
|
xor edx,edx
|
|
mov cl,bl
|
|
dec esi
|
|
cmp bl,64
|
|
jae oct_out_of_range
|
|
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
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je fp_value_start
|
|
cmp al,'-'
|
|
je fp_sign_ok
|
|
cmp al,'+'
|
|
jne not_fp_value
|
|
fp_sign_ok:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne not_fp_value
|
|
fp_value_start:
|
|
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
|
|
lods byte [esi]
|
|
mov [fp_sign],0
|
|
cmp al,1Ah
|
|
je fp_get
|
|
inc esi
|
|
cmp al,'+'
|
|
je fp_get
|
|
mov [fp_sign],1
|
|
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
|
|
|
|
calculate_expression:
|
|
mov [current_offset],edi
|
|
mov [value_undefined],0
|
|
cmp byte [esi],0
|
|
je get_string_value
|
|
cmp byte [esi],'.'
|
|
je convert_fp
|
|
calculation_loop:
|
|
lods byte [esi]
|
|
cmp al,1
|
|
je get_byte_number
|
|
cmp al,2
|
|
je get_word_number
|
|
cmp al,4
|
|
je get_dword_number
|
|
cmp al,8
|
|
je get_qword_number
|
|
cmp al,0Fh
|
|
je value_out_of_range
|
|
cmp al,10h
|
|
je get_register
|
|
cmp al,11h
|
|
je get_label
|
|
cmp al,')'
|
|
je expression_calculated
|
|
cmp al,']'
|
|
je expression_calculated
|
|
cmp al,'!'
|
|
je invalid_expression
|
|
sub edi,14h
|
|
mov ebx,edi
|
|
sub ebx,14h
|
|
cmp al,0E0h
|
|
je calculate_rva
|
|
cmp al,0E1h
|
|
je calculate_plt
|
|
cmp al,0D0h
|
|
je calculate_not
|
|
cmp al,083h
|
|
je calculate_neg
|
|
mov dx,[ebx+8]
|
|
or dx,[edi+8]
|
|
cmp al,80h
|
|
je calculate_add
|
|
cmp al,81h
|
|
je calculate_sub
|
|
mov ah,[ebx+12]
|
|
or ah,[edi+12]
|
|
jz absolute_values_calculation
|
|
cmp [error_line],0
|
|
jne absolute_values_calculation
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
absolute_values_calculation:
|
|
cmp al,90h
|
|
je calculate_mul
|
|
cmp al,91h
|
|
je calculate_div
|
|
or dx,dx
|
|
jnz invalid_expression
|
|
cmp al,0A0h
|
|
je calculate_mod
|
|
cmp al,0B0h
|
|
je calculate_and
|
|
cmp al,0B1h
|
|
je calculate_or
|
|
cmp al,0B2h
|
|
je calculate_xor
|
|
cmp al,0C0h
|
|
je calculate_shl
|
|
cmp al,0C1h
|
|
je calculate_shr
|
|
jmp invalid_expression
|
|
expression_calculated:
|
|
sub edi,14h
|
|
cmp [value_undefined],0
|
|
je expression_value_ok
|
|
xor eax,eax
|
|
mov [edi],eax
|
|
mov [edi+4],eax
|
|
mov [edi+12],al
|
|
expression_value_ok:
|
|
ret
|
|
get_byte_number:
|
|
xor eax,eax
|
|
lods byte [esi]
|
|
stos dword [edi]
|
|
xor al,al
|
|
stos dword [edi]
|
|
got_number:
|
|
mov word [edi-8+8],0
|
|
mov byte [edi-8+12],0
|
|
mov dword [edi-8+16],0
|
|
add edi,0Ch
|
|
jmp calculation_loop
|
|
get_word_number:
|
|
xor eax,eax
|
|
lods word [esi]
|
|
stos dword [edi]
|
|
xor ax,ax
|
|
stos dword [edi]
|
|
jmp got_number
|
|
get_dword_number:
|
|
movs dword [edi],[esi]
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
jmp got_number
|
|
get_qword_number:
|
|
movs dword [edi],[esi]
|
|
movs dword [edi],[esi]
|
|
jmp got_number
|
|
get_register:
|
|
mov byte [edi+9],0
|
|
mov byte [edi+12],0
|
|
lods byte [esi]
|
|
mov [edi+8],al
|
|
mov byte [edi+10],1
|
|
xor eax,eax
|
|
mov [edi+16],eax
|
|
stos dword [edi]
|
|
stos dword [edi]
|
|
add edi,0Ch
|
|
jmp calculation_loop
|
|
get_label:
|
|
xor eax,eax
|
|
mov [edi+8],eax
|
|
mov [edi+12],al
|
|
mov [edi+20],eax
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb predefined_label
|
|
je reserved_word_used_as_symbol
|
|
mov ebx,eax
|
|
mov ax,[current_pass]
|
|
mov [ebx+18],ax
|
|
or byte [ebx+8],8
|
|
test byte [ebx+8],1
|
|
jz label_undefined
|
|
cmp ax,[ebx+16]
|
|
je label_defined
|
|
test byte [ebx+8],4
|
|
jnz label_out_of_scope
|
|
test byte [ebx+9],1
|
|
jz label_defined
|
|
mov eax,[ebx]
|
|
sub eax,dword [adjustment]
|
|
stos dword [edi]
|
|
mov eax,[ebx+4]
|
|
sbb eax,dword [adjustment+4]
|
|
stos dword [edi]
|
|
mov eax,dword [adjustment]
|
|
or eax,dword [adjustment+4]
|
|
jz got_label
|
|
or [next_pass_needed],-1
|
|
jmp got_label
|
|
label_defined:
|
|
mov eax,[ebx]
|
|
stos dword [edi]
|
|
mov eax,[ebx+4]
|
|
stos dword [edi]
|
|
got_label:
|
|
mov al,[ebx+11]
|
|
mov [edi-8+12],al
|
|
mov eax,[ebx+12]
|
|
mov [edi-8+8],eax
|
|
mov eax,[ebx+20]
|
|
mov [edi-8+16],eax
|
|
add edi,0Ch
|
|
mov al,[ebx+10]
|
|
or al,al
|
|
jz calculation_loop
|
|
cmp [size_override],-1
|
|
je calculation_loop
|
|
cmp [size_override],0
|
|
je check_size
|
|
cmp [operand_size],0
|
|
jne calculation_loop
|
|
mov [operand_size],al
|
|
jmp calculation_loop
|
|
check_size:
|
|
xchg [operand_size],al
|
|
or al,al
|
|
jz calculation_loop
|
|
cmp al,[operand_size]
|
|
jne operand_sizes_do_not_match
|
|
jmp calculation_loop
|
|
current_offset_label:
|
|
mov eax,[current_offset]
|
|
make_current_offset_label:
|
|
xor edx,edx
|
|
sub eax,dword [org_origin]
|
|
sbb edx,dword [org_origin+4]
|
|
stos dword [edi]
|
|
mov eax,edx
|
|
stos dword [edi]
|
|
mov eax,[org_registers]
|
|
stos dword [edi]
|
|
mov al,[labels_type]
|
|
mov [edi-12+12],al
|
|
mov eax,[org_symbol]
|
|
mov [edi-12+16],eax
|
|
add edi,8
|
|
jmp calculation_loop
|
|
org_origin_label:
|
|
mov eax,[org_start]
|
|
jmp make_current_offset_label
|
|
counter_label:
|
|
mov eax,[counter]
|
|
make_dword_label_value:
|
|
stos dword [edi]
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
add edi,0Ch
|
|
jmp calculation_loop
|
|
timestamp_label:
|
|
call make_timestamp
|
|
make_qword_label_value:
|
|
stos dword [edi]
|
|
mov eax,edx
|
|
stos dword [edi]
|
|
add edi,0Ch
|
|
jmp calculation_loop
|
|
predefined_label:
|
|
or eax,eax
|
|
jz current_offset_label
|
|
cmp eax,1
|
|
je counter_label
|
|
cmp eax,2
|
|
je timestamp_label
|
|
cmp eax,3
|
|
je org_origin_label
|
|
mov edx,invalid_value
|
|
jmp error_undefined
|
|
label_out_of_scope:
|
|
mov edx,symbol_out_of_scope
|
|
mov eax,[ebx+24]
|
|
cmp [error_line],0
|
|
jne error_undefined
|
|
mov [error_info],eax
|
|
jmp error_undefined
|
|
label_undefined:
|
|
mov edx,undefined_symbol
|
|
cmp [error_line],0
|
|
jne error_undefined
|
|
mov eax,[ebx+24]
|
|
mov [error_info],eax
|
|
error_undefined:
|
|
cmp [current_pass],1
|
|
ja undefined_value
|
|
force_next_pass:
|
|
or [next_pass_needed],-1
|
|
undefined_value:
|
|
mov byte [edi+12],0
|
|
or [value_undefined],-1
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
stos dword [edi]
|
|
add edi,0Ch
|
|
cmp [error_line],0
|
|
jne calculation_loop
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],edx
|
|
jmp calculation_loop
|
|
calculate_add:
|
|
mov ecx,[ebx+16]
|
|
cmp byte [edi+12],0
|
|
je add_values
|
|
mov ecx,[edi+16]
|
|
cmp byte [ebx+12],0
|
|
je add_values
|
|
cmp [error_line],0
|
|
jne add_values
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
add_values:
|
|
mov al,[edi+12]
|
|
or [ebx+12],al
|
|
mov [ebx+16],ecx
|
|
mov eax,[edi]
|
|
add [ebx],eax
|
|
mov eax,[edi+4]
|
|
adc [ebx+4],eax
|
|
or dx,dx
|
|
jz calculation_loop
|
|
push esi
|
|
mov esi,ebx
|
|
lea ebx,[edi+10]
|
|
mov cl,[edi+8]
|
|
call add_register
|
|
lea ebx,[edi+11]
|
|
mov cl,[edi+9]
|
|
call add_register
|
|
pop esi
|
|
jmp calculation_loop
|
|
add_register:
|
|
or cl,cl
|
|
jz add_register_done
|
|
add_register_start:
|
|
cmp [esi+8],cl
|
|
jne add_in_second_slot
|
|
mov al,[ebx]
|
|
add [esi+10],al
|
|
jnz add_register_done
|
|
mov byte [esi+8],0
|
|
ret
|
|
add_in_second_slot:
|
|
cmp [esi+9],cl
|
|
jne create_in_first_slot
|
|
mov al,[ebx]
|
|
add [esi+11],al
|
|
jnz add_register_done
|
|
mov byte [esi+9],0
|
|
ret
|
|
create_in_first_slot:
|
|
cmp byte [esi+8],0
|
|
jne create_in_second_slot
|
|
mov [esi+8],cl
|
|
mov al,[ebx]
|
|
mov [esi+10],al
|
|
ret
|
|
create_in_second_slot:
|
|
cmp byte [esi+9],0
|
|
jne invalid_expression
|
|
mov [esi+9],cl
|
|
mov al,[ebx]
|
|
mov [esi+11],al
|
|
add_register_done:
|
|
ret
|
|
calculate_sub:
|
|
xor ah,ah
|
|
mov ah,[ebx+12]
|
|
mov al,[edi+12]
|
|
or al,al
|
|
jz sub_values
|
|
cmp al,ah
|
|
jne invalid_sub
|
|
xor ah,ah
|
|
mov ecx,[edi+16]
|
|
cmp ecx,[ebx+16]
|
|
jne invalid_sub
|
|
sub_values:
|
|
mov [ebx+12],ah
|
|
mov eax,[edi]
|
|
sub [ebx],eax
|
|
mov eax,[edi+4]
|
|
sbb [ebx+4],eax
|
|
or dx,dx
|
|
jz calculation_loop
|
|
push esi
|
|
mov esi,ebx
|
|
lea ebx,[edi+10]
|
|
mov cl,[edi+8]
|
|
call sub_register
|
|
lea ebx,[edi+11]
|
|
mov cl,[edi+9]
|
|
call sub_register
|
|
pop esi
|
|
jmp calculation_loop
|
|
invalid_sub:
|
|
cmp [error_line],0
|
|
jne sub_values
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
jmp sub_values
|
|
sub_register:
|
|
or cl,cl
|
|
jz add_register_done
|
|
neg byte [ebx]
|
|
jmp add_register_start
|
|
calculate_mul:
|
|
or dx,dx
|
|
jz mul_start
|
|
cmp word [ebx+8],0
|
|
jne mul_start
|
|
mov eax,[ebx]
|
|
xchg eax,[edi]
|
|
mov [ebx],eax
|
|
mov eax,[ebx+4]
|
|
xchg eax,[edi+4]
|
|
mov [ebx+4],eax
|
|
mov eax,[ebx+8]
|
|
xchg eax,[edi+8]
|
|
mov [ebx+8],eax
|
|
mov eax,[ebx+12]
|
|
xchg eax,[edi+12]
|
|
mov [ebx+12],eax
|
|
mul_start:
|
|
push esi edx
|
|
mov esi,ebx
|
|
xor bl,bl
|
|
bt dword [esi+4],31
|
|
jnc mul_first_sign_ok
|
|
not dword [esi]
|
|
not dword [esi+4]
|
|
add dword [esi],1
|
|
adc dword [esi+4],0
|
|
not bl
|
|
mul_first_sign_ok:
|
|
bt dword [edi+4],31
|
|
jnc mul_second_sign_ok
|
|
not dword [edi]
|
|
not dword [edi+4]
|
|
add dword [edi],1
|
|
adc dword [edi+4],0
|
|
not bl
|
|
mul_second_sign_ok:
|
|
cmp dword [esi+4],0
|
|
jz mul_numbers
|
|
cmp dword [edi+4],0
|
|
jnz value_out_of_range
|
|
mul_numbers:
|
|
mov eax,[esi+4]
|
|
mul dword [edi]
|
|
or edx,edx
|
|
jnz value_out_of_range
|
|
mov ecx,eax
|
|
mov eax,[esi]
|
|
mul dword [edi+4]
|
|
or edx,edx
|
|
jnz value_out_of_range
|
|
add ecx,eax
|
|
jc value_out_of_range
|
|
mov eax,[esi]
|
|
mul dword [edi]
|
|
add edx,ecx
|
|
jc value_out_of_range
|
|
test edx,1 shl 31
|
|
jnz value_out_of_range
|
|
mov [esi],eax
|
|
mov [esi+4],edx
|
|
or bl,bl
|
|
jz mul_ok
|
|
not dword [esi]
|
|
not dword [esi+4]
|
|
add dword [esi],1
|
|
adc dword [esi+4],0
|
|
mul_ok:
|
|
pop edx
|
|
or dx,dx
|
|
jz mul_calculated
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
cmp byte [esi+8],0
|
|
je mul_first_register_ok
|
|
mov al,[edi]
|
|
cbw
|
|
cwde
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne value_out_of_range
|
|
cmp eax,[edi]
|
|
jne value_out_of_range
|
|
imul byte [esi+10]
|
|
mov dl,ah
|
|
cbw
|
|
cmp ah,dl
|
|
jne value_out_of_range
|
|
mov [esi+10],al
|
|
or al,al
|
|
jnz mul_first_register_ok
|
|
mov [esi+8],al
|
|
mul_first_register_ok:
|
|
cmp byte [esi+9],0
|
|
je mul_calculated
|
|
mov al,[edi]
|
|
cbw
|
|
cwde
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne value_out_of_range
|
|
cmp eax,[edi]
|
|
jne value_out_of_range
|
|
imul byte [esi+11]
|
|
mov dl,ah
|
|
cbw
|
|
cmp ah,dl
|
|
jne value_out_of_range
|
|
mov [esi+11],al
|
|
or al,al
|
|
jnz mul_calculated
|
|
mov [esi+9],al
|
|
mul_calculated:
|
|
pop esi
|
|
jmp calculation_loop
|
|
calculate_div:
|
|
push esi edx
|
|
mov esi,ebx
|
|
call div_64
|
|
pop edx
|
|
or dx,dx
|
|
jz div_calculated
|
|
cmp byte [esi+8],0
|
|
je div_first_register_ok
|
|
mov al,[edi]
|
|
cbw
|
|
cwde
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne value_out_of_range
|
|
cmp eax,[edi]
|
|
jne value_out_of_range
|
|
or al,al
|
|
jz value_out_of_range
|
|
mov al,[esi+10]
|
|
cbw
|
|
idiv byte [edi]
|
|
or ah,ah
|
|
jnz invalid_use_of_symbol
|
|
mov [esi+10],al
|
|
div_first_register_ok:
|
|
cmp byte [esi+9],0
|
|
je div_calculated
|
|
mov al,[edi]
|
|
cbw
|
|
cwde
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne value_out_of_range
|
|
cmp eax,[edi]
|
|
jne value_out_of_range
|
|
or al,al
|
|
jz value_out_of_range
|
|
mov al,[esi+11]
|
|
cbw
|
|
idiv byte [edi]
|
|
or ah,ah
|
|
jnz invalid_use_of_symbol
|
|
mov [esi+11],al
|
|
div_calculated:
|
|
pop esi
|
|
jmp calculation_loop
|
|
calculate_mod:
|
|
push esi
|
|
mov esi,ebx
|
|
call div_64
|
|
mov [esi],eax
|
|
mov [esi+4],edx
|
|
pop esi
|
|
jmp calculation_loop
|
|
calculate_and:
|
|
mov eax,[edi]
|
|
and [ebx],eax
|
|
mov eax,[edi+4]
|
|
and [ebx+4],eax
|
|
jmp calculation_loop
|
|
calculate_or:
|
|
mov eax,[edi]
|
|
or [ebx],eax
|
|
mov eax,[edi+4]
|
|
or [ebx+4],eax
|
|
jmp calculation_loop
|
|
calculate_xor:
|
|
mov eax,[edi]
|
|
xor [ebx],eax
|
|
mov eax,[edi+4]
|
|
xor [ebx+4],eax
|
|
jmp calculation_loop
|
|
shr_negative:
|
|
not dword [edi]
|
|
not dword [edi+4]
|
|
add dword [edi],1
|
|
adc dword [edi+4],0
|
|
calculate_shl:
|
|
mov eax,dword [edi+4]
|
|
bt eax,31
|
|
jc shl_negative
|
|
or eax,eax
|
|
jnz zero_value
|
|
mov ecx,[edi]
|
|
cmp ecx,64
|
|
jae zero_value
|
|
cmp ecx,32
|
|
jae shl_high
|
|
mov edx,[ebx+4]
|
|
mov eax,[ebx]
|
|
shld edx,eax,cl
|
|
shl eax,cl
|
|
mov [ebx],eax
|
|
mov [ebx+4],edx
|
|
jmp calculation_loop
|
|
shl_high:
|
|
sub cl,32
|
|
mov eax,[ebx]
|
|
shl eax,cl
|
|
mov [ebx+4],eax
|
|
mov dword [ebx],0
|
|
jmp calculation_loop
|
|
shl_negative:
|
|
not dword [edi]
|
|
not dword [edi+4]
|
|
add dword [edi],1
|
|
adc dword [edi+4],0
|
|
calculate_shr:
|
|
mov eax,dword [edi+4]
|
|
bt eax,31
|
|
jc shr_negative
|
|
or eax,eax
|
|
jnz zero_value
|
|
mov ecx,[edi]
|
|
cmp ecx,64
|
|
jae zero_value
|
|
cmp ecx,32
|
|
jae shr_high
|
|
mov edx,[ebx+4]
|
|
mov eax,[ebx]
|
|
shrd eax,edx,cl
|
|
shr edx,cl
|
|
mov [ebx],eax
|
|
mov [ebx+4],edx
|
|
jmp calculation_loop
|
|
shr_high:
|
|
sub cl,32
|
|
mov eax,[ebx+4]
|
|
shr eax,cl
|
|
mov [ebx],eax
|
|
mov dword [ebx+4],0
|
|
jmp calculation_loop
|
|
zero_value:
|
|
mov dword [ebx],0
|
|
mov dword [ebx+4],0
|
|
jmp calculation_loop
|
|
calculate_not:
|
|
cmp word [edi+8],0
|
|
jne invalid_expression
|
|
cmp byte [edi+12],0
|
|
je not_ok
|
|
cmp [error_line],0
|
|
jne not_ok
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
not_ok:
|
|
cmp [value_size],1
|
|
je not_byte
|
|
cmp [value_size],2
|
|
je not_word
|
|
cmp [value_size],4
|
|
je not_dword
|
|
cmp [value_size],6
|
|
je not_pword
|
|
not_qword:
|
|
not dword [edi]
|
|
not dword [edi+4]
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
not_byte:
|
|
cmp dword [edi+4],0
|
|
jne not_qword
|
|
cmp word [edi+2],0
|
|
jne not_qword
|
|
cmp byte [edi+1],0
|
|
jne not_qword
|
|
not byte [edi]
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
not_word:
|
|
cmp dword [edi+4],0
|
|
jne not_qword
|
|
cmp word [edi+2],0
|
|
jne not_qword
|
|
not word [edi]
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
not_dword:
|
|
cmp dword [edi+4],0
|
|
jne not_qword
|
|
not dword [edi]
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
not_pword:
|
|
cmp word [edi+6],0
|
|
jne not_qword
|
|
not dword [edi]
|
|
not word [edi+4]
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
calculate_neg:
|
|
cmp word [edi+8],0
|
|
jne invalid_expression
|
|
cmp byte [edi+12],0
|
|
je neg_ok
|
|
cmp [error_line],0
|
|
jne neg_ok
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
neg_ok:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
mov dword [edi],0
|
|
mov dword [edi+4],0
|
|
sub [edi],eax
|
|
sbb [edi+4],edx
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
calculate_rva:
|
|
cmp word [edi+8],0
|
|
jne invalid_expression
|
|
cmp [output_format],5
|
|
je calculate_gotoff
|
|
cmp [output_format],4
|
|
je calculate_coff_rva
|
|
cmp [output_format],3
|
|
jne invalid_expression
|
|
test [format_flags],8
|
|
jnz pe64_rva
|
|
mov al,2
|
|
bt [resolver_flags],0
|
|
jc rva_type_ok
|
|
xor al,al
|
|
rva_type_ok:
|
|
cmp byte [edi+12],al
|
|
je rva_ok
|
|
cmp [error_line],0
|
|
jne rva_ok
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
rva_ok:
|
|
mov byte [edi+12],0
|
|
mov eax,[code_start]
|
|
mov eax,[eax+34h]
|
|
cdq
|
|
sub [edi],eax
|
|
sbb [edi+4],edx
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
pe64_rva:
|
|
mov al,4
|
|
bt [resolver_flags],0
|
|
jc pe64_rva_type_ok
|
|
xor al,al
|
|
pe64_rva_type_ok:
|
|
cmp byte [edi+12],al
|
|
je pe64_rva_ok
|
|
cmp [error_line],0
|
|
jne pe64_rva_ok
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
pe64_rva_ok:
|
|
mov byte [edi+12],0
|
|
mov eax,[code_start]
|
|
mov edx,[eax+34h]
|
|
mov eax,[eax+30h]
|
|
sub [edi],eax
|
|
sbb [edi+4],edx
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
calculate_gotoff:
|
|
test [format_flags],8+1
|
|
jnz invalid_expression
|
|
calculate_coff_rva:
|
|
mov dl,5
|
|
cmp byte [edi+12],2
|
|
je change_value_type
|
|
incorrect_change_of_value_type:
|
|
cmp [error_line],0
|
|
jne change_value_type
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
change_value_type:
|
|
mov byte [edi+12],dl
|
|
add edi,14h
|
|
jmp calculation_loop
|
|
calculate_plt:
|
|
cmp word [edi+8],0
|
|
jne invalid_expression
|
|
cmp [output_format],5
|
|
jne invalid_expression
|
|
test [format_flags],1
|
|
jnz invalid_expression
|
|
mov dl,6
|
|
mov dh,2
|
|
test [format_flags],8
|
|
jz check_value_for_plt
|
|
mov dh,4
|
|
check_value_for_plt:
|
|
mov eax,[edi]
|
|
or eax,[edi+4]
|
|
jnz incorrect_change_of_value_type
|
|
cmp byte [edi+12],dh
|
|
jne incorrect_change_of_value_type
|
|
mov eax,[edi+16]
|
|
cmp byte [eax],80h
|
|
jne incorrect_change_of_value_type
|
|
jmp change_value_type
|
|
div_64:
|
|
xor ebx,ebx
|
|
cmp dword [edi],0
|
|
jne divider_ok
|
|
cmp dword [edi+4],0
|
|
jne divider_ok
|
|
cmp [next_pass_needed],0
|
|
je value_out_of_range
|
|
jmp div_done
|
|
divider_ok:
|
|
bt dword [esi+4],31
|
|
jnc div_first_sign_ok
|
|
not dword [esi]
|
|
not dword [esi+4]
|
|
add dword [esi],1
|
|
adc dword [esi+4],0
|
|
not bx
|
|
div_first_sign_ok:
|
|
bt dword [edi+4],31
|
|
jnc div_second_sign_ok
|
|
not dword [edi]
|
|
not dword [edi+4]
|
|
add dword [edi],1
|
|
adc dword [edi+4],0
|
|
not bl
|
|
div_second_sign_ok:
|
|
cmp dword [edi+4],0
|
|
jne div_high
|
|
mov ecx,[edi]
|
|
mov eax,[esi+4]
|
|
xor edx,edx
|
|
div ecx
|
|
mov [esi+4],eax
|
|
mov eax,[esi]
|
|
div ecx
|
|
mov [esi],eax
|
|
mov eax,edx
|
|
xor edx,edx
|
|
jmp div_done
|
|
div_high:
|
|
mov eax,[esi+4]
|
|
xor edx,edx
|
|
div dword [edi+4]
|
|
mov ebx,[esi]
|
|
mov [esi],eax
|
|
mov dword [esi+4],0
|
|
mov ecx,edx
|
|
mul dword [edi]
|
|
div_high_loop:
|
|
cmp ecx,edx
|
|
ja div_high_done
|
|
jb div_high_large_correction
|
|
cmp ebx,eax
|
|
jae div_high_done
|
|
div_high_correction:
|
|
dec dword [esi]
|
|
sub eax,[edi]
|
|
sbb edx,[edi+4]
|
|
jnc div_high_loop
|
|
div_high_done:
|
|
sub ebx,eax
|
|
sbb ecx,edx
|
|
mov edx,ecx
|
|
mov eax,ebx
|
|
ret
|
|
div_high_large_correction:
|
|
push eax edx
|
|
mov eax,edx
|
|
sub eax,ecx
|
|
xor edx,edx
|
|
div dword [edi+4]
|
|
shr eax,1
|
|
jz div_high_small_correction
|
|
sub [esi],eax
|
|
push eax
|
|
mul dword [edi+4]
|
|
sub dword [esp+4],eax
|
|
pop eax
|
|
mul dword [edi]
|
|
sub dword [esp+4],eax
|
|
sbb dword [esp],edx
|
|
pop edx eax
|
|
jmp div_high_loop
|
|
div_high_small_correction:
|
|
pop edx eax
|
|
jmp div_high_correction
|
|
div_done:
|
|
or bh,bh
|
|
jz remainder_ok
|
|
not eax
|
|
not edx
|
|
add eax,1
|
|
adc edx,0
|
|
remainder_ok:
|
|
or bl,bl
|
|
jz div_ok
|
|
not dword [esi]
|
|
not dword [esi+4]
|
|
add dword [esi],1
|
|
adc dword [esi+4],0
|
|
div_ok:
|
|
ret
|
|
convert_fp:
|
|
inc esi
|
|
mov word [edi+8],0
|
|
mov byte [edi+12],0
|
|
mov al,[value_size]
|
|
cmp al,4
|
|
je convert_fp_dword
|
|
cmp al,8
|
|
je convert_fp_qword
|
|
jmp invalid_value
|
|
convert_fp_dword:
|
|
xor eax,eax
|
|
cmp word [esi+8],8000h
|
|
je fp_dword_store
|
|
mov bx,[esi+8]
|
|
mov eax,[esi+4]
|
|
shl eax,1
|
|
shr eax,9
|
|
jnc fp_dword_ok
|
|
inc eax
|
|
bt eax,23
|
|
jnc fp_dword_ok
|
|
and eax,1 shl 23 - 1
|
|
inc bx
|
|
shr eax,1
|
|
fp_dword_ok:
|
|
add bx,7Fh
|
|
cmp bx,0FFh
|
|
jge value_out_of_range
|
|
cmp bx,0
|
|
jg fp_dword_exp_ok
|
|
or eax,1 shl 23
|
|
mov cx,bx
|
|
neg cx
|
|
inc cx
|
|
cmp cx,23
|
|
ja value_out_of_range
|
|
xor bx,bx
|
|
shr eax,cl
|
|
jnc fp_dword_exp_ok
|
|
inc eax
|
|
test eax,1 shl 23
|
|
jz fp_dword_exp_ok
|
|
and eax,1 shl 23 - 1
|
|
inc bx
|
|
fp_dword_exp_ok:
|
|
shl ebx,23
|
|
or eax,ebx
|
|
fp_dword_store:
|
|
mov bl,[esi+11]
|
|
shl ebx,31
|
|
or eax,ebx
|
|
mov [edi],eax
|
|
xor eax,eax
|
|
mov [edi+4],eax
|
|
add esi,13
|
|
ret
|
|
convert_fp_qword:
|
|
xor eax,eax
|
|
xor edx,edx
|
|
cmp word [esi+8],8000h
|
|
je fp_qword_store
|
|
mov bx,[esi+8]
|
|
mov eax,[esi]
|
|
mov edx,[esi+4]
|
|
add eax,eax
|
|
adc edx,edx
|
|
mov ecx,edx
|
|
shr edx,12
|
|
shrd eax,ecx,12
|
|
jnc fp_qword_ok
|
|
add eax,1
|
|
adc edx,0
|
|
bt edx,20
|
|
jnc fp_qword_ok
|
|
and edx,1 shl 20 - 1
|
|
inc bx
|
|
shr edx,1
|
|
rcr eax,1
|
|
fp_qword_ok:
|
|
add bx,3FFh
|
|
cmp bx,7FFh
|
|
jge value_out_of_range
|
|
cmp bx,0
|
|
jg fp_qword_exp_ok
|
|
or edx,1 shl 20
|
|
mov cx,bx
|
|
neg cx
|
|
inc cx
|
|
cmp cx,52
|
|
ja value_out_of_range
|
|
cmp cx,32
|
|
jbe fp_qword_small_shift
|
|
sub cx,32
|
|
mov eax,edx
|
|
xor edx,edx
|
|
shr eax,cl
|
|
jmp fp_qword_shift_done
|
|
fp_qword_small_shift:
|
|
mov ebx,edx
|
|
shr edx,cl
|
|
shrd eax,ebx,cl
|
|
fp_qword_shift_done:
|
|
mov bx,0
|
|
jnc fp_qword_exp_ok
|
|
add eax,1
|
|
adc edx,0
|
|
test edx,1 shl 20
|
|
jz fp_qword_exp_ok
|
|
and edx,1 shl 20 - 1
|
|
inc bx
|
|
fp_qword_exp_ok:
|
|
shl ebx,20
|
|
or edx,ebx
|
|
fp_qword_store:
|
|
mov bl,[esi+11]
|
|
shl ebx,31
|
|
or edx,ebx
|
|
mov [edi],eax
|
|
mov [edi+4],edx
|
|
add esi,13
|
|
ret
|
|
get_string_value:
|
|
inc esi
|
|
lods dword [esi]
|
|
mov ecx,eax
|
|
cmp ecx,8
|
|
ja value_out_of_range
|
|
mov edx,edi
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
stos dword [edi]
|
|
mov edi,edx
|
|
rep movs byte [edi],[esi]
|
|
mov edi,edx
|
|
inc esi
|
|
mov word [edi+8],0
|
|
mov byte [edi+12],0
|
|
ret
|
|
|
|
get_byte_value:
|
|
mov [value_size],1
|
|
mov [size_override],-1
|
|
call calculate_expression
|
|
mov eax,[edi+16]
|
|
mov [symbol_identifier],eax
|
|
mov [value_type],0
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
cmp byte [edi+12],0
|
|
je check_byte_value
|
|
cmp [error_line],0
|
|
jne check_byte_value
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
check_byte_value:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
or edx,edx
|
|
jz byte_positive
|
|
cmp edx,-1
|
|
jne range_exceeded
|
|
cmp eax,-80h
|
|
jb range_exceeded
|
|
ret
|
|
byte_positive:
|
|
cmp eax,100h
|
|
jae range_exceeded
|
|
return_byte_value:
|
|
ret
|
|
range_exceeded:
|
|
xor eax,eax
|
|
xor edx,edx
|
|
cmp [error_line],0
|
|
jne return_byte_value
|
|
mov ecx,[current_line]
|
|
mov [error_line],ecx
|
|
mov [error],value_out_of_range
|
|
ret
|
|
get_word_value:
|
|
mov [value_size],2
|
|
mov [size_override],-1
|
|
call calculate_expression
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
mov eax,[edi+16]
|
|
mov [symbol_identifier],eax
|
|
mov al,[edi+12]
|
|
mov [value_type],al
|
|
cmp al,2
|
|
jb check_word_value
|
|
cmp [error_line],0
|
|
jne check_word_value
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
check_word_value:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
or edx,edx
|
|
jz word_positive
|
|
cmp edx,-1
|
|
jne range_exceeded
|
|
cmp eax,-8000h
|
|
jb range_exceeded
|
|
ret
|
|
word_positive:
|
|
cmp eax,10000h
|
|
jae range_exceeded
|
|
ret
|
|
get_dword_value:
|
|
mov [value_size],4
|
|
mov [size_override],-1
|
|
call calculate_expression
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
mov eax,[edi+16]
|
|
mov [symbol_identifier],eax
|
|
mov al,[edi+12]
|
|
mov [value_type],al
|
|
cmp al,4
|
|
jne check_dword_value
|
|
mov [value_type],2
|
|
mov eax,[edi]
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne range_exceeded
|
|
ret
|
|
check_dword_value:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
or edx,edx
|
|
jz dword_positive
|
|
cmp edx,-1
|
|
jne range_exceeded
|
|
bt eax,31
|
|
jnc range_exceeded
|
|
dword_positive:
|
|
ret
|
|
get_pword_value:
|
|
mov [value_size],6
|
|
mov [size_override],-1
|
|
call calculate_expression
|
|
mov eax,[edi+16]
|
|
mov [symbol_identifier],eax
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
mov al,[edi+12]
|
|
mov [value_type],al
|
|
cmp al,4
|
|
jne check_pword_value
|
|
cmp [error_line],0
|
|
jne check_pword_value
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_use_of_symbol
|
|
check_pword_value:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
cmp edx,10000h
|
|
jge range_exceeded
|
|
cmp edx,-8000h
|
|
jl range_exceeded
|
|
ret
|
|
get_qword_value:
|
|
mov [value_size],8
|
|
mov [size_override],-1
|
|
call calculate_expression
|
|
cmp word [edi+8],0
|
|
jne invalid_value
|
|
mov eax,[edi+16]
|
|
mov [symbol_identifier],eax
|
|
mov al,[edi+12]
|
|
mov [value_type],al
|
|
check_qword_value:
|
|
mov eax,[edi]
|
|
mov edx,[edi+4]
|
|
ret
|
|
get_value:
|
|
mov [operand_size],0
|
|
lods byte [esi]
|
|
call get_size_operator
|
|
cmp al,'('
|
|
jne invalid_value
|
|
mov al,[operand_size]
|
|
cmp al,1
|
|
je value_byte
|
|
cmp al,2
|
|
je value_word
|
|
cmp al,4
|
|
je value_dword
|
|
cmp al,6
|
|
je value_pword
|
|
cmp al,8
|
|
je value_qword
|
|
or al,al
|
|
jnz invalid_value
|
|
value_qword:
|
|
call get_qword_value
|
|
ret
|
|
value_pword:
|
|
call get_pword_value
|
|
movzx edx,dx
|
|
ret
|
|
value_dword:
|
|
call get_dword_value
|
|
xor edx,edx
|
|
ret
|
|
value_word:
|
|
call get_word_value
|
|
xor edx,edx
|
|
movzx eax,ax
|
|
ret
|
|
value_byte:
|
|
call get_byte_value
|
|
xor edx,edx
|
|
movzx eax,al
|
|
ret
|
|
get_address_word_value:
|
|
mov [address_size],2
|
|
mov [value_size],2
|
|
jmp calculate_address
|
|
get_address_dword_value:
|
|
mov [address_size],4
|
|
mov [value_size],4
|
|
jmp calculate_address
|
|
get_address_qword_value:
|
|
mov [address_size],8
|
|
mov [value_size],8
|
|
jmp calculate_address
|
|
get_address_value:
|
|
mov [address_size],0
|
|
mov [value_size],8
|
|
calculate_address:
|
|
cmp byte [esi],'.'
|
|
je invalid_address
|
|
call calculate_expression
|
|
mov eax,[edi+16]
|
|
mov [address_symbol],eax
|
|
mov al,[edi+12]
|
|
mov [value_type],al
|
|
cmp al,6
|
|
je special_address_type_32bit
|
|
cmp al,5
|
|
je special_address_type_32bit
|
|
ja invalid_use_of_symbol
|
|
test al,1
|
|
jnz invalid_use_of_symbol
|
|
or al,al
|
|
jz address_size_ok
|
|
shl al,5
|
|
jmp address_symbol_ok
|
|
special_address_type_32bit:
|
|
mov al,40h
|
|
address_symbol_ok:
|
|
mov ah,[address_size]
|
|
or [address_size],al
|
|
shr al,4
|
|
or ah,ah
|
|
jz address_size_ok
|
|
cmp al,ah
|
|
je address_size_ok
|
|
cmp ax,0804h
|
|
jne address_sizes_do_not_agree
|
|
cmp [value_type],2
|
|
ja value_type_correction_ok
|
|
mov [value_type],2
|
|
value_type_correction_ok:
|
|
mov eax,[edi]
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
je address_size_ok
|
|
cmp [error_line],0
|
|
jne address_size_ok
|
|
mov ecx,[current_line]
|
|
mov [error_line],ecx
|
|
mov [error],value_out_of_range
|
|
address_size_ok:
|
|
xor ebx,ebx
|
|
xor ecx,ecx
|
|
mov cl,[value_type]
|
|
shl ecx,16
|
|
mov ch,[address_size]
|
|
cmp word [edi+8],0
|
|
je check_immediate_address
|
|
mov al,[edi+8]
|
|
mov dl,[edi+10]
|
|
call get_address_register
|
|
mov al,[edi+9]
|
|
mov dl,[edi+11]
|
|
call get_address_register
|
|
mov ax,bx
|
|
shr ah,4
|
|
shr al,4
|
|
or bh,bh
|
|
jz check_address_registers
|
|
or bl,bl
|
|
jz check_address_registers
|
|
cmp al,ah
|
|
jne invalid_address
|
|
check_address_registers:
|
|
or al,ah
|
|
mov ah,[address_size]
|
|
and ah,0Fh
|
|
jz address_registers_sizes_ok
|
|
cmp al,ah
|
|
jne address_sizes_do_not_match
|
|
address_registers_sizes_ok:
|
|
cmp al,4
|
|
je sib_allowed
|
|
cmp al,8
|
|
je sib_allowed
|
|
cmp al,0Fh
|
|
je check_ip_relative_address
|
|
or cl,cl
|
|
jz check_word_value
|
|
cmp cl,1
|
|
je check_word_value
|
|
jmp invalid_address
|
|
address_sizes_do_not_match:
|
|
cmp al,0Fh
|
|
jne invalid_address
|
|
mov al,bh
|
|
and al,0Fh
|
|
cmp al,ah
|
|
jne invalid_address
|
|
check_ip_relative_address:
|
|
cmp bh,0F4h
|
|
je check_dword_value
|
|
cmp bh,0F8h
|
|
jne invalid_address
|
|
mov eax,[edi]
|
|
cdq
|
|
cmp edx,[edi+4]
|
|
jne range_exceeded
|
|
ret
|
|
get_address_register:
|
|
or al,al
|
|
jz address_register_ok
|
|
cmp dl,1
|
|
jne scaled_register
|
|
or bh,bh
|
|
jnz scaled_register
|
|
mov bh,al
|
|
address_register_ok:
|
|
ret
|
|
scaled_register:
|
|
or bl,bl
|
|
jnz invalid_address
|
|
mov bl,al
|
|
mov cl,dl
|
|
jmp address_register_ok
|
|
sib_allowed:
|
|
or bh,bh
|
|
jnz check_index_scale
|
|
cmp cl,2
|
|
je special_index_scale
|
|
cmp cl,3
|
|
je special_index_scale
|
|
cmp cl,5
|
|
je special_index_scale
|
|
cmp cl,9
|
|
je special_index_scale
|
|
check_index_scale:
|
|
or cl,cl
|
|
jz check_immediate_address
|
|
cmp cl,1
|
|
je check_immediate_address
|
|
cmp cl,2
|
|
je check_immediate_address
|
|
cmp cl,4
|
|
je check_immediate_address
|
|
cmp cl,8
|
|
je check_immediate_address
|
|
jmp invalid_address
|
|
special_index_scale:
|
|
mov bh,bl
|
|
dec cl
|
|
check_immediate_address:
|
|
mov al,[address_size]
|
|
and al,0Fh
|
|
cmp al,2
|
|
je check_word_value
|
|
cmp al,4
|
|
je check_dword_value
|
|
cmp al,8
|
|
je check_qword_value
|
|
or al,al
|
|
jnz invalid_value
|
|
cmp [code_type],64
|
|
jne check_dword_value
|
|
jmp check_qword_value
|
|
calculate_relative_offset:
|
|
cmp [value_undefined],0
|
|
jne relative_offset_ok
|
|
test bh,bh
|
|
setne ch
|
|
cmp bx,word [org_registers]
|
|
je origin_registers_ok
|
|
xchg bh,bl
|
|
xchg ch,cl
|
|
cmp bx,word [org_registers]
|
|
jne invalid_value
|
|
origin_registers_ok:
|
|
cmp cx,word [org_registers+2]
|
|
jne invalid_value
|
|
add eax,dword [org_origin]
|
|
adc edx,dword [org_origin+4]
|
|
sub eax,edi
|
|
sbb edx,0
|
|
mov bl,[value_type]
|
|
or bl,bl
|
|
je relative_offset_ok
|
|
test bl,1
|
|
jnz invalid_use_of_symbol
|
|
mov ecx,[address_symbol]
|
|
mov [symbol_identifier],ecx
|
|
cmp bl,6
|
|
je plt_relative_offset
|
|
cmp bl,[labels_type]
|
|
jne invalid_use_of_symbol
|
|
mov [value_type],0
|
|
cmp ecx,[org_symbol]
|
|
je relative_offset_ok
|
|
mov [value_type],3
|
|
relative_offset_ok:
|
|
ret
|
|
plt_relative_offset:
|
|
mov [value_type],7
|
|
ret
|
|
|
|
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,'}'
|
|
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,'{'
|
|
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,'}'
|
|
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,'{'
|
|
je skip_logical_value_internal_parenthesis
|
|
cmp al,'}'
|
|
jne skip_logical_value_symbol
|
|
sub [logical_value_parentheses],1
|
|
jnc skip_logical_value_symbol
|
|
cmp [logical_value_wrapping],'{'
|
|
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],'{'
|
|
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],'}'
|
|
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,'{'
|
|
je logical_value_internal_parentheses
|
|
cmp al,'}'
|
|
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],'{'
|
|
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
|
|
|
|
calculate_logical_expression:
|
|
xor al,al
|
|
calculate_embedded_logical_expression:
|
|
mov [logical_value_wrapping],al
|
|
call get_logical_value
|
|
logical_loop:
|
|
cmp byte [esi],'|'
|
|
je logical_or
|
|
cmp byte [esi],'&'
|
|
je logical_and
|
|
ret
|
|
logical_or:
|
|
inc esi
|
|
or al,al
|
|
jnz logical_value_already_determined
|
|
push eax
|
|
call get_logical_value
|
|
pop ebx
|
|
or al,bl
|
|
jmp logical_loop
|
|
logical_and:
|
|
inc esi
|
|
or al,al
|
|
jz logical_value_already_determined
|
|
push eax
|
|
call get_logical_value
|
|
pop ebx
|
|
and al,bl
|
|
jmp logical_loop
|
|
logical_value_already_determined:
|
|
push eax
|
|
call skip_logical_value
|
|
jc invalid_expression
|
|
pop eax
|
|
jmp logical_loop
|
|
get_logical_value:
|
|
xor al,al
|
|
check_for_negation:
|
|
cmp byte [esi],'~'
|
|
jne negation_ok
|
|
inc esi
|
|
xor al,-1
|
|
jmp check_for_negation
|
|
negation_ok:
|
|
push eax
|
|
mov al,[esi]
|
|
cmp al,'{'
|
|
je logical_expression
|
|
cmp al,0FFh
|
|
je invalid_expression
|
|
cmp al,88h
|
|
je check_for_defined
|
|
cmp al,89h
|
|
je check_for_used
|
|
cmp al,'0'
|
|
je given_false
|
|
cmp al,'1'
|
|
je given_true
|
|
call get_value
|
|
mov bl,[value_type]
|
|
push eax edx ebx
|
|
mov al,[esi]
|
|
or al,al
|
|
jz logical_number
|
|
cmp al,0Fh
|
|
je logical_number
|
|
cmp al,'}'
|
|
je logical_number
|
|
cmp al,'&'
|
|
je logical_number
|
|
cmp al,'|'
|
|
je logical_number
|
|
inc esi
|
|
mov [compare_type],al
|
|
call get_value
|
|
pop ebx
|
|
cmp [next_pass_needed],0
|
|
jne values_ok
|
|
cmp bl,[value_type]
|
|
jne invalid_use_of_symbol
|
|
values_ok:
|
|
pop ecx ebx
|
|
cmp [compare_type],'='
|
|
je check_equal
|
|
cmp [compare_type],'>'
|
|
je check_greater
|
|
cmp [compare_type],'<'
|
|
je check_less
|
|
cmp [compare_type],0F1h
|
|
je check_not_equal
|
|
cmp [compare_type],0F2h
|
|
je check_not_less
|
|
cmp [compare_type],0F3h
|
|
je check_not_greater
|
|
jmp invalid_expression
|
|
check_equal:
|
|
cmp eax,ebx
|
|
jne return_false
|
|
cmp edx,ecx
|
|
jne return_false
|
|
jmp return_true
|
|
check_greater:
|
|
cmp edx,ecx
|
|
jl return_true
|
|
jg return_false
|
|
cmp eax,ebx
|
|
jb return_true
|
|
jae return_false
|
|
check_less:
|
|
cmp edx,ecx
|
|
jl return_false
|
|
jg return_true
|
|
cmp eax,ebx
|
|
jbe return_false
|
|
ja return_true
|
|
check_not_less:
|
|
cmp edx,ecx
|
|
jl return_true
|
|
jg return_false
|
|
cmp eax,ebx
|
|
jbe return_true
|
|
ja return_false
|
|
check_not_greater:
|
|
cmp edx,ecx
|
|
jl return_false
|
|
jg return_true
|
|
cmp eax,ebx
|
|
jb return_false
|
|
jae return_true
|
|
check_not_equal:
|
|
cmp eax,ebx
|
|
jne return_true
|
|
cmp edx,ecx
|
|
jne return_true
|
|
jmp return_false
|
|
logical_number:
|
|
pop ebx edx eax
|
|
or bl,bl
|
|
jnz invalid_expression
|
|
or eax,edx
|
|
jnz return_true
|
|
jmp return_false
|
|
check_for_defined:
|
|
or bl,-1
|
|
lods word [esi]
|
|
cmp ah,'('
|
|
jne invalid_expression
|
|
check_expression:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz defined_string
|
|
cmp al,'.'
|
|
je defined_fp_value
|
|
cmp al,')'
|
|
je expression_checked
|
|
cmp al,'!'
|
|
je invalid_expression
|
|
cmp al,0Fh
|
|
je check_expression
|
|
cmp al,10h
|
|
je defined_register
|
|
cmp al,11h
|
|
je check_if_symbol_defined
|
|
cmp al,80h
|
|
jae check_expression
|
|
movzx eax,al
|
|
add esi,eax
|
|
jmp check_expression
|
|
defined_register:
|
|
inc esi
|
|
jmp check_expression
|
|
defined_fp_value:
|
|
add esi,12
|
|
jmp expression_checked
|
|
defined_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
inc esi
|
|
jmp expression_checked
|
|
check_if_symbol_defined:
|
|
lods dword [esi]
|
|
cmp eax,-1
|
|
je invalid_expression
|
|
cmp eax,0Fh
|
|
jb check_expression
|
|
je reserved_word_used_as_symbol
|
|
test byte [eax+8],4
|
|
jnz no_prediction
|
|
test byte [eax+8],1
|
|
jz symbol_predicted_undefined
|
|
mov cx,[current_pass]
|
|
sub cx,[eax+16]
|
|
jz check_expression
|
|
cmp cx,1
|
|
ja symbol_predicted_undefined
|
|
or byte [eax+8],40h+80h
|
|
jmp check_expression
|
|
no_prediction:
|
|
test byte [eax+8],1
|
|
jz symbol_undefined
|
|
mov cx,[current_pass]
|
|
sub cx,[eax+16]
|
|
jz check_expression
|
|
jmp symbol_undefined
|
|
symbol_predicted_undefined:
|
|
or byte [eax+8],40h
|
|
and byte [eax+8],not 80h
|
|
symbol_undefined:
|
|
xor bl,bl
|
|
jmp check_expression
|
|
expression_checked:
|
|
mov al,bl
|
|
jmp logical_value_ok
|
|
check_for_used:
|
|
lods word [esi]
|
|
cmp ah,2
|
|
jne invalid_expression
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
inc esi
|
|
test byte [eax+8],8
|
|
jz not_used
|
|
mov cx,[current_pass]
|
|
sub cx,[eax+18]
|
|
jz return_true
|
|
cmp cx,1
|
|
ja not_used
|
|
or byte [eax+8],10h+20h
|
|
jmp return_true
|
|
not_used:
|
|
or byte [eax+8],10h
|
|
and byte [eax+8],not 20h
|
|
jmp return_false
|
|
given_false:
|
|
inc esi
|
|
return_false:
|
|
xor al,al
|
|
jmp logical_value_ok
|
|
given_true:
|
|
inc esi
|
|
return_true:
|
|
or al,-1
|
|
jmp logical_value_ok
|
|
logical_expression:
|
|
lods byte [esi]
|
|
mov dl,[logical_value_wrapping]
|
|
push edx
|
|
call calculate_embedded_logical_expression
|
|
pop edx
|
|
mov [logical_value_wrapping],dl
|
|
push eax
|
|
lods byte [esi]
|
|
cmp al,'}'
|
|
jne invalid_expression
|
|
pop eax
|
|
logical_value_ok:
|
|
pop ebx
|
|
xor al,bl
|
|
ret
|