2899 lines
53 KiB
PHP
2899 lines
53 KiB
PHP
|
|
; flat assembler core
|
|
; Copyright (c) 1999-2016, Tomasz Grysztar.
|
|
; All rights reserved.
|
|
|
|
preprocessor:
|
|
mov edi,characters
|
|
xor al,al
|
|
make_characters_table:
|
|
stosb
|
|
inc al
|
|
jnz make_characters_table
|
|
mov esi,characters+'a'
|
|
mov edi,characters+'A'
|
|
mov ecx,26
|
|
rep movsb
|
|
mov edi,characters
|
|
mov esi,symbol_characters+1
|
|
movzx ecx,byte [esi-1]
|
|
xor eax,eax
|
|
mark_symbol_characters:
|
|
lodsb
|
|
mov byte [edi+eax],0
|
|
loop mark_symbol_characters
|
|
mov edi,locals_counter
|
|
mov ax,1 + '0' shl 8
|
|
stos word [edi]
|
|
mov edi,[memory_start]
|
|
mov [include_paths],edi
|
|
mov esi,include_variable
|
|
call get_environment_variable
|
|
xor al,al
|
|
stos byte [edi]
|
|
mov [memory_start],edi
|
|
mov eax,[additional_memory]
|
|
mov [free_additional_memory],eax
|
|
mov eax,[additional_memory_end]
|
|
mov [labels_list],eax
|
|
xor eax,eax
|
|
mov [source_start],eax
|
|
mov [tagged_blocks],eax
|
|
mov [hash_tree],eax
|
|
mov [error],eax
|
|
mov [macro_status],al
|
|
mov [current_line],eax
|
|
mov esi,[initial_definitions]
|
|
test esi,esi
|
|
jz predefinitions_ok
|
|
process_predefinitions:
|
|
movzx ecx,byte [esi]
|
|
test ecx,ecx
|
|
jz predefinitions_ok
|
|
inc esi
|
|
lea eax,[esi+ecx]
|
|
push eax
|
|
mov ch,10b
|
|
call add_preprocessor_symbol
|
|
pop esi
|
|
mov edi,[memory_start]
|
|
mov [edx+8],edi
|
|
convert_predefinition:
|
|
cmp edi,[memory_end]
|
|
jae out_of_memory
|
|
lods byte [esi]
|
|
or al,al
|
|
jz predefinition_converted
|
|
cmp al,20h
|
|
je convert_predefinition
|
|
mov ah,al
|
|
mov ebx,characters
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz predefinition_separator
|
|
cmp ah,27h
|
|
je predefinition_string
|
|
cmp ah,22h
|
|
je predefinition_string
|
|
mov byte [edi],1Ah
|
|
scas word [edi]
|
|
xchg al,ah
|
|
stos byte [edi]
|
|
mov ebx,characters
|
|
xor ecx,ecx
|
|
predefinition_symbol:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
xlat byte [ebx]
|
|
or al,al
|
|
loopnzd predefinition_symbol
|
|
neg ecx
|
|
cmp ecx,255
|
|
ja invalid_definition
|
|
mov ebx,edi
|
|
sub ebx,ecx
|
|
mov byte [ebx-2],cl
|
|
found_predefinition_separator:
|
|
dec edi
|
|
mov ah,[esi-1]
|
|
predefinition_separator:
|
|
xchg al,ah
|
|
or al,al
|
|
jz predefinition_converted
|
|
cmp al,20h
|
|
je convert_predefinition
|
|
cmp al,3Bh
|
|
je invalid_definition
|
|
cmp al,5Ch
|
|
je predefinition_backslash
|
|
stos byte [edi]
|
|
jmp convert_predefinition
|
|
predefinition_string:
|
|
mov al,22h
|
|
stos byte [edi]
|
|
scas dword [edi]
|
|
mov ebx,edi
|
|
copy_predefinition_string:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
or al,al
|
|
jz invalid_definition
|
|
cmp al,ah
|
|
jne copy_predefinition_string
|
|
lods byte [esi]
|
|
cmp al,ah
|
|
je copy_predefinition_string
|
|
dec esi
|
|
dec edi
|
|
mov eax,edi
|
|
sub eax,ebx
|
|
mov [ebx-4],eax
|
|
jmp convert_predefinition
|
|
predefinition_backslash:
|
|
mov byte [edi],0
|
|
lods byte [esi]
|
|
or al,al
|
|
jz invalid_definition
|
|
cmp al,20h
|
|
je invalid_definition
|
|
cmp al,3Bh
|
|
je invalid_definition
|
|
mov al,1Ah
|
|
stos byte [edi]
|
|
mov ecx,edi
|
|
mov ax,5C01h
|
|
stos word [edi]
|
|
dec esi
|
|
group_predefinition_backslashes:
|
|
lods byte [esi]
|
|
cmp al,5Ch
|
|
jne predefinition_backslashed_symbol
|
|
stos byte [edi]
|
|
inc byte [ecx]
|
|
jmp group_predefinition_backslashes
|
|
predefinition_backslashed_symbol:
|
|
cmp al,20h
|
|
je invalid_definition
|
|
cmp al,22h
|
|
je invalid_definition
|
|
cmp al,27h
|
|
je invalid_definition
|
|
cmp al,3Bh
|
|
je invalid_definition
|
|
mov ah,al
|
|
mov ebx,characters
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz predefinition_backslashed_symbol_character
|
|
mov al,ah
|
|
convert_predefinition_backslashed_symbol:
|
|
stos byte [edi]
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz found_predefinition_separator
|
|
inc byte [ecx]
|
|
jz invalid_definition
|
|
lods byte [esi]
|
|
jmp convert_predefinition_backslashed_symbol
|
|
predefinition_backslashed_symbol_character:
|
|
mov al,ah
|
|
stos byte [edi]
|
|
inc byte [ecx]
|
|
jmp convert_predefinition
|
|
predefinition_converted:
|
|
mov [memory_start],edi
|
|
sub edi,[edx+8]
|
|
mov [edx+12],edi
|
|
jmp process_predefinitions
|
|
predefinitions_ok:
|
|
mov esi,[input_file]
|
|
mov edx,esi
|
|
call open
|
|
jc main_file_not_found
|
|
mov edi,[memory_start]
|
|
call preprocess_file
|
|
cmp [macro_status],0
|
|
je process_postponed
|
|
mov eax,[error_line]
|
|
mov [current_line],eax
|
|
jmp incomplete_macro
|
|
process_postponed:
|
|
mov edx,hash_tree
|
|
mov ecx,32
|
|
find_postponed_list:
|
|
mov edx,[edx]
|
|
or edx,edx
|
|
loopnz find_postponed_list
|
|
jz preprocessing_finished
|
|
process_postponed_list:
|
|
mov eax,[edx]
|
|
or eax,eax
|
|
jz preprocessing_finished
|
|
push edx
|
|
mov ebx,edx
|
|
find_earliest_postponed:
|
|
mov eax,[edx]
|
|
or eax,eax
|
|
jz earliest_postponed_found
|
|
mov ebx,edx
|
|
mov edx,eax
|
|
jmp find_earliest_postponed
|
|
earliest_postponed_found:
|
|
mov [ebx],eax
|
|
call use_postponed_macro
|
|
pop edx
|
|
cmp [macro_status],0
|
|
je process_postponed_list
|
|
mov eax,[error_line]
|
|
mov [current_line],eax
|
|
jmp incomplete_macro
|
|
preprocessing_finished:
|
|
mov [source_start],edi
|
|
ret
|
|
use_postponed_macro:
|
|
lea esi,[edi-1]
|
|
push ecx esi
|
|
mov [struc_name],0
|
|
jmp use_macro
|
|
|
|
preprocess_file:
|
|
push [memory_end]
|
|
push esi
|
|
mov al,2
|
|
xor edx,edx
|
|
call lseek
|
|
push eax
|
|
xor al,al
|
|
xor edx,edx
|
|
call lseek
|
|
pop ecx
|
|
mov edx,[memory_end]
|
|
dec edx
|
|
mov byte [edx],1Ah
|
|
sub edx,ecx
|
|
jc out_of_memory
|
|
mov esi,edx
|
|
cmp edx,edi
|
|
jbe out_of_memory
|
|
mov [memory_end],edx
|
|
call read
|
|
call close
|
|
pop edx
|
|
xor ecx,ecx
|
|
mov ebx,esi
|
|
preprocess_source:
|
|
inc ecx
|
|
mov [current_line],edi
|
|
mov eax,edx
|
|
stos dword [edi]
|
|
mov eax,ecx
|
|
stos dword [edi]
|
|
mov eax,esi
|
|
sub eax,ebx
|
|
stos dword [edi]
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
push ebx edx
|
|
call convert_line
|
|
call preprocess_line
|
|
pop edx ebx
|
|
next_line:
|
|
cmp byte [esi-1],0
|
|
je file_end
|
|
cmp byte [esi-1],1Ah
|
|
jne preprocess_source
|
|
file_end:
|
|
pop [memory_end]
|
|
clc
|
|
ret
|
|
|
|
convert_line:
|
|
push ecx
|
|
test [macro_status],0Fh
|
|
jz convert_line_data
|
|
mov ax,3Bh
|
|
stos word [edi]
|
|
convert_line_data:
|
|
cmp edi,[memory_end]
|
|
jae out_of_memory
|
|
lods byte [esi]
|
|
cmp al,20h
|
|
je convert_line_data
|
|
cmp al,9
|
|
je convert_line_data
|
|
mov ah,al
|
|
mov ebx,characters
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz convert_separator
|
|
cmp ah,27h
|
|
je convert_string
|
|
cmp ah,22h
|
|
je convert_string
|
|
mov byte [edi],1Ah
|
|
scas word [edi]
|
|
xchg al,ah
|
|
stos byte [edi]
|
|
mov ebx,characters
|
|
xor ecx,ecx
|
|
convert_symbol:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
xlat byte [ebx]
|
|
or al,al
|
|
loopnzd convert_symbol
|
|
neg ecx
|
|
cmp ecx,255
|
|
ja name_too_long
|
|
mov ebx,edi
|
|
sub ebx,ecx
|
|
mov byte [ebx-2],cl
|
|
found_separator:
|
|
dec edi
|
|
mov ah,[esi-1]
|
|
convert_separator:
|
|
xchg al,ah
|
|
cmp al,20h
|
|
jb control_character
|
|
je convert_line_data
|
|
symbol_character:
|
|
cmp al,3Bh
|
|
je ignore_comment
|
|
cmp al,5Ch
|
|
je backslash_character
|
|
stos byte [edi]
|
|
jmp convert_line_data
|
|
control_character:
|
|
cmp al,1Ah
|
|
je line_end
|
|
cmp al,0Dh
|
|
je cr_character
|
|
cmp al,0Ah
|
|
je lf_character
|
|
cmp al,9
|
|
je convert_line_data
|
|
or al,al
|
|
jnz symbol_character
|
|
jmp line_end
|
|
lf_character:
|
|
lods byte [esi]
|
|
cmp al,0Dh
|
|
je line_end
|
|
dec esi
|
|
jmp line_end
|
|
cr_character:
|
|
lods byte [esi]
|
|
cmp al,0Ah
|
|
je line_end
|
|
dec esi
|
|
jmp line_end
|
|
convert_string:
|
|
mov al,22h
|
|
stos byte [edi]
|
|
scas dword [edi]
|
|
mov ebx,edi
|
|
copy_string:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
cmp al,0Ah
|
|
je no_end_quote
|
|
cmp al,0Dh
|
|
je no_end_quote
|
|
or al,al
|
|
jz no_end_quote
|
|
cmp al,1Ah
|
|
je no_end_quote
|
|
cmp al,ah
|
|
jne copy_string
|
|
lods byte [esi]
|
|
cmp al,ah
|
|
je copy_string
|
|
dec esi
|
|
dec edi
|
|
mov eax,edi
|
|
sub eax,ebx
|
|
mov [ebx-4],eax
|
|
jmp convert_line_data
|
|
backslash_character:
|
|
mov byte [edi],0
|
|
lods byte [esi]
|
|
cmp al,20h
|
|
je concatenate_lines
|
|
cmp al,9
|
|
je concatenate_lines
|
|
cmp al,1Ah
|
|
je unexpected_end_of_file
|
|
or al,al
|
|
jz unexpected_end_of_file
|
|
cmp al,0Ah
|
|
je concatenate_lf
|
|
cmp al,0Dh
|
|
je concatenate_cr
|
|
cmp al,3Bh
|
|
je find_concatenated_line
|
|
mov al,1Ah
|
|
stos byte [edi]
|
|
mov ecx,edi
|
|
mov ax,5C01h
|
|
stos word [edi]
|
|
dec esi
|
|
group_backslashes:
|
|
lods byte [esi]
|
|
cmp al,5Ch
|
|
jne backslashed_symbol
|
|
stos byte [edi]
|
|
inc byte [ecx]
|
|
jz name_too_long
|
|
jmp group_backslashes
|
|
no_end_quote:
|
|
mov byte [ebx-5],0
|
|
jmp missing_end_quote
|
|
backslashed_symbol:
|
|
cmp al,1Ah
|
|
je unexpected_end_of_file
|
|
or al,al
|
|
jz unexpected_end_of_file
|
|
cmp al,0Ah
|
|
je extra_characters_on_line
|
|
cmp al,0Dh
|
|
je extra_characters_on_line
|
|
cmp al,20h
|
|
je extra_characters_on_line
|
|
cmp al,9
|
|
je extra_characters_on_line
|
|
cmp al,22h
|
|
je extra_characters_on_line
|
|
cmp al,27h
|
|
je extra_characters_on_line
|
|
cmp al,3Bh
|
|
je extra_characters_on_line
|
|
mov ah,al
|
|
mov ebx,characters
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz backslashed_symbol_character
|
|
mov al,ah
|
|
convert_backslashed_symbol:
|
|
stos byte [edi]
|
|
xlat byte [ebx]
|
|
or al,al
|
|
jz found_separator
|
|
inc byte [ecx]
|
|
jz name_too_long
|
|
lods byte [esi]
|
|
jmp convert_backslashed_symbol
|
|
backslashed_symbol_character:
|
|
mov al,ah
|
|
stos byte [edi]
|
|
inc byte [ecx]
|
|
jmp convert_line_data
|
|
concatenate_lines:
|
|
lods byte [esi]
|
|
cmp al,20h
|
|
je concatenate_lines
|
|
cmp al,9
|
|
je concatenate_lines
|
|
cmp al,1Ah
|
|
je unexpected_end_of_file
|
|
or al,al
|
|
jz unexpected_end_of_file
|
|
cmp al,0Ah
|
|
je concatenate_lf
|
|
cmp al,0Dh
|
|
je concatenate_cr
|
|
cmp al,3Bh
|
|
jne extra_characters_on_line
|
|
find_concatenated_line:
|
|
lods byte [esi]
|
|
cmp al,0Ah
|
|
je concatenate_lf
|
|
cmp al,0Dh
|
|
je concatenate_cr
|
|
or al,al
|
|
jz concatenate_ok
|
|
cmp al,1Ah
|
|
jne find_concatenated_line
|
|
jmp unexpected_end_of_file
|
|
concatenate_lf:
|
|
lods byte [esi]
|
|
cmp al,0Dh
|
|
je concatenate_ok
|
|
dec esi
|
|
jmp concatenate_ok
|
|
concatenate_cr:
|
|
lods byte [esi]
|
|
cmp al,0Ah
|
|
je concatenate_ok
|
|
dec esi
|
|
concatenate_ok:
|
|
inc dword [esp]
|
|
jmp convert_line_data
|
|
ignore_comment:
|
|
lods byte [esi]
|
|
cmp al,0Ah
|
|
je lf_character
|
|
cmp al,0Dh
|
|
je cr_character
|
|
or al,al
|
|
jz line_end
|
|
cmp al,1Ah
|
|
jne ignore_comment
|
|
line_end:
|
|
xor al,al
|
|
stos byte [edi]
|
|
pop ecx
|
|
ret
|
|
|
|
lower_case:
|
|
mov edi,converted
|
|
mov ebx,characters
|
|
convert_case:
|
|
lods byte [esi]
|
|
xlat byte [ebx]
|
|
stos byte [edi]
|
|
loop convert_case
|
|
case_ok:
|
|
ret
|
|
|
|
get_directive:
|
|
push edi
|
|
mov edx,esi
|
|
mov ebp,ecx
|
|
call lower_case
|
|
pop edi
|
|
scan_directives:
|
|
mov esi,converted
|
|
movzx eax,byte [edi]
|
|
or al,al
|
|
jz no_directive
|
|
mov ecx,ebp
|
|
inc edi
|
|
mov ebx,edi
|
|
add ebx,eax
|
|
mov ah,[esi]
|
|
cmp ah,[edi]
|
|
jb no_directive
|
|
ja next_directive
|
|
cmp cl,al
|
|
jne next_directive
|
|
repe cmps byte [esi],[edi]
|
|
jb no_directive
|
|
je directive_ok
|
|
next_directive:
|
|
mov edi,ebx
|
|
add edi,2
|
|
jmp scan_directives
|
|
no_directive:
|
|
mov esi,edx
|
|
mov ecx,ebp
|
|
stc
|
|
ret
|
|
directive_ok:
|
|
lea esi,[edx+ebp]
|
|
call directive_handler
|
|
directive_handler:
|
|
pop ecx
|
|
movzx eax,word [ebx]
|
|
add eax,ecx
|
|
clc
|
|
ret
|
|
|
|
preprocess_line:
|
|
mov eax,esp
|
|
sub eax,100h
|
|
jc stack_overflow
|
|
cmp eax,[stack_limit]
|
|
jb stack_overflow
|
|
push ecx esi
|
|
preprocess_current_line:
|
|
mov esi,[current_line]
|
|
add esi,16
|
|
cmp word [esi],3Bh
|
|
jne line_start_ok
|
|
add esi,2
|
|
line_start_ok:
|
|
test [macro_status],0F0h
|
|
jnz macro_preprocessing
|
|
cmp byte [esi],1Ah
|
|
jne not_fix_constant
|
|
movzx edx,byte [esi+1]
|
|
lea edx,[esi+2+edx]
|
|
cmp word [edx],031Ah
|
|
jne not_fix_constant
|
|
mov ebx,characters
|
|
movzx eax,byte [edx+2]
|
|
xlat byte [ebx]
|
|
ror eax,8
|
|
mov al,[edx+3]
|
|
xlat byte [ebx]
|
|
ror eax,8
|
|
mov al,[edx+4]
|
|
xlat byte [ebx]
|
|
ror eax,16
|
|
cmp eax,'fix'
|
|
je define_fix_constant
|
|
not_fix_constant:
|
|
call process_fix_constants
|
|
jmp initial_preprocessing_ok
|
|
macro_preprocessing:
|
|
call process_macro_operators
|
|
initial_preprocessing_ok:
|
|
mov esi,[current_line]
|
|
add esi,16
|
|
mov al,[macro_status]
|
|
test al,2
|
|
jnz skip_macro_block
|
|
test al,1
|
|
jnz find_macro_block
|
|
preprocess_instruction:
|
|
mov [current_offset],esi
|
|
lods byte [esi]
|
|
movzx ecx,byte [esi]
|
|
inc esi
|
|
cmp al,1Ah
|
|
jne not_preprocessor_symbol
|
|
cmp cl,3
|
|
jb not_preprocessor_directive
|
|
push edi
|
|
mov edi,preprocessor_directives
|
|
call get_directive
|
|
pop edi
|
|
jc not_preprocessor_directive
|
|
mov byte [edx-2],3Bh
|
|
jmp near eax
|
|
not_preprocessor_directive:
|
|
xor ch,ch
|
|
call get_preprocessor_symbol
|
|
jc not_macro
|
|
mov byte [ebx-2],3Bh
|
|
mov [struc_name],0
|
|
jmp use_macro
|
|
not_macro:
|
|
mov [struc_name],esi
|
|
add esi,ecx
|
|
lods byte [esi]
|
|
cmp al,':'
|
|
je preprocess_label
|
|
cmp al,1Ah
|
|
jne not_preprocessor_symbol
|
|
lods byte [esi]
|
|
cmp al,3
|
|
jne not_symbolic_constant
|
|
mov ebx,characters
|
|
movzx eax,byte [esi]
|
|
xlat byte [ebx]
|
|
ror eax,8
|
|
mov al,[esi+1]
|
|
xlat byte [ebx]
|
|
ror eax,8
|
|
mov al,[esi+2]
|
|
xlat byte [ebx]
|
|
ror eax,16
|
|
cmp eax,'equ'
|
|
je define_equ_constant
|
|
mov al,3
|
|
not_symbolic_constant:
|
|
mov ch,1
|
|
mov cl,al
|
|
call get_preprocessor_symbol
|
|
jc not_preprocessor_symbol
|
|
push edx esi
|
|
mov esi,[struc_name]
|
|
mov [struc_label],esi
|
|
sub [struc_label],2
|
|
mov cl,[esi-1]
|
|
mov ch,10b
|
|
call get_preprocessor_symbol
|
|
jc struc_name_ok
|
|
mov ecx,[edx+12]
|
|
add ecx,3
|
|
lea ebx,[edi+ecx]
|
|
mov ecx,edi
|
|
sub ecx,[struc_label]
|
|
lea esi,[edi-1]
|
|
lea edi,[ebx-1]
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
mov edi,[struc_label]
|
|
mov esi,[edx+8]
|
|
mov ecx,[edx+12]
|
|
add [struc_name],ecx
|
|
add [struc_name],3
|
|
call move_data
|
|
mov al,3Ah
|
|
stos byte [edi]
|
|
mov ax,3Bh
|
|
stos word [edi]
|
|
mov edi,ebx
|
|
pop esi
|
|
add esi,[edx+12]
|
|
add esi,3
|
|
pop edx
|
|
jmp use_macro
|
|
struc_name_ok:
|
|
mov edx,[struc_name]
|
|
movzx eax,byte [edx-1]
|
|
add edx,eax
|
|
push edi
|
|
lea esi,[edi-1]
|
|
mov ecx,edi
|
|
sub ecx,edx
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
pop edi
|
|
inc edi
|
|
mov al,3Ah
|
|
mov [edx],al
|
|
inc al
|
|
mov [edx+1],al
|
|
pop esi edx
|
|
inc esi
|
|
jmp use_macro
|
|
preprocess_label:
|
|
dec esi
|
|
sub esi,ecx
|
|
lea ebp,[esi-2]
|
|
mov ch,10b
|
|
call get_preprocessor_symbol
|
|
jnc symbolic_constant_in_label
|
|
lea esi,[esi+ecx+1]
|
|
cmp byte [esi],':'
|
|
jne preprocess_instruction
|
|
inc esi
|
|
jmp preprocess_instruction
|
|
symbolic_constant_in_label:
|
|
mov ebx,[edx+8]
|
|
mov ecx,[edx+12]
|
|
add ecx,ebx
|
|
check_for_broken_label:
|
|
cmp ebx,ecx
|
|
je label_broken
|
|
cmp byte [ebx],1Ah
|
|
jne label_broken
|
|
movzx eax,byte [ebx+1]
|
|
lea ebx,[ebx+2+eax]
|
|
cmp ebx,ecx
|
|
je label_constant_ok
|
|
cmp byte [ebx],':'
|
|
jne label_broken
|
|
inc ebx
|
|
cmp byte [ebx],':'
|
|
jne check_for_broken_label
|
|
inc ebx
|
|
jmp check_for_broken_label
|
|
label_broken:
|
|
push line_preprocessed
|
|
jmp replace_symbolic_constant
|
|
label_constant_ok:
|
|
mov ecx,edi
|
|
sub ecx,esi
|
|
mov edi,[edx+12]
|
|
add edi,ebp
|
|
push edi
|
|
lea eax,[edi+ecx]
|
|
push eax
|
|
cmp esi,edi
|
|
je replace_label
|
|
jb move_rest_of_line_up
|
|
rep movs byte [edi],[esi]
|
|
jmp replace_label
|
|
move_rest_of_line_up:
|
|
lea esi,[esi+ecx-1]
|
|
lea edi,[edi+ecx-1]
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
replace_label:
|
|
mov ecx,[edx+12]
|
|
mov edi,[esp+4]
|
|
sub edi,ecx
|
|
mov esi,[edx+8]
|
|
rep movs byte [edi],[esi]
|
|
pop edi esi
|
|
inc esi
|
|
jmp preprocess_instruction
|
|
not_preprocessor_symbol:
|
|
mov esi,[current_offset]
|
|
call process_equ_constants
|
|
line_preprocessed:
|
|
pop esi ecx
|
|
ret
|
|
|
|
get_preprocessor_symbol:
|
|
push ebp edi esi
|
|
mov ebp,ecx
|
|
shl ebp,22
|
|
movzx ecx,cl
|
|
mov ebx,hash_tree
|
|
mov edi,10
|
|
follow_hashes_roots:
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz preprocessor_symbol_not_found
|
|
xor eax,eax
|
|
shl ebp,1
|
|
adc eax,0
|
|
lea ebx,[edx+eax*4]
|
|
dec edi
|
|
jnz follow_hashes_roots
|
|
mov edi,ebx
|
|
call calculate_hash
|
|
mov ebp,eax
|
|
and ebp,3FFh
|
|
shl ebp,10
|
|
xor ebp,eax
|
|
mov ebx,edi
|
|
mov edi,22
|
|
follow_hashes_tree:
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz preprocessor_symbol_not_found
|
|
xor eax,eax
|
|
shl ebp,1
|
|
adc eax,0
|
|
lea ebx,[edx+eax*4]
|
|
dec edi
|
|
jnz follow_hashes_tree
|
|
mov al,cl
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz preprocessor_symbol_not_found
|
|
compare_with_preprocessor_symbol:
|
|
mov edi,[edx+4]
|
|
cmp edi,1
|
|
jbe next_equal_hash
|
|
repe cmps byte [esi],[edi]
|
|
je preprocessor_symbol_found
|
|
mov cl,al
|
|
mov esi,[esp]
|
|
next_equal_hash:
|
|
mov edx,[edx]
|
|
or edx,edx
|
|
jnz compare_with_preprocessor_symbol
|
|
preprocessor_symbol_not_found:
|
|
pop esi edi ebp
|
|
stc
|
|
ret
|
|
preprocessor_symbol_found:
|
|
pop ebx edi ebp
|
|
clc
|
|
ret
|
|
calculate_hash:
|
|
xor ebx,ebx
|
|
mov eax,2166136261
|
|
mov ebp,16777619
|
|
fnv1a_hash:
|
|
xor al,[esi+ebx]
|
|
mul ebp
|
|
inc bl
|
|
cmp bl,cl
|
|
jb fnv1a_hash
|
|
ret
|
|
add_preprocessor_symbol:
|
|
push edi esi
|
|
xor eax,eax
|
|
or cl,cl
|
|
jz reshape_hash
|
|
cmp ch,11b
|
|
je preprocessor_symbol_name_ok
|
|
push ecx
|
|
movzx ecx,cl
|
|
mov edi,preprocessor_directives
|
|
call get_directive
|
|
jnc reserved_word_used_as_symbol
|
|
pop ecx
|
|
preprocessor_symbol_name_ok:
|
|
call calculate_hash
|
|
reshape_hash:
|
|
mov ebp,eax
|
|
and ebp,3FFh
|
|
shr eax,10
|
|
xor ebp,eax
|
|
shl ecx,22
|
|
or ebp,ecx
|
|
mov ebx,hash_tree
|
|
mov ecx,32
|
|
find_leave_for_symbol:
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz extend_hashes_tree
|
|
xor eax,eax
|
|
rol ebp,1
|
|
adc eax,0
|
|
lea ebx,[edx+eax*4]
|
|
dec ecx
|
|
jnz find_leave_for_symbol
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz add_symbol_entry
|
|
shr ebp,30
|
|
cmp ebp,11b
|
|
je reuse_symbol_entry
|
|
cmp dword [edx+4],0
|
|
jne add_symbol_entry
|
|
find_entry_to_reuse:
|
|
mov edi,[edx]
|
|
or edi,edi
|
|
jz reuse_symbol_entry
|
|
cmp dword [edi+4],0
|
|
jne reuse_symbol_entry
|
|
mov edx,edi
|
|
jmp find_entry_to_reuse
|
|
add_symbol_entry:
|
|
mov eax,edx
|
|
mov edx,[labels_list]
|
|
sub edx,16
|
|
cmp edx,[free_additional_memory]
|
|
jb out_of_memory
|
|
mov [labels_list],edx
|
|
mov [edx],eax
|
|
mov [ebx],edx
|
|
reuse_symbol_entry:
|
|
pop esi edi
|
|
mov [edx+4],esi
|
|
ret
|
|
extend_hashes_tree:
|
|
mov edx,[labels_list]
|
|
sub edx,8
|
|
cmp edx,[free_additional_memory]
|
|
jb out_of_memory
|
|
mov [labels_list],edx
|
|
xor eax,eax
|
|
mov [edx],eax
|
|
mov [edx+4],eax
|
|
shl ebp,1
|
|
adc eax,0
|
|
mov [ebx],edx
|
|
lea ebx,[edx+eax*4]
|
|
dec ecx
|
|
jnz extend_hashes_tree
|
|
mov edx,[labels_list]
|
|
sub edx,16
|
|
cmp edx,[free_additional_memory]
|
|
jb out_of_memory
|
|
mov [labels_list],edx
|
|
mov dword [edx],0
|
|
mov [ebx],edx
|
|
pop esi edi
|
|
mov [edx+4],esi
|
|
ret
|
|
|
|
define_fix_constant:
|
|
add edx,5
|
|
add esi,2
|
|
push edx
|
|
mov ch,11b
|
|
jmp define_preprocessor_constant
|
|
define_equ_constant:
|
|
add esi,3
|
|
push esi
|
|
call process_equ_constants
|
|
mov esi,[struc_name]
|
|
mov ch,10b
|
|
define_preprocessor_constant:
|
|
mov byte [esi-2],3Bh
|
|
mov cl,[esi-1]
|
|
call add_preprocessor_symbol
|
|
pop ebx
|
|
mov ecx,edi
|
|
dec ecx
|
|
sub ecx,ebx
|
|
mov [edx+8],ebx
|
|
mov [edx+12],ecx
|
|
jmp line_preprocessed
|
|
define_symbolic_constant:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_name
|
|
lods byte [esi]
|
|
mov cl,al
|
|
mov ch,10b
|
|
call add_preprocessor_symbol
|
|
movzx eax,byte [esi-1]
|
|
add esi,eax
|
|
lea ecx,[edi-1]
|
|
sub ecx,esi
|
|
mov [edx+8],esi
|
|
mov [edx+12],ecx
|
|
jmp line_preprocessed
|
|
|
|
define_struc:
|
|
mov ch,1
|
|
jmp make_macro
|
|
define_macro:
|
|
xor ch,ch
|
|
make_macro:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_name
|
|
lods byte [esi]
|
|
mov cl,al
|
|
call add_preprocessor_symbol
|
|
mov eax,[current_line]
|
|
mov [edx+12],eax
|
|
movzx eax,byte [esi-1]
|
|
add esi,eax
|
|
mov [edx+8],esi
|
|
mov al,[macro_status]
|
|
and al,0F0h
|
|
or al,1
|
|
mov [macro_status],al
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
xor ebp,ebp
|
|
lods byte [esi]
|
|
or al,al
|
|
jz line_preprocessed
|
|
cmp al,'{'
|
|
je found_macro_block
|
|
dec esi
|
|
skip_macro_arguments:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je skip_macro_argument
|
|
cmp al,'['
|
|
jne invalid_macro_arguments
|
|
or ebp,-1
|
|
jz invalid_macro_arguments
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_macro_arguments
|
|
skip_macro_argument:
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
add esi,eax
|
|
lods byte [esi]
|
|
cmp al,':'
|
|
je macro_argument_with_default_value
|
|
cmp al,'='
|
|
je macro_argument_with_default_value
|
|
cmp al,'*'
|
|
jne macro_argument_end
|
|
lods byte [esi]
|
|
macro_argument_end:
|
|
cmp al,','
|
|
je skip_macro_arguments
|
|
cmp al,'&'
|
|
je macro_arguments_finisher
|
|
cmp al,']'
|
|
jne end_macro_arguments
|
|
not ebp
|
|
macro_arguments_finisher:
|
|
lods byte [esi]
|
|
end_macro_arguments:
|
|
or ebp,ebp
|
|
jnz invalid_macro_arguments
|
|
or al,al
|
|
jz line_preprocessed
|
|
cmp al,'{'
|
|
je found_macro_block
|
|
jmp invalid_macro_arguments
|
|
macro_argument_with_default_value:
|
|
or [skip_default_argument_value],-1
|
|
call skip_macro_argument_value
|
|
inc esi
|
|
jmp macro_argument_end
|
|
skip_macro_argument_value:
|
|
cmp byte [esi],'<'
|
|
jne simple_argument
|
|
mov ecx,1
|
|
inc esi
|
|
enclosed_argument:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz invalid_macro_arguments
|
|
cmp al,1Ah
|
|
je enclosed_symbol
|
|
cmp al,22h
|
|
je enclosed_string
|
|
cmp al,'>'
|
|
je enclosed_argument_end
|
|
cmp al,'<'
|
|
jne enclosed_argument
|
|
inc ecx
|
|
jmp enclosed_argument
|
|
enclosed_symbol:
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
add esi,eax
|
|
jmp enclosed_argument
|
|
enclosed_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp enclosed_argument
|
|
enclosed_argument_end:
|
|
loop enclosed_argument
|
|
lods byte [esi]
|
|
or al,al
|
|
jz argument_value_end
|
|
cmp al,','
|
|
je argument_value_end
|
|
cmp [skip_default_argument_value],0
|
|
je invalid_macro_arguments
|
|
cmp al,'{'
|
|
je argument_value_end
|
|
cmp al,'&'
|
|
je argument_value_end
|
|
or ebp,ebp
|
|
jz invalid_macro_arguments
|
|
cmp al,']'
|
|
je argument_value_end
|
|
jmp invalid_macro_arguments
|
|
simple_argument:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz argument_value_end
|
|
cmp al,','
|
|
je argument_value_end
|
|
cmp al,22h
|
|
je argument_string
|
|
cmp al,1Ah
|
|
je argument_symbol
|
|
cmp [skip_default_argument_value],0
|
|
je simple_argument
|
|
cmp al,'{'
|
|
je argument_value_end
|
|
cmp al,'&'
|
|
je argument_value_end
|
|
or ebp,ebp
|
|
jz simple_argument
|
|
cmp al,']'
|
|
je argument_value_end
|
|
argument_symbol:
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
add esi,eax
|
|
jmp simple_argument
|
|
argument_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp simple_argument
|
|
argument_value_end:
|
|
dec esi
|
|
ret
|
|
find_macro_block:
|
|
add esi,2
|
|
lods byte [esi]
|
|
or al,al
|
|
jz line_preprocessed
|
|
cmp al,'{'
|
|
jne unexpected_characters
|
|
found_macro_block:
|
|
or [macro_status],2
|
|
skip_macro_block:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je skip_macro_symbol
|
|
cmp al,3Bh
|
|
je skip_macro_symbol
|
|
cmp al,22h
|
|
je skip_macro_string
|
|
or al,al
|
|
jz line_preprocessed
|
|
cmp al,'}'
|
|
jne skip_macro_block
|
|
mov al,[macro_status]
|
|
and [macro_status],0F0h
|
|
test al,8
|
|
jnz use_instant_macro
|
|
cmp byte [esi],0
|
|
je line_preprocessed
|
|
mov ecx,edi
|
|
sub ecx,esi
|
|
mov edx,esi
|
|
lea esi,[esi+ecx-1]
|
|
lea edi,[edi+1+16]
|
|
mov ebx,edi
|
|
dec edi
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
mov edi,edx
|
|
xor al,al
|
|
stos byte [edi]
|
|
mov esi,[current_line]
|
|
mov [current_line],edi
|
|
mov ecx,4
|
|
rep movs dword [edi],[esi]
|
|
mov edi,ebx
|
|
jmp initial_preprocessing_ok
|
|
skip_macro_symbol:
|
|
movzx eax,byte [esi]
|
|
inc esi
|
|
add esi,eax
|
|
jmp skip_macro_block
|
|
skip_macro_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp skip_macro_block
|
|
postpone_directive:
|
|
push esi
|
|
mov esi,edx
|
|
xor ecx,ecx
|
|
call add_preprocessor_symbol
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [edx+12],eax
|
|
pop esi
|
|
mov [edx+8],esi
|
|
mov al,[macro_status]
|
|
and al,0F0h
|
|
or al,1
|
|
mov [macro_status],al
|
|
lods byte [esi]
|
|
or al,al
|
|
jz line_preprocessed
|
|
cmp al,'{'
|
|
jne unexpected_characters
|
|
jmp found_macro_block
|
|
rept_directive:
|
|
mov [base_code],0
|
|
jmp define_instant_macro
|
|
irp_directive:
|
|
mov [base_code],1
|
|
jmp define_instant_macro
|
|
irps_directive:
|
|
mov [base_code],2
|
|
jmp define_instant_macro
|
|
irpv_directive:
|
|
mov [base_code],3
|
|
jmp define_instant_macro
|
|
match_directive:
|
|
mov [base_code],10h
|
|
define_instant_macro:
|
|
mov al,[macro_status]
|
|
and al,0F0h
|
|
or al,8+1
|
|
mov [macro_status],al
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [instant_macro_start],esi
|
|
cmp [base_code],10h
|
|
je prepare_match
|
|
skip_parameters:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz parameters_skipped
|
|
cmp al,'{'
|
|
je parameters_skipped
|
|
cmp al,22h
|
|
je skip_quoted_parameter
|
|
cmp al,1Ah
|
|
jne skip_parameters
|
|
lods byte [esi]
|
|
movzx eax,al
|
|
add esi,eax
|
|
jmp skip_parameters
|
|
skip_quoted_parameter:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp skip_parameters
|
|
parameters_skipped:
|
|
dec esi
|
|
mov [parameters_end],esi
|
|
lods byte [esi]
|
|
cmp al,'{'
|
|
je found_macro_block
|
|
or al,al
|
|
jnz invalid_macro_arguments
|
|
jmp line_preprocessed
|
|
prepare_match:
|
|
call skip_pattern
|
|
mov [value_type],80h+10b
|
|
call process_symbolic_constants
|
|
jmp parameters_skipped
|
|
skip_pattern:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz invalid_macro_arguments
|
|
cmp al,','
|
|
je pattern_skipped
|
|
cmp al,22h
|
|
je skip_quoted_string_in_pattern
|
|
cmp al,1Ah
|
|
je skip_symbol_in_pattern
|
|
cmp al,'='
|
|
jne skip_pattern
|
|
mov al,[esi]
|
|
cmp al,1Ah
|
|
je skip_pattern
|
|
cmp al,22h
|
|
je skip_pattern
|
|
inc esi
|
|
jmp skip_pattern
|
|
skip_symbol_in_pattern:
|
|
lods byte [esi]
|
|
movzx eax,al
|
|
add esi,eax
|
|
jmp skip_pattern
|
|
skip_quoted_string_in_pattern:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp skip_pattern
|
|
pattern_skipped:
|
|
ret
|
|
|
|
purge_macro:
|
|
xor ch,ch
|
|
jmp restore_preprocessor_symbol
|
|
purge_struc:
|
|
mov ch,1
|
|
jmp restore_preprocessor_symbol
|
|
restore_equ_constant:
|
|
mov ch,10b
|
|
restore_preprocessor_symbol:
|
|
push ecx
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_name
|
|
lods byte [esi]
|
|
mov cl,al
|
|
call get_preprocessor_symbol
|
|
jc no_symbol_to_restore
|
|
mov dword [edx+4],0
|
|
jmp symbol_restored
|
|
no_symbol_to_restore:
|
|
add esi,ecx
|
|
symbol_restored:
|
|
pop ecx
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je restore_preprocessor_symbol
|
|
or al,al
|
|
jnz extra_characters_on_line
|
|
jmp line_preprocessed
|
|
|
|
process_fix_constants:
|
|
mov [value_type],11b
|
|
jmp process_symbolic_constants
|
|
process_equ_constants:
|
|
mov [value_type],10b
|
|
process_symbolic_constants:
|
|
mov ebp,esi
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je check_symbol
|
|
cmp al,22h
|
|
je ignore_string
|
|
cmp al,'{'
|
|
je check_brace
|
|
or al,al
|
|
jnz process_symbolic_constants
|
|
ret
|
|
ignore_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp process_symbolic_constants
|
|
check_brace:
|
|
test [value_type],80h
|
|
jz process_symbolic_constants
|
|
ret
|
|
no_replacing:
|
|
movzx ecx,byte [esi-1]
|
|
add esi,ecx
|
|
jmp process_symbolic_constants
|
|
check_symbol:
|
|
mov cl,[esi]
|
|
inc esi
|
|
mov ch,[value_type]
|
|
call get_preprocessor_symbol
|
|
jc no_replacing
|
|
mov [current_section],edi
|
|
replace_symbolic_constant:
|
|
mov ecx,[edx+12]
|
|
mov edx,[edx+8]
|
|
xchg esi,edx
|
|
call move_data
|
|
mov esi,edx
|
|
process_after_replaced:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je symbol_after_replaced
|
|
stos byte [edi]
|
|
cmp al,22h
|
|
je string_after_replaced
|
|
cmp al,'{'
|
|
je brace_after_replaced
|
|
or al,al
|
|
jnz process_after_replaced
|
|
mov ecx,edi
|
|
sub ecx,esi
|
|
mov edi,ebp
|
|
call move_data
|
|
mov esi,edi
|
|
ret
|
|
move_data:
|
|
lea eax,[edi+ecx]
|
|
cmp eax,[memory_end]
|
|
jae out_of_memory
|
|
shr ecx,1
|
|
jnc movsb_ok
|
|
movs byte [edi],[esi]
|
|
movsb_ok:
|
|
shr ecx,1
|
|
jnc movsw_ok
|
|
movs word [edi],[esi]
|
|
movsw_ok:
|
|
rep movs dword [edi],[esi]
|
|
ret
|
|
string_after_replaced:
|
|
lods dword [esi]
|
|
stos dword [edi]
|
|
mov ecx,eax
|
|
call move_data
|
|
jmp process_after_replaced
|
|
brace_after_replaced:
|
|
test [value_type],80h
|
|
jz process_after_replaced
|
|
mov edx,edi
|
|
mov ecx,[current_section]
|
|
sub edx,ecx
|
|
sub ecx,esi
|
|
rep movs byte [edi],[esi]
|
|
mov ecx,edi
|
|
sub ecx,esi
|
|
mov edi,ebp
|
|
call move_data
|
|
lea esi,[ebp+edx]
|
|
ret
|
|
symbol_after_replaced:
|
|
mov cl,[esi]
|
|
inc esi
|
|
mov ch,[value_type]
|
|
call get_preprocessor_symbol
|
|
jnc replace_symbolic_constant
|
|
movzx ecx,byte [esi-1]
|
|
mov al,1Ah
|
|
mov ah,cl
|
|
stos word [edi]
|
|
call move_data
|
|
jmp process_after_replaced
|
|
process_macro_operators:
|
|
xor dl,dl
|
|
mov ebp,edi
|
|
before_macro_operators:
|
|
mov edi,esi
|
|
lods byte [esi]
|
|
cmp al,'`'
|
|
je symbol_conversion
|
|
cmp al,'#'
|
|
je concatenation
|
|
cmp al,1Ah
|
|
je symbol_before_macro_operators
|
|
cmp al,3Bh
|
|
je no_more_macro_operators
|
|
cmp al,22h
|
|
je string_before_macro_operators
|
|
xor dl,dl
|
|
or al,al
|
|
jnz before_macro_operators
|
|
mov edi,esi
|
|
ret
|
|
no_more_macro_operators:
|
|
mov edi,ebp
|
|
ret
|
|
symbol_before_macro_operators:
|
|
mov dl,1Ah
|
|
mov ebx,esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
jecxz symbol_before_macro_operators_ok
|
|
mov edi,esi
|
|
cmp byte [esi],'\'
|
|
je escaped_symbol
|
|
symbol_before_macro_operators_ok:
|
|
add esi,ecx
|
|
jmp before_macro_operators
|
|
string_before_macro_operators:
|
|
mov dl,22h
|
|
mov ebx,esi
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp before_macro_operators
|
|
escaped_symbol:
|
|
dec byte [edi-1]
|
|
dec ecx
|
|
inc esi
|
|
cmp ecx,1
|
|
rep movs byte [edi],[esi]
|
|
jne after_macro_operators
|
|
mov al,[esi-1]
|
|
mov ecx,ebx
|
|
mov ebx,characters
|
|
xlat byte [ebx]
|
|
mov ebx,ecx
|
|
or al,al
|
|
jnz after_macro_operators
|
|
sub edi,3
|
|
mov al,[esi-1]
|
|
stos byte [edi]
|
|
xor dl,dl
|
|
jmp after_macro_operators
|
|
reduce_symbol_conversion:
|
|
inc esi
|
|
symbol_conversion:
|
|
mov edx,esi
|
|
mov al,[esi]
|
|
cmp al,1Ah
|
|
jne symbol_character_conversion
|
|
lods word [esi]
|
|
movzx ecx,ah
|
|
lea ebx,[edi+3]
|
|
jecxz convert_to_quoted_string
|
|
cmp byte [esi],'\'
|
|
jne convert_to_quoted_string
|
|
inc esi
|
|
dec ecx
|
|
dec ebx
|
|
jmp convert_to_quoted_string
|
|
symbol_character_conversion:
|
|
cmp al,22h
|
|
je after_macro_operators
|
|
cmp al,'`'
|
|
je reduce_symbol_conversion
|
|
lea ebx,[edi+5]
|
|
xor ecx,ecx
|
|
or al,al
|
|
jz convert_to_quoted_string
|
|
cmp al,'#'
|
|
je convert_to_quoted_string
|
|
inc ecx
|
|
convert_to_quoted_string:
|
|
sub ebx,edx
|
|
ja shift_line_data
|
|
mov al,22h
|
|
mov dl,al
|
|
stos byte [edi]
|
|
mov ebx,edi
|
|
mov eax,ecx
|
|
stos dword [edi]
|
|
rep movs byte [edi],[esi]
|
|
cmp edi,esi
|
|
je before_macro_operators
|
|
jmp after_macro_operators
|
|
shift_line_data:
|
|
push ecx
|
|
mov edx,esi
|
|
lea esi,[ebp-1]
|
|
add ebp,ebx
|
|
lea edi,[ebp-1]
|
|
lea ecx,[esi+1]
|
|
sub ecx,edx
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
pop eax
|
|
sub edi,3
|
|
mov dl,22h
|
|
mov [edi-1],dl
|
|
mov ebx,edi
|
|
mov [edi],eax
|
|
lea esi,[edi+4+eax]
|
|
jmp before_macro_operators
|
|
concatenation:
|
|
cmp dl,1Ah
|
|
je symbol_concatenation
|
|
cmp dl,22h
|
|
je string_concatenation
|
|
no_concatenation:
|
|
cmp esi,edi
|
|
je before_macro_operators
|
|
jmp after_macro_operators
|
|
symbol_concatenation:
|
|
cmp byte [esi],1Ah
|
|
jne no_concatenation
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
jecxz do_symbol_concatenation
|
|
cmp byte [esi],'\'
|
|
je concatenate_escaped_symbol
|
|
do_symbol_concatenation:
|
|
add [ebx],cl
|
|
jc name_too_long
|
|
rep movs byte [edi],[esi]
|
|
jmp after_macro_operators
|
|
concatenate_escaped_symbol:
|
|
inc esi
|
|
dec ecx
|
|
jz do_symbol_concatenation
|
|
movzx eax,byte [esi]
|
|
cmp byte [characters+eax],0
|
|
jne do_symbol_concatenation
|
|
sub esi,3
|
|
jmp no_concatenation
|
|
string_concatenation:
|
|
cmp byte [esi],22h
|
|
je do_string_concatenation
|
|
cmp byte [esi],'`'
|
|
jne no_concatenation
|
|
concatenate_converted_symbol:
|
|
inc esi
|
|
mov al,[esi]
|
|
cmp al,'`'
|
|
je concatenate_converted_symbol
|
|
cmp al,22h
|
|
je do_string_concatenation
|
|
cmp al,1Ah
|
|
jne concatenate_converted_symbol_character
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
jecxz finish_concatenating_converted_symbol
|
|
cmp byte [esi],'\'
|
|
jne finish_concatenating_converted_symbol
|
|
inc esi
|
|
dec ecx
|
|
finish_concatenating_converted_symbol:
|
|
add [ebx],ecx
|
|
rep movs byte [edi],[esi]
|
|
jmp after_macro_operators
|
|
concatenate_converted_symbol_character:
|
|
or al,al
|
|
jz after_macro_operators
|
|
cmp al,'#'
|
|
je after_macro_operators
|
|
inc dword [ebx]
|
|
movs byte [edi],[esi]
|
|
jmp after_macro_operators
|
|
do_string_concatenation:
|
|
inc esi
|
|
lods dword [esi]
|
|
mov ecx,eax
|
|
add [ebx],eax
|
|
rep movs byte [edi],[esi]
|
|
after_macro_operators:
|
|
lods byte [esi]
|
|
cmp al,'`'
|
|
je symbol_conversion
|
|
cmp al,'#'
|
|
je concatenation
|
|
stos byte [edi]
|
|
cmp al,1Ah
|
|
je symbol_after_macro_operators
|
|
cmp al,3Bh
|
|
je no_more_macro_operators
|
|
cmp al,22h
|
|
je string_after_macro_operators
|
|
xor dl,dl
|
|
or al,al
|
|
jnz after_macro_operators
|
|
ret
|
|
symbol_after_macro_operators:
|
|
mov dl,1Ah
|
|
mov ebx,edi
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
movzx ecx,al
|
|
jecxz symbol_after_macro_operatorss_ok
|
|
cmp byte [esi],'\'
|
|
je escaped_symbol
|
|
symbol_after_macro_operatorss_ok:
|
|
rep movs byte [edi],[esi]
|
|
jmp after_macro_operators
|
|
string_after_macro_operators:
|
|
mov dl,22h
|
|
mov ebx,edi
|
|
lods dword [esi]
|
|
stos dword [edi]
|
|
mov ecx,eax
|
|
rep movs byte [edi],[esi]
|
|
jmp after_macro_operators
|
|
|
|
use_macro:
|
|
push [free_additional_memory]
|
|
push [macro_symbols]
|
|
mov [macro_symbols],0
|
|
push [counter_limit]
|
|
push dword [edx+4]
|
|
mov dword [edx+4],1
|
|
push edx
|
|
mov ebx,esi
|
|
mov esi,[edx+8]
|
|
mov eax,[edx+12]
|
|
mov [macro_line],eax
|
|
mov [counter_limit],0
|
|
xor ebp,ebp
|
|
process_macro_arguments:
|
|
mov al,[esi]
|
|
or al,al
|
|
jz arguments_end
|
|
cmp al,'{'
|
|
je arguments_end
|
|
inc esi
|
|
cmp al,'['
|
|
jne get_macro_arguments
|
|
mov ebp,esi
|
|
inc esi
|
|
inc [counter_limit]
|
|
get_macro_arguments:
|
|
call get_macro_argument
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je next_argument
|
|
cmp al,']'
|
|
je next_arguments_group
|
|
cmp al,'&'
|
|
je arguments_end
|
|
dec esi
|
|
jmp arguments_end
|
|
next_argument:
|
|
cmp byte [ebx],','
|
|
jne process_macro_arguments
|
|
inc ebx
|
|
jmp process_macro_arguments
|
|
next_arguments_group:
|
|
cmp byte [ebx],','
|
|
jne arguments_end
|
|
inc ebx
|
|
inc [counter_limit]
|
|
mov esi,ebp
|
|
jmp process_macro_arguments
|
|
get_macro_argument:
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
mov eax,[counter_limit]
|
|
call add_macro_symbol
|
|
add esi,ecx
|
|
xor eax,eax
|
|
mov [default_argument_value],eax
|
|
cmp byte [esi],'*'
|
|
je required_value
|
|
cmp byte [esi],':'
|
|
je get_default_value
|
|
cmp byte [esi],'='
|
|
jne default_value_ok
|
|
get_default_value:
|
|
inc esi
|
|
mov [default_argument_value],esi
|
|
or [skip_default_argument_value],-1
|
|
call skip_macro_argument_value
|
|
jmp default_value_ok
|
|
required_value:
|
|
inc esi
|
|
or [default_argument_value],-1
|
|
default_value_ok:
|
|
xchg esi,ebx
|
|
mov [edx+12],esi
|
|
mov [skip_default_argument_value],0
|
|
cmp byte [ebx],'&'
|
|
je greedy_macro_argument
|
|
call skip_macro_argument_value
|
|
call finish_macro_argument
|
|
jmp got_macro_argument
|
|
greedy_macro_argument:
|
|
call skip_foreign_line
|
|
dec esi
|
|
mov eax,[edx+12]
|
|
mov ecx,esi
|
|
sub ecx,eax
|
|
mov [edx+8],ecx
|
|
got_macro_argument:
|
|
xchg esi,ebx
|
|
cmp dword [edx+8],0
|
|
jne macro_argument_ok
|
|
mov eax,[default_argument_value]
|
|
or eax,eax
|
|
jz macro_argument_ok
|
|
cmp eax,-1
|
|
je invalid_macro_arguments
|
|
mov [edx+12],eax
|
|
call finish_macro_argument
|
|
macro_argument_ok:
|
|
ret
|
|
finish_macro_argument:
|
|
mov eax,[edx+12]
|
|
mov ecx,esi
|
|
sub ecx,eax
|
|
cmp byte [eax],'<'
|
|
jne argument_value_length_ok
|
|
inc dword [edx+12]
|
|
sub ecx,2
|
|
or ecx,80000000h
|
|
argument_value_length_ok:
|
|
mov [edx+8],ecx
|
|
ret
|
|
arguments_end:
|
|
cmp byte [ebx],0
|
|
jne invalid_macro_arguments
|
|
mov eax,[esp+4]
|
|
dec eax
|
|
call process_macro
|
|
pop edx
|
|
pop dword [edx+4]
|
|
pop [counter_limit]
|
|
pop [macro_symbols]
|
|
pop [free_additional_memory]
|
|
jmp line_preprocessed
|
|
use_instant_macro:
|
|
push edi [current_line] esi
|
|
mov eax,[error_line]
|
|
mov [current_line],eax
|
|
mov [macro_line],eax
|
|
mov esi,[instant_macro_start]
|
|
cmp [base_code],10h
|
|
jae do_match
|
|
cmp [base_code],0
|
|
jne do_irp
|
|
call precalculate_value
|
|
cmp eax,0
|
|
jl value_out_of_range
|
|
push [free_additional_memory]
|
|
push [macro_symbols]
|
|
mov [macro_symbols],0
|
|
push [counter_limit]
|
|
mov [struc_name],0
|
|
mov [counter_limit],eax
|
|
lods byte [esi]
|
|
or al,al
|
|
jz rept_counters_ok
|
|
cmp al,'{'
|
|
je rept_counters_ok
|
|
cmp al,1Ah
|
|
jne invalid_macro_arguments
|
|
add_rept_counter:
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
xor eax,eax
|
|
call add_macro_symbol
|
|
add esi,ecx
|
|
xor eax,eax
|
|
mov dword [edx+12],eax
|
|
inc eax
|
|
mov dword [edx+8],eax
|
|
lods byte [esi]
|
|
cmp al,':'
|
|
jne rept_counter_added
|
|
push edx
|
|
call precalculate_value
|
|
mov edx,eax
|
|
add edx,[counter_limit]
|
|
jo value_out_of_range
|
|
pop edx
|
|
mov dword [edx+8],eax
|
|
lods byte [esi]
|
|
rept_counter_added:
|
|
cmp al,','
|
|
jne rept_counters_ok
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_macro_arguments
|
|
jmp add_rept_counter
|
|
rept_counters_ok:
|
|
dec esi
|
|
cmp [counter_limit],0
|
|
je instant_macro_finish
|
|
instant_macro_parameters_ok:
|
|
xor eax,eax
|
|
call process_macro
|
|
instant_macro_finish:
|
|
pop [counter_limit]
|
|
pop [macro_symbols]
|
|
pop [free_additional_memory]
|
|
instant_macro_done:
|
|
pop ebx esi edx
|
|
cmp byte [ebx],0
|
|
je line_preprocessed
|
|
mov [current_line],edi
|
|
mov ecx,4
|
|
rep movs dword [edi],[esi]
|
|
test [macro_status],0Fh
|
|
jz instant_macro_attached_line
|
|
mov ax,3Bh
|
|
stos word [edi]
|
|
instant_macro_attached_line:
|
|
mov esi,ebx
|
|
sub edx,ebx
|
|
mov ecx,edx
|
|
call move_data
|
|
jmp initial_preprocessing_ok
|
|
precalculate_value:
|
|
push edi
|
|
call convert_expression
|
|
mov al,')'
|
|
stosb
|
|
push esi
|
|
mov esi,[esp+4]
|
|
mov [error_line],0
|
|
mov [value_size],0
|
|
call calculate_expression
|
|
cmp [error_line],0
|
|
je value_precalculated
|
|
jmp [error]
|
|
value_precalculated:
|
|
mov eax,[edi]
|
|
mov ecx,[edi+4]
|
|
cdq
|
|
cmp edx,ecx
|
|
jne value_out_of_range
|
|
cmp dl,[edi+13]
|
|
jne value_out_of_range
|
|
pop esi edi
|
|
ret
|
|
do_irp:
|
|
cmp byte [esi],1Ah
|
|
jne invalid_macro_arguments
|
|
movzx eax,byte [esi+1]
|
|
lea esi,[esi+2+eax]
|
|
lods byte [esi]
|
|
cmp [base_code],1
|
|
ja irps_name_ok
|
|
cmp al,':'
|
|
je irp_with_default_value
|
|
cmp al,'='
|
|
je irp_with_default_value
|
|
cmp al,'*'
|
|
jne irp_name_ok
|
|
lods byte [esi]
|
|
irp_name_ok:
|
|
cmp al,','
|
|
jne invalid_macro_arguments
|
|
jmp irp_parameters_start
|
|
irp_with_default_value:
|
|
xor ebp,ebp
|
|
or [skip_default_argument_value],-1
|
|
call skip_macro_argument_value
|
|
cmp byte [esi],','
|
|
jne invalid_macro_arguments
|
|
inc esi
|
|
jmp irp_parameters_start
|
|
irps_name_ok:
|
|
cmp al,','
|
|
jne invalid_macro_arguments
|
|
cmp [base_code],3
|
|
je irp_parameters_start
|
|
mov al,[esi]
|
|
or al,al
|
|
jz instant_macro_done
|
|
cmp al,'{'
|
|
je instant_macro_done
|
|
irp_parameters_start:
|
|
xor eax,eax
|
|
push [free_additional_memory]
|
|
push [macro_symbols]
|
|
mov [macro_symbols],eax
|
|
push [counter_limit]
|
|
mov [counter_limit],eax
|
|
mov [struc_name],eax
|
|
cmp [base_code],3
|
|
je get_irpv_parameter
|
|
mov ebx,esi
|
|
cmp [base_code],2
|
|
je get_irps_parameter
|
|
mov edx,[parameters_end]
|
|
mov al,[edx]
|
|
push eax
|
|
mov byte [edx],0
|
|
get_irp_parameter:
|
|
inc [counter_limit]
|
|
mov esi,[instant_macro_start]
|
|
inc esi
|
|
call get_macro_argument
|
|
cmp byte [ebx],','
|
|
jne irp_parameters_end
|
|
inc ebx
|
|
jmp get_irp_parameter
|
|
irp_parameters_end:
|
|
mov esi,ebx
|
|
pop eax
|
|
mov [esi],al
|
|
jmp instant_macro_parameters_ok
|
|
get_irps_parameter:
|
|
mov esi,[instant_macro_start]
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
inc [counter_limit]
|
|
mov eax,[counter_limit]
|
|
call add_macro_symbol
|
|
mov [edx+12],ebx
|
|
cmp byte [ebx],1Ah
|
|
je irps_symbol
|
|
cmp byte [ebx],22h
|
|
je irps_quoted_string
|
|
mov eax,1
|
|
jmp irps_parameter_ok
|
|
irps_quoted_string:
|
|
mov eax,[ebx+1]
|
|
add eax,1+4
|
|
jmp irps_parameter_ok
|
|
irps_symbol:
|
|
movzx eax,byte [ebx+1]
|
|
add eax,1+1
|
|
irps_parameter_ok:
|
|
mov [edx+8],eax
|
|
add ebx,eax
|
|
cmp byte [ebx],0
|
|
je irps_parameters_end
|
|
cmp byte [ebx],'{'
|
|
jne get_irps_parameter
|
|
irps_parameters_end:
|
|
mov esi,ebx
|
|
jmp instant_macro_parameters_ok
|
|
get_irpv_parameter:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_macro_arguments
|
|
lods byte [esi]
|
|
mov ebp,esi
|
|
mov cl,al
|
|
mov ch,10b
|
|
call get_preprocessor_symbol
|
|
jc instant_macro_finish
|
|
push edx
|
|
mark_variable_value:
|
|
inc [counter_limit]
|
|
mov [edx+4],ebp
|
|
next_variable_value:
|
|
mov edx,[edx]
|
|
or edx,edx
|
|
jz variable_values_marked
|
|
mov eax,[edx+4]
|
|
cmp eax,1
|
|
jbe next_variable_value
|
|
mov esi,ebp
|
|
movzx ecx,byte [esi-1]
|
|
xchg edi,eax
|
|
repe cmps byte [esi],[edi]
|
|
xchg edi,eax
|
|
je mark_variable_value
|
|
jmp next_variable_value
|
|
variable_values_marked:
|
|
pop edx
|
|
push [counter_limit]
|
|
add_irpv_value:
|
|
push edx
|
|
mov esi,[instant_macro_start]
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
mov eax,[esp+4]
|
|
call add_macro_symbol
|
|
mov ebx,edx
|
|
pop edx
|
|
mov ecx,[edx+12]
|
|
mov eax,[edx+8]
|
|
mov [ebx+12],eax
|
|
mov [ebx+8],ecx
|
|
collect_next_variable_value:
|
|
mov edx,[edx]
|
|
or edx,edx
|
|
jz variable_values_collected
|
|
cmp ebp,[edx+4]
|
|
jne collect_next_variable_value
|
|
dec dword [esp]
|
|
jnz add_irpv_value
|
|
variable_values_collected:
|
|
pop eax
|
|
mov esi,ebp
|
|
movzx ecx,byte [esi-1]
|
|
add esi,ecx
|
|
cmp byte [esi],0
|
|
je instant_macro_parameters_ok
|
|
cmp byte [esi],'{'
|
|
jne invalid_macro_arguments
|
|
jmp instant_macro_parameters_ok
|
|
|
|
do_match:
|
|
mov ebx,esi
|
|
call skip_pattern
|
|
call exact_match
|
|
mov edx,edi
|
|
mov al,[ebx]
|
|
cmp al,1Ah
|
|
je free_match
|
|
cmp al,','
|
|
jne instant_macro_done
|
|
cmp esi,[parameters_end]
|
|
je matched_pattern
|
|
jmp instant_macro_done
|
|
free_match:
|
|
add edx,12
|
|
cmp edx,[memory_end]
|
|
ja out_of_memory
|
|
mov [edx-12],ebx
|
|
mov [edx-8],esi
|
|
call skip_match_element
|
|
jc try_different_matching
|
|
mov [edx-4],esi
|
|
movzx eax,byte [ebx+1]
|
|
lea ebx,[ebx+2+eax]
|
|
cmp byte [ebx],1Ah
|
|
je free_match
|
|
find_exact_match:
|
|
call exact_match
|
|
cmp esi,[parameters_end]
|
|
je end_matching
|
|
cmp byte [ebx],1Ah
|
|
je free_match
|
|
mov ebx,[edx-12]
|
|
movzx eax,byte [ebx+1]
|
|
lea ebx,[ebx+2+eax]
|
|
mov esi,[edx-4]
|
|
jmp match_more_elements
|
|
try_different_matching:
|
|
sub edx,12
|
|
cmp edx,edi
|
|
je instant_macro_done
|
|
mov ebx,[edx-12]
|
|
movzx eax,byte [ebx+1]
|
|
lea ebx,[ebx+2+eax]
|
|
cmp byte [ebx],1Ah
|
|
je try_different_matching
|
|
mov esi,[edx-4]
|
|
match_more_elements:
|
|
call skip_match_element
|
|
jc try_different_matching
|
|
mov [edx-4],esi
|
|
jmp find_exact_match
|
|
skip_match_element:
|
|
cmp esi,[parameters_end]
|
|
je cannot_match
|
|
mov al,[esi]
|
|
cmp al,1Ah
|
|
je skip_match_symbol
|
|
cmp al,22h
|
|
je skip_match_quoted_string
|
|
add esi,1
|
|
ret
|
|
skip_match_quoted_string:
|
|
mov eax,[esi+1]
|
|
add esi,5
|
|
jmp skip_match_ok
|
|
skip_match_symbol:
|
|
movzx eax,byte [esi+1]
|
|
add esi,2
|
|
skip_match_ok:
|
|
add esi,eax
|
|
ret
|
|
cannot_match:
|
|
stc
|
|
ret
|
|
exact_match:
|
|
cmp esi,[parameters_end]
|
|
je exact_match_complete
|
|
mov ah,[esi]
|
|
mov al,[ebx]
|
|
cmp al,','
|
|
je exact_match_complete
|
|
cmp al,1Ah
|
|
je exact_match_complete
|
|
cmp al,'='
|
|
je match_verbatim
|
|
call match_elements
|
|
je exact_match
|
|
exact_match_complete:
|
|
ret
|
|
match_verbatim:
|
|
inc ebx
|
|
call match_elements
|
|
je exact_match
|
|
dec ebx
|
|
ret
|
|
match_elements:
|
|
mov al,[ebx]
|
|
cmp al,1Ah
|
|
je match_symbols
|
|
cmp al,22h
|
|
je match_quoted_strings
|
|
cmp al,ah
|
|
je symbol_characters_matched
|
|
ret
|
|
symbol_characters_matched:
|
|
lea ebx,[ebx+1]
|
|
lea esi,[esi+1]
|
|
ret
|
|
match_quoted_strings:
|
|
mov ecx,[ebx+1]
|
|
add ecx,5
|
|
jmp compare_elements
|
|
match_symbols:
|
|
movzx ecx,byte [ebx+1]
|
|
add ecx,2
|
|
compare_elements:
|
|
mov eax,esi
|
|
mov ebp,edi
|
|
mov edi,ebx
|
|
repe cmps byte [esi],[edi]
|
|
jne elements_mismatch
|
|
mov ebx,edi
|
|
mov edi,ebp
|
|
ret
|
|
elements_mismatch:
|
|
mov esi,eax
|
|
mov edi,ebp
|
|
ret
|
|
end_matching:
|
|
cmp byte [ebx],','
|
|
jne instant_macro_done
|
|
matched_pattern:
|
|
xor eax,eax
|
|
push [free_additional_memory]
|
|
push [macro_symbols]
|
|
mov [macro_symbols],eax
|
|
push [counter_limit]
|
|
mov [counter_limit],eax
|
|
mov [struc_name],eax
|
|
push esi edi edx
|
|
add_matched_symbol:
|
|
cmp edi,[esp]
|
|
je matched_symbols_ok
|
|
mov esi,[edi]
|
|
inc esi
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
xor eax,eax
|
|
call add_macro_symbol
|
|
mov eax,[edi+4]
|
|
mov dword [edx+12],eax
|
|
mov ecx,[edi+8]
|
|
sub ecx,eax
|
|
mov dword [edx+8],ecx
|
|
add edi,12
|
|
jmp add_matched_symbol
|
|
matched_symbols_ok:
|
|
pop edx edi esi
|
|
jmp instant_macro_parameters_ok
|
|
|
|
process_macro:
|
|
push dword [macro_status]
|
|
or [macro_status],10h
|
|
push [counter]
|
|
push [macro_block]
|
|
push [macro_block_line]
|
|
push [macro_block_line_number]
|
|
push [struc_label]
|
|
push [struc_name]
|
|
push eax
|
|
push [current_line]
|
|
lods byte [esi]
|
|
cmp al,'{'
|
|
je macro_instructions_start
|
|
or al,al
|
|
jnz unexpected_characters
|
|
find_macro_instructions:
|
|
mov [macro_line],esi
|
|
add esi,16+2
|
|
lods byte [esi]
|
|
or al,al
|
|
jz find_macro_instructions
|
|
cmp al,'{'
|
|
je macro_instructions_start
|
|
cmp al,3Bh
|
|
jne unexpected_characters
|
|
call skip_foreign_symbol
|
|
jmp find_macro_instructions
|
|
macro_instructions_start:
|
|
mov ecx,80000000h
|
|
mov [macro_block],esi
|
|
mov eax,[macro_line]
|
|
mov [macro_block_line],eax
|
|
mov [macro_block_line_number],ecx
|
|
xor eax,eax
|
|
mov [counter],eax
|
|
cmp [counter_limit],eax
|
|
je process_macro_line
|
|
inc [counter]
|
|
process_macro_line:
|
|
lods byte [esi]
|
|
or al,al
|
|
jz process_next_line
|
|
cmp al,'}'
|
|
je macro_block_processed
|
|
dec esi
|
|
mov [current_line],edi
|
|
lea eax,[edi+10h]
|
|
cmp eax,[memory_end]
|
|
jae out_of_memory
|
|
mov eax,[esp+4]
|
|
or eax,eax
|
|
jz instant_macro_line_header
|
|
stos dword [edi]
|
|
mov eax,ecx
|
|
stos dword [edi]
|
|
mov eax,[esp]
|
|
stos dword [edi]
|
|
mov eax,[macro_line]
|
|
stos dword [edi]
|
|
jmp macro_line_header_ok
|
|
instant_macro_line_header:
|
|
mov eax,[esp]
|
|
add eax,16
|
|
find_defining_directive:
|
|
inc eax
|
|
cmp byte [eax-1],3Bh
|
|
je defining_directive_ok
|
|
cmp byte [eax-1],1Ah
|
|
jne find_defining_directive
|
|
push eax
|
|
movzx eax,byte [eax]
|
|
inc eax
|
|
add [esp],eax
|
|
pop eax
|
|
jmp find_defining_directive
|
|
defining_directive_ok:
|
|
stos dword [edi]
|
|
mov eax,ecx
|
|
stos dword [edi]
|
|
mov eax,[macro_line]
|
|
stos dword [edi]
|
|
stos dword [edi]
|
|
macro_line_header_ok:
|
|
or [macro_status],20h
|
|
push ebx ecx
|
|
test [macro_status],0Fh
|
|
jz process_macro_line_element
|
|
mov ax,3Bh
|
|
stos word [edi]
|
|
process_macro_line_element:
|
|
lea eax,[edi+100h]
|
|
cmp eax,[memory_end]
|
|
jae out_of_memory
|
|
lods byte [esi]
|
|
cmp al,'}'
|
|
je macro_line_processed
|
|
or al,al
|
|
jz macro_line_processed
|
|
cmp al,1Ah
|
|
je process_macro_symbol
|
|
cmp al,3Bh
|
|
je macro_foreign_line
|
|
and [macro_status],not 20h
|
|
stos byte [edi]
|
|
cmp al,22h
|
|
jne process_macro_line_element
|
|
copy_macro_string:
|
|
mov ecx,[esi]
|
|
add ecx,4
|
|
call move_data
|
|
jmp process_macro_line_element
|
|
process_macro_symbol:
|
|
push esi edi
|
|
test [macro_status],20h
|
|
jz not_macro_directive
|
|
movzx ecx,byte [esi]
|
|
inc esi
|
|
mov edi,macro_directives
|
|
call get_directive
|
|
jnc process_macro_directive
|
|
dec esi
|
|
jmp not_macro_directive
|
|
process_macro_directive:
|
|
mov edx,eax
|
|
pop edi eax
|
|
mov byte [edi],0
|
|
inc edi
|
|
pop ecx ebx
|
|
jmp near edx
|
|
not_macro_directive:
|
|
and [macro_status],not 20h
|
|
movzx ecx,byte [esi]
|
|
inc esi
|
|
mov eax,[counter]
|
|
call get_macro_symbol
|
|
jnc group_macro_symbol
|
|
xor eax,eax
|
|
cmp [counter],eax
|
|
je multiple_macro_symbol_values
|
|
call get_macro_symbol
|
|
jc not_macro_symbol
|
|
replace_macro_symbol:
|
|
pop edi eax
|
|
mov ecx,[edx+8]
|
|
mov edx,[edx+12]
|
|
or edx,edx
|
|
jz replace_macro_counter
|
|
and ecx,not 80000000h
|
|
xchg esi,edx
|
|
call move_data
|
|
mov esi,edx
|
|
jmp process_macro_line_element
|
|
group_macro_symbol:
|
|
xor eax,eax
|
|
cmp [counter],eax
|
|
je replace_macro_symbol
|
|
push esi edx
|
|
sub esi,ecx
|
|
call get_macro_symbol
|
|
mov ebx,edx
|
|
pop edx esi
|
|
jc replace_macro_symbol
|
|
cmp edx,ebx
|
|
ja replace_macro_symbol
|
|
mov edx,ebx
|
|
jmp replace_macro_symbol
|
|
multiple_macro_symbol_values:
|
|
inc eax
|
|
push eax
|
|
call get_macro_symbol
|
|
pop eax
|
|
jc not_macro_symbol
|
|
pop edi
|
|
push ecx
|
|
mov ecx,[edx+8]
|
|
mov edx,[edx+12]
|
|
xchg esi,edx
|
|
btr ecx,31
|
|
jc enclose_macro_symbol_value
|
|
rep movs byte [edi],[esi]
|
|
jmp macro_symbol_value_ok
|
|
enclose_macro_symbol_value:
|
|
mov byte [edi],'<'
|
|
inc edi
|
|
rep movs byte [edi],[esi]
|
|
mov byte [edi],'>'
|
|
inc edi
|
|
macro_symbol_value_ok:
|
|
cmp eax,[counter_limit]
|
|
je multiple_macro_symbol_values_ok
|
|
mov byte [edi],','
|
|
inc edi
|
|
mov esi,edx
|
|
pop ecx
|
|
push edi
|
|
sub esi,ecx
|
|
jmp multiple_macro_symbol_values
|
|
multiple_macro_symbol_values_ok:
|
|
pop ecx eax
|
|
mov esi,edx
|
|
jmp process_macro_line_element
|
|
replace_macro_counter:
|
|
mov eax,[counter]
|
|
and eax,not 80000000h
|
|
jz group_macro_counter
|
|
add ecx,eax
|
|
dec ecx
|
|
call store_number_symbol
|
|
jmp process_macro_line_element
|
|
group_macro_counter:
|
|
mov edx,ecx
|
|
xor ecx,ecx
|
|
multiple_macro_counter_values:
|
|
push ecx edx
|
|
add ecx,edx
|
|
call store_number_symbol
|
|
pop edx ecx
|
|
inc ecx
|
|
cmp ecx,[counter_limit]
|
|
je process_macro_line_element
|
|
mov byte [edi],','
|
|
inc edi
|
|
jmp multiple_macro_counter_values
|
|
store_number_symbol:
|
|
cmp ecx,0
|
|
jge numer_symbol_sign_ok
|
|
neg ecx
|
|
mov al,'-'
|
|
stos byte [edi]
|
|
numer_symbol_sign_ok:
|
|
mov ax,1Ah
|
|
stos word [edi]
|
|
push edi
|
|
mov eax,ecx
|
|
mov ecx,1000000000
|
|
xor edx,edx
|
|
xor bl,bl
|
|
store_number_digits:
|
|
div ecx
|
|
push edx
|
|
or bl,bl
|
|
jnz store_number_digit
|
|
cmp ecx,1
|
|
je store_number_digit
|
|
or al,al
|
|
jz number_digit_ok
|
|
not bl
|
|
store_number_digit:
|
|
add al,30h
|
|
stos byte [edi]
|
|
number_digit_ok:
|
|
mov eax,ecx
|
|
xor edx,edx
|
|
mov ecx,10
|
|
div ecx
|
|
mov ecx,eax
|
|
pop eax
|
|
or ecx,ecx
|
|
jnz store_number_digits
|
|
pop ebx
|
|
mov eax,edi
|
|
sub eax,ebx
|
|
mov [ebx-1],al
|
|
ret
|
|
not_macro_symbol:
|
|
pop edi esi
|
|
mov al,1Ah
|
|
stos byte [edi]
|
|
mov al,[esi]
|
|
inc esi
|
|
stos byte [edi]
|
|
cmp byte [esi],'.'
|
|
jne copy_raw_symbol
|
|
mov ebx,[esp+8+8]
|
|
or ebx,ebx
|
|
jz copy_raw_symbol
|
|
cmp al,1
|
|
je copy_struc_name
|
|
xchg esi,ebx
|
|
movzx ecx,byte [esi-1]
|
|
add [edi-1],cl
|
|
jc name_too_long
|
|
rep movs byte [edi],[esi]
|
|
xchg esi,ebx
|
|
copy_raw_symbol:
|
|
movzx ecx,al
|
|
rep movs byte [edi],[esi]
|
|
jmp process_macro_line_element
|
|
copy_struc_name:
|
|
inc esi
|
|
xchg esi,ebx
|
|
movzx ecx,byte [esi-1]
|
|
mov [edi-1],cl
|
|
rep movs byte [edi],[esi]
|
|
xchg esi,ebx
|
|
mov eax,[esp+8+12]
|
|
cmp byte [eax],3Bh
|
|
je process_macro_line_element
|
|
cmp byte [eax],1Ah
|
|
jne disable_replaced_struc_name
|
|
mov byte [eax],3Bh
|
|
jmp process_macro_line_element
|
|
disable_replaced_struc_name:
|
|
mov ebx,[esp+8+8]
|
|
push esi edi
|
|
lea edi,[ebx-3]
|
|
lea esi,[edi-2]
|
|
lea ecx,[esi+1]
|
|
sub ecx,eax
|
|
std
|
|
rep movs byte [edi],[esi]
|
|
cld
|
|
mov word [eax],3Bh
|
|
pop edi esi
|
|
jmp process_macro_line_element
|
|
skip_foreign_symbol:
|
|
lods byte [esi]
|
|
movzx eax,al
|
|
add esi,eax
|
|
skip_foreign_line:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je skip_foreign_symbol
|
|
cmp al,3Bh
|
|
je skip_foreign_symbol
|
|
cmp al,22h
|
|
je skip_foreign_string
|
|
or al,al
|
|
jnz skip_foreign_line
|
|
ret
|
|
skip_foreign_string:
|
|
lods dword [esi]
|
|
add esi,eax
|
|
jmp skip_foreign_line
|
|
macro_foreign_line:
|
|
call skip_foreign_symbol
|
|
macro_line_processed:
|
|
mov byte [edi],0
|
|
inc edi
|
|
push eax
|
|
call preprocess_line
|
|
pop eax
|
|
pop ecx ebx
|
|
cmp al,'}'
|
|
je macro_block_processed
|
|
process_next_line:
|
|
inc ecx
|
|
mov [macro_line],esi
|
|
add esi,16+2
|
|
jmp process_macro_line
|
|
macro_block_processed:
|
|
call close_macro_block
|
|
jc process_macro_line
|
|
pop [current_line]
|
|
add esp,12
|
|
pop [macro_block_line_number]
|
|
pop [macro_block_line]
|
|
pop [macro_block]
|
|
pop [counter]
|
|
pop eax
|
|
and al,0F0h
|
|
and [macro_status],0Fh
|
|
or [macro_status],al
|
|
ret
|
|
|
|
local_symbols:
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
jne invalid_argument
|
|
mov byte [edi-1],3Bh
|
|
xor al,al
|
|
stos byte [edi]
|
|
make_local_symbol:
|
|
push ecx
|
|
lods byte [esi]
|
|
movzx ecx,al
|
|
mov eax,[counter]
|
|
call add_macro_symbol
|
|
mov [edx+12],edi
|
|
movzx eax,[locals_counter]
|
|
add eax,ecx
|
|
inc eax
|
|
cmp eax,100h
|
|
jae name_too_long
|
|
lea ebp,[edi+2+eax]
|
|
cmp ebp,[memory_end]
|
|
jae out_of_memory
|
|
mov ah,al
|
|
mov al,1Ah
|
|
stos word [edi]
|
|
rep movs byte [edi],[esi]
|
|
mov al,'?'
|
|
stos byte [edi]
|
|
push esi
|
|
mov esi,locals_counter+1
|
|
movzx ecx,[locals_counter]
|
|
rep movs byte [edi],[esi]
|
|
pop esi
|
|
mov eax,edi
|
|
sub eax,[edx+12]
|
|
mov [edx+8],eax
|
|
xor al,al
|
|
stos byte [edi]
|
|
mov eax,locals_counter
|
|
movzx ecx,byte [eax]
|
|
counter_loop:
|
|
inc byte [eax+ecx]
|
|
cmp byte [eax+ecx],'9'+1
|
|
jb counter_ok
|
|
jne letter_digit
|
|
mov byte [eax+ecx],'A'
|
|
jmp counter_ok
|
|
letter_digit:
|
|
cmp byte [eax+ecx],'Z'+1
|
|
jb counter_ok
|
|
jne small_letter_digit
|
|
mov byte [eax+ecx],'a'
|
|
jmp counter_ok
|
|
small_letter_digit:
|
|
cmp byte [eax+ecx],'z'+1
|
|
jb counter_ok
|
|
mov byte [eax+ecx],'0'
|
|
loop counter_loop
|
|
inc byte [eax]
|
|
movzx ecx,byte [eax]
|
|
mov byte [eax+ecx],'0'
|
|
counter_ok:
|
|
pop ecx
|
|
lods byte [esi]
|
|
cmp al,'}'
|
|
je macro_block_processed
|
|
or al,al
|
|
jz process_next_line
|
|
cmp al,','
|
|
jne extra_characters_on_line
|
|
dec edi
|
|
lods byte [esi]
|
|
cmp al,1Ah
|
|
je make_local_symbol
|
|
jmp invalid_argument
|
|
common_block:
|
|
call close_macro_block
|
|
jc process_macro_line
|
|
mov [counter],0
|
|
jmp new_macro_block
|
|
forward_block:
|
|
cmp [counter_limit],0
|
|
je common_block
|
|
call close_macro_block
|
|
jc process_macro_line
|
|
mov [counter],1
|
|
jmp new_macro_block
|
|
reverse_block:
|
|
cmp [counter_limit],0
|
|
je common_block
|
|
call close_macro_block
|
|
jc process_macro_line
|
|
mov eax,[counter_limit]
|
|
or eax,80000000h
|
|
mov [counter],eax
|
|
new_macro_block:
|
|
mov [macro_block],esi
|
|
mov eax,[macro_line]
|
|
mov [macro_block_line],eax
|
|
mov [macro_block_line_number],ecx
|
|
jmp process_macro_line
|
|
close_macro_block:
|
|
cmp esi,[macro_block]
|
|
je block_closed
|
|
cmp [counter],0
|
|
je block_closed
|
|
jl reverse_counter
|
|
mov eax,[counter]
|
|
cmp eax,[counter_limit]
|
|
je block_closed
|
|
inc [counter]
|
|
jmp continue_block
|
|
reverse_counter:
|
|
mov eax,[counter]
|
|
dec eax
|
|
cmp eax,80000000h
|
|
je block_closed
|
|
mov [counter],eax
|
|
continue_block:
|
|
mov esi,[macro_block]
|
|
mov eax,[macro_block_line]
|
|
mov [macro_line],eax
|
|
mov ecx,[macro_block_line_number]
|
|
stc
|
|
ret
|
|
block_closed:
|
|
clc
|
|
ret
|
|
get_macro_symbol:
|
|
push ecx
|
|
call find_macro_symbol_leaf
|
|
jc macro_symbol_not_found
|
|
mov edx,[ebx]
|
|
mov ebx,esi
|
|
try_macro_symbol:
|
|
or edx,edx
|
|
jz macro_symbol_not_found
|
|
mov ecx,[esp]
|
|
mov edi,[edx+4]
|
|
repe cmps byte [esi],[edi]
|
|
je macro_symbol_found
|
|
mov esi,ebx
|
|
mov edx,[edx]
|
|
jmp try_macro_symbol
|
|
macro_symbol_found:
|
|
pop ecx
|
|
clc
|
|
ret
|
|
macro_symbol_not_found:
|
|
pop ecx
|
|
stc
|
|
ret
|
|
find_macro_symbol_leaf:
|
|
shl eax,8
|
|
mov al,cl
|
|
mov ebp,eax
|
|
mov ebx,macro_symbols
|
|
follow_macro_symbols_tree:
|
|
mov edx,[ebx]
|
|
or edx,edx
|
|
jz no_such_macro_symbol
|
|
xor eax,eax
|
|
shr ebp,1
|
|
adc eax,0
|
|
lea ebx,[edx+eax*4]
|
|
or ebp,ebp
|
|
jnz follow_macro_symbols_tree
|
|
add ebx,8
|
|
clc
|
|
ret
|
|
no_such_macro_symbol:
|
|
stc
|
|
ret
|
|
add_macro_symbol:
|
|
push ebx ebp
|
|
call find_macro_symbol_leaf
|
|
jc extend_macro_symbol_tree
|
|
mov eax,[ebx]
|
|
make_macro_symbol:
|
|
mov edx,[free_additional_memory]
|
|
add edx,16
|
|
cmp edx,[labels_list]
|
|
ja out_of_memory
|
|
xchg edx,[free_additional_memory]
|
|
mov [ebx],edx
|
|
mov [edx],eax
|
|
mov [edx+4],esi
|
|
pop ebp ebx
|
|
ret
|
|
extend_macro_symbol_tree:
|
|
mov edx,[free_additional_memory]
|
|
add edx,16
|
|
cmp edx,[labels_list]
|
|
ja out_of_memory
|
|
xchg edx,[free_additional_memory]
|
|
xor eax,eax
|
|
mov [edx],eax
|
|
mov [edx+4],eax
|
|
mov [edx+8],eax
|
|
mov [edx+12],eax
|
|
shr ebp,1
|
|
adc eax,0
|
|
mov [ebx],edx
|
|
lea ebx,[edx+eax*4]
|
|
or ebp,ebp
|
|
jnz extend_macro_symbol_tree
|
|
add ebx,8
|
|
xor eax,eax
|
|
jmp make_macro_symbol
|
|
|
|
include_file:
|
|
lods byte [esi]
|
|
cmp al,22h
|
|
jne invalid_argument
|
|
lods dword [esi]
|
|
cmp byte [esi+eax],0
|
|
jne extra_characters_on_line
|
|
push esi
|
|
push edi
|
|
mov ebx,[current_line]
|
|
find_current_file_path:
|
|
mov esi,[ebx]
|
|
test byte [ebx+7],80h
|
|
jz copy_current_file_path
|
|
mov ebx,[ebx+8]
|
|
jmp find_current_file_path
|
|
copy_current_file_path:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
or al,al
|
|
jnz copy_current_file_path
|
|
cut_current_file_name:
|
|
cmp edi,[esp]
|
|
je current_file_path_ok
|
|
cmp byte [edi-1],'\'
|
|
je current_file_path_ok
|
|
cmp byte [edi-1],'/'
|
|
je current_file_path_ok
|
|
dec edi
|
|
jmp cut_current_file_name
|
|
current_file_path_ok:
|
|
mov esi,[esp+4]
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
jnc include_path_ok
|
|
mov ebp,[include_paths]
|
|
try_include_directories:
|
|
mov edi,esi
|
|
mov esi,ebp
|
|
cmp byte [esi],0
|
|
je try_in_current_directory
|
|
push ebp
|
|
push edi
|
|
call get_include_directory
|
|
mov [esp+4],esi
|
|
mov esi,[esp+8]
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
pop ebp
|
|
jnc include_path_ok
|
|
jmp try_include_directories
|
|
mov edi,esi
|
|
try_in_current_directory:
|
|
mov esi,[esp]
|
|
push edi
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
jc file_not_found
|
|
include_path_ok:
|
|
mov edi,[esp]
|
|
copy_preprocessed_path:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
or al,al
|
|
jnz copy_preprocessed_path
|
|
pop esi
|
|
lea ecx,[edi-1]
|
|
sub ecx,esi
|
|
mov [esi-4],ecx
|
|
push dword [macro_status]
|
|
and [macro_status],0Fh
|
|
call preprocess_file
|
|
pop eax
|
|
and al,0F0h
|
|
and [macro_status],0Fh
|
|
or [macro_status],al
|
|
jmp line_preprocessed
|