asm_dip/toolchain/fasmw17332/SOURCE/PARSER.INC

1471 lines
27 KiB
Plaintext
Raw Normal View History

2024-11-24 20:13:28 -08:00
; flat assembler core
; Copyright (c) 1999-2022, Tomasz Grysztar.
; All rights reserved.
parser:
mov eax,[memory_end]
mov [labels_list],eax
mov eax,[additional_memory]
mov [free_additional_memory],eax
xor eax,eax
mov [current_locals_prefix],eax
mov [anonymous_reverse],eax
mov [anonymous_forward],eax
mov [hash_tree],eax
mov [blocks_stack],eax
mov [parsed_lines],eax
mov esi,[memory_start]
mov edi,[source_start]
parser_loop:
mov [current_line],esi
lea eax,[edi+100h]
cmp eax,[labels_list]
jae out_of_memory
cmp byte [esi+16],0
je empty_line
cmp byte [esi+16],3Bh
je empty_line
mov al,0Fh
stos byte [edi]
mov eax,esi
stos dword [edi]
inc [parsed_lines]
add esi,16
parse_line:
mov [formatter_symbols_allowed],0
mov [decorator_symbols_allowed],0
cmp byte [esi],1Ah
jne empty_instruction
push edi
add esi,2
movzx ecx,byte [esi-1]
cmp byte [esi+ecx],':'
je simple_label
cmp byte [esi+ecx],'='
je constant_label
call get_instruction
jnc main_instruction_identified
cmp byte [esi+ecx],1Ah
jne no_data_label
push esi ecx
lea esi,[esi+ecx+2]
movzx ecx,byte [esi-1]
call get_data_directive
jnc data_label
pop ecx esi
no_data_label:
call get_data_directive
jnc main_instruction_identified
pop edi
sub esi,2
xor bx,bx
call parse_line_contents
jmp parse_next_line
simple_label:
pop edi
call identify_label
cmp byte [esi+1],':'
je block_label
mov byte [edi],2
inc edi
stos dword [edi]
inc esi
xor al,al
stos byte [edi]
jmp parse_line
block_label:
mov byte [edi],4
inc edi
stos dword [edi]
add esi,2
jmp parse_line
constant_label:
pop edi
call get_label_id
mov byte [edi],3
inc edi
stos dword [edi]
xor al,al
stos byte [edi]
inc esi
xor bx,bx
call parse_line_contents
jmp parse_next_line
data_label:
pop ecx edx
pop edi
push eax ebx esi
mov esi,edx
movzx ecx,byte [esi-1]
call identify_label
mov byte [edi],2
inc edi
stos dword [edi]
pop esi ebx eax
stos byte [edi]
push edi
main_instruction_identified:
pop edi
mov dl,al
mov al,1
stos byte [edi]
mov ax,bx
stos word [edi]
mov al,dl
stos byte [edi]
cmp bx,if_directive-instruction_handler
je parse_block
cmp bx,repeat_directive-instruction_handler
je parse_block
cmp bx,while_directive-instruction_handler
je parse_block
cmp bx,end_directive-instruction_handler
je parse_end_directive
cmp bx,else_directive-instruction_handler
je parse_else
cmp bx,assert_directive-instruction_handler
je parse_assert
common_parse:
call parse_line_contents
jmp parse_next_line
empty_instruction:
lods byte [esi]
or al,al
jz parse_next_line
cmp al,':'
je invalid_name
dec esi
mov [parenthesis_stack],0
call parse_argument
jmp parse_next_line
empty_line:
add esi,16
skip_rest_of_line:
call skip_foreign_line
parse_next_line:
cmp esi,[source_start]
jb parser_loop
source_parsed:
cmp [blocks_stack],0
je blocks_stack_ok
pop eax
pop [current_line]
jmp missing_end_directive
blocks_stack_ok:
xor al,al
stos byte [edi]
add edi,0Fh
and edi,not 0Fh
mov [code_start],edi
ret
parse_block:
mov eax,esp
sub eax,[stack_limit]
cmp eax,100h
jb stack_overflow
push [current_line]
mov ax,bx
shl eax,16
push eax
inc [blocks_stack]
cmp bx,if_directive-instruction_handler
je parse_if
cmp bx,while_directive-instruction_handler
je parse_while
call parse_line_contents
jmp parse_next_line
parse_end_directive:
cmp byte [esi],1Ah
jne common_parse
push edi
inc esi
movzx ecx,byte [esi]
inc esi
call get_instruction
pop edi
jnc parse_end_block
sub esi,2
jmp common_parse
parse_end_block:
mov dl,al
mov al,1
stos byte [edi]
mov ax,bx
stos word [edi]
mov al,dl
stos byte [edi]
lods byte [esi]
or al,al
jnz extra_characters_on_line
cmp bx,if_directive-instruction_handler
je close_parsing_block
cmp bx,repeat_directive-instruction_handler
je close_parsing_block
cmp bx,while_directive-instruction_handler
je close_parsing_block
jmp parse_next_line
close_parsing_block:
cmp [blocks_stack],0
je unexpected_instruction
cmp bx,[esp+2]
jne unexpected_instruction
dec [blocks_stack]
pop eax edx
cmp bx,if_directive-instruction_handler
jne parse_next_line
test al,1100b
jz parse_next_line
test al,10000b
jnz parse_next_line
sub edi,8
jmp parse_next_line
parse_if:
push edi
call parse_line_contents
xor al,al
stos byte [edi]
xchg esi,[esp]
mov edi,esi
call preevaluate_logical_expression
pop esi
cmp al,'0'
je parse_false_condition_block
cmp al,'1'
je parse_true_condition_block
or byte [esp],10000b
jmp parse_next_line
parse_while:
push edi
call parse_line_contents
xor al,al
stos byte [edi]
xchg esi,[esp]
mov edi,esi
call preevaluate_logical_expression
pop esi
cmp al,'0'
je parse_false_condition_block
cmp al,'1'
jne parse_next_line
stos byte [edi]
jmp parse_next_line
parse_false_condition_block:
or byte [esp],1
sub edi,4
jmp skip_parsing
parse_true_condition_block:
or byte [esp],100b
sub edi,4
jmp parse_next_line
parse_else:
cmp [blocks_stack],0
je unexpected_instruction
cmp word [esp+2],if_directive-instruction_handler
jne unexpected_instruction
lods byte [esi]
or al,al
jz parse_pure_else
cmp al,1Ah
jne extra_characters_on_line
push edi
movzx ecx,byte [esi]
inc esi
call get_instruction
jc extra_characters_on_line
pop edi
cmp bx,if_directive-instruction_handler
jne extra_characters_on_line
test byte [esp],100b
jnz skip_true_condition_else
mov dl,al
mov al,1
stos byte [edi]
mov ax,bx
stos word [edi]
mov al,dl
stos byte [edi]
jmp parse_if
parse_assert:
push edi
call parse_line_contents
xor al,al
stos byte [edi]
xchg esi,[esp]
mov edi,esi
call preevaluate_logical_expression
pop esi
or al,al
jz parse_next_line
stos byte [edi]
jmp parse_next_line
skip_true_condition_else:
sub edi,4
or byte [esp],1
jmp skip_parsing_contents
parse_pure_else:
bts dword [esp],1
jc unexpected_instruction
test byte [esp],100b
jz parse_next_line
sub edi,4
or byte [esp],1
jmp skip_parsing
skip_parsing:
cmp esi,[source_start]
jae source_parsed
mov [current_line],esi
add esi,16
skip_parsing_line:
cmp byte [esi],1Ah
jne skip_parsing_contents
inc esi
movzx ecx,byte [esi]
inc esi
cmp byte [esi+ecx],':'
je skip_parsing_label
push edi
call get_instruction
pop edi
jnc skip_parsing_instruction
add esi,ecx
jmp skip_parsing_contents
skip_parsing_label:
lea esi,[esi+ecx+1]
jmp skip_parsing_line
skip_parsing_instruction:
cmp bx,if_directive-instruction_handler
je skip_parsing_block
cmp bx,repeat_directive-instruction_handler
je skip_parsing_block
cmp bx,while_directive-instruction_handler
je skip_parsing_block
cmp bx,end_directive-instruction_handler
je skip_parsing_end_directive
cmp bx,else_directive-instruction_handler
je skip_parsing_else
skip_parsing_contents:
lods byte [esi]
or al,al
jz skip_parsing
cmp al,1Ah
je skip_parsing_symbol
cmp al,3Bh
je skip_parsing_symbol
cmp al,22h
je skip_parsing_string
jmp skip_parsing_contents
skip_parsing_symbol:
lods byte [esi]
movzx eax,al
add esi,eax
jmp skip_parsing_contents
skip_parsing_string:
lods dword [esi]
add esi,eax
jmp skip_parsing_contents
skip_parsing_block:
mov eax,esp
sub eax,[stack_limit]
cmp eax,100h
jb stack_overflow
push [current_line]
mov ax,bx
shl eax,16
push eax
inc [blocks_stack]
jmp skip_parsing_contents
skip_parsing_end_directive:
cmp byte [esi],1Ah
jne skip_parsing_contents
push edi
inc esi
movzx ecx,byte [esi]
inc esi
call get_instruction
pop edi
jnc skip_parsing_end_block
add esi,ecx
jmp skip_parsing_contents
skip_parsing_end_block:
lods byte [esi]
or al,al
jnz extra_characters_on_line
cmp bx,if_directive-instruction_handler
je close_skip_parsing_block
cmp bx,repeat_directive-instruction_handler
je close_skip_parsing_block
cmp bx,while_directive-instruction_handler
je close_skip_parsing_block
jmp skip_parsing
close_skip_parsing_block:
cmp [blocks_stack],0
je unexpected_instruction
cmp bx,[esp+2]
jne unexpected_instruction
dec [blocks_stack]
pop eax edx
test al,1
jz skip_parsing
cmp bx,if_directive-instruction_handler
jne parse_next_line
test al,10000b
jz parse_next_line
mov al,0Fh
stos byte [edi]
mov eax,[current_line]
stos dword [edi]
inc [parsed_lines]
mov eax,1 + (end_directive-instruction_handler) shl 8
stos dword [edi]
mov eax,1 + (if_directive-instruction_handler) shl 8
stos dword [edi]
jmp parse_next_line
skip_parsing_else:
cmp [blocks_stack],0
je unexpected_instruction
cmp word [esp+2],if_directive-instruction_handler
jne unexpected_instruction
lods byte [esi]
or al,al
jz skip_parsing_pure_else
cmp al,1Ah
jne extra_characters_on_line
push edi
movzx ecx,byte [esi]
inc esi
call get_instruction
jc extra_characters_on_line
pop edi
cmp bx,if_directive-instruction_handler
jne extra_characters_on_line
mov al,[esp]
test al,1
jz skip_parsing_contents
test al,100b
jnz skip_parsing_contents
test al,10000b
jnz parse_else_if
xor al,al
mov [esp],al
mov al,0Fh
stos byte [edi]
mov eax,[current_line]
stos dword [edi]
inc [parsed_lines]
parse_else_if:
mov eax,1 + (if_directive-instruction_handler) shl 8
stos dword [edi]
jmp parse_if
skip_parsing_pure_else:
bts dword [esp],1
jc unexpected_instruction
mov al,[esp]
test al,1
jz skip_parsing
test al,100b
jnz skip_parsing
and al,not 1
or al,1000b
mov [esp],al
jmp parse_next_line
parse_line_contents:
mov [parenthesis_stack],0
parse_instruction_arguments:
cmp bx,prefix_instruction-instruction_handler
je allow_embedded_instruction
cmp bx,times_directive-instruction_handler
je parse_times_directive
cmp bx,end_directive-instruction_handler
je allow_embedded_instruction
cmp bx,label_directive-instruction_handler
je parse_label_directive
cmp bx,segment_directive-instruction_handler
je parse_segment_directive
cmp bx,load_directive-instruction_handler
je parse_load_directive
cmp bx,extrn_directive-instruction_handler
je parse_extrn_directive
cmp bx,public_directive-instruction_handler
je parse_public_directive
cmp bx,section_directive-instruction_handler
je parse_formatter_argument
cmp bx,format_directive-instruction_handler
je parse_formatter_argument
cmp bx,data_directive-instruction_handler
je parse_formatter_argument
jmp parse_argument
parse_formatter_argument:
or [formatter_symbols_allowed],-1
parse_argument:
lea eax,[edi+100h]
cmp eax,[labels_list]
jae out_of_memory
lods byte [esi]
cmp al,':'
je instruction_separator
cmp al,','
je separator
cmp al,'='
je expression_comparator
cmp al,'|'
je separator
cmp al,'&'
je separator
cmp al,'~'
je separator
cmp al,'>'
je greater
cmp al,'<'
je less
cmp al,')'
je close_parenthesis
or al,al
jz contents_parsed
cmp al,'['
je address_argument
cmp al,']'
je separator
cmp al,'{'
je open_decorator
cmp al,'}'
je close_decorator
cmp al,'#'
je unallowed_character
cmp al,'`'
je unallowed_character
cmp al,3Bh
je foreign_argument
cmp [decorator_symbols_allowed],0
je not_a_separator
cmp al,'-'
je separator
not_a_separator:
dec esi
cmp al,1Ah
jne expression_argument
push edi
mov edi,directive_operators
call get_operator
or al,al
jnz operator_argument
inc esi
movzx ecx,byte [esi]
inc esi
call get_symbol
jnc symbol_argument
cmp ecx,1
jne check_argument
cmp byte [esi],'?'
jne check_argument
pop edi
movs byte [edi],[esi]
jmp argument_parsed
foreign_argument:
dec esi
call skip_foreign_line
jmp contents_parsed
symbol_argument:
pop edi
stos word [edi]
cmp byte [esi],'+'
jne argument_parsed
and ax,0F0FFh
cmp ax,6010h
jne argument_parsed
movs byte [edi],[esi]
jmp argument_parsed
operator_argument:
pop edi
cmp al,85h
je ptr_argument
stos byte [edi]
cmp al,8Ch
je forced_expression
cmp al,81h
je forced_parenthesis
cmp al,80h
je parse_at_operator
cmp al,82h
je parse_from_operator
cmp al,89h
je parse_label_operator
cmp al,0F8h
je forced_expression
jmp argument_parsed
instruction_separator:
stos byte [edi]
allow_embedded_instruction:
cmp byte [esi],1Ah
jne parse_argument
push edi
inc esi
movzx ecx,byte [esi]
inc esi
call get_instruction
jnc embedded_instruction
call get_data_directive
jnc embedded_instruction
pop edi
sub esi,2
jmp parse_argument
embedded_instruction:
pop edi
mov dl,al
mov al,1
stos byte [edi]
mov ax,bx
stos word [edi]
mov al,dl
stos byte [edi]
jmp parse_instruction_arguments
parse_times_directive:
mov al,'('
stos byte [edi]
call convert_expression
mov al,')'
stos byte [edi]
cmp byte [esi],':'
jne allow_embedded_instruction
movs byte [edi],[esi]
jmp allow_embedded_instruction
parse_segment_directive:
or [formatter_symbols_allowed],-1
parse_label_directive:
cmp byte [esi],1Ah
jne argument_parsed
push esi
inc esi
movzx ecx,byte [esi]
inc esi
call identify_label
pop ebx
cmp eax,0Fh
je non_label_identified
mov byte [edi],2
inc edi
stos dword [edi]
xor al,al
stos byte [edi]
jmp argument_parsed
non_label_identified:
mov esi,ebx
jmp argument_parsed
parse_load_directive:
cmp byte [esi],1Ah
jne argument_parsed
push esi
inc esi
movzx ecx,byte [esi]
inc esi
call get_label_id
pop ebx
cmp eax,0Fh
je non_label_identified
mov byte [edi],2
inc edi
stos dword [edi]
xor al,al
stos byte [edi]
jmp argument_parsed
parse_public_directive:
cmp byte [esi],1Ah
jne parse_argument
inc esi
push esi
movzx ecx,byte [esi]
inc esi
push esi ecx
push edi
or [formatter_symbols_allowed],-1
call get_symbol
mov [formatter_symbols_allowed],0
pop edi
jc parse_public_label
cmp al,1Dh
jne parse_public_label
add esp,12
stos word [edi]
jmp parse_public_directive
parse_public_label:
pop ecx esi
mov al,2
stos byte [edi]
call get_label_id
stos dword [edi]
mov ax,8600h
stos word [edi]
pop ebx
push ebx esi edi
mov edi,directive_operators
call get_operator
pop edi edx ebx
cmp al,86h
je argument_parsed
mov esi,edx
xchg esi,ebx
movzx ecx,byte [esi]
inc esi
mov ax,'('
stos word [edi]
mov eax,ecx
stos dword [edi]
rep movs byte [edi],[esi]
xor al,al
stos byte [edi]
xchg esi,ebx
jmp argument_parsed
parse_extrn_directive:
cmp byte [esi],22h
je parse_quoted_extrn
cmp byte [esi],1Ah
jne parse_argument
push esi
movzx ecx,byte [esi+1]
add esi,2
mov ax,'('
stos word [edi]
mov eax,ecx
stos dword [edi]
rep movs byte [edi],[esi]
mov ax,8600h
stos word [edi]
pop esi
parse_label_operator:
cmp byte [esi],1Ah
jne argument_parsed
inc esi
movzx ecx,byte [esi]
inc esi
mov al,2
stos byte [edi]
call get_label_id
stos dword [edi]
xor al,al
stos byte [edi]
jmp argument_parsed
parse_from_operator:
cmp byte [esi],22h
je argument_parsed
parse_at_operator:
cmp byte [esi],':'
je argument_parsed
jmp forced_multipart_expression
parse_quoted_extrn:
inc esi
mov ax,'('
stos word [edi]
lods dword [esi]
mov ecx,eax
stos dword [edi]
rep movs byte [edi],[esi]
xor al,al
stos byte [edi]
push esi edi
mov edi,directive_operators
call get_operator
mov edx,esi
pop edi esi
cmp al,86h
jne argument_parsed
stos byte [edi]
mov esi,edx
jmp parse_label_operator
ptr_argument:
call parse_address
jmp address_parsed
check_argument:
push esi ecx
sub esi,2
mov edi,single_operand_operators
call get_operator
pop ecx esi
or al,al
jnz not_instruction
call get_instruction
jnc embedded_instruction
call get_data_directive
jnc embedded_instruction
not_instruction:
pop edi
sub esi,2
expression_argument:
cmp byte [esi],22h
jne not_string
mov eax,[esi+1]
lea ebx,[esi+5+eax]
push ebx ecx esi edi
call parse_expression
pop eax edx ecx ebx
cmp esi,ebx
jne expression_argument_parsed
mov edi,eax
mov esi,edx
string_argument:
inc esi
mov ax,'('
stos word [edi]
lods dword [esi]
mov ecx,eax
stos dword [edi]
shr ecx,1
jnc string_movsb_ok
movs byte [edi],[esi]
string_movsb_ok:
shr ecx,1
jnc string_movsw_ok
movs word [edi],[esi]
string_movsw_ok:
rep movs dword [edi],[esi]
xor al,al
stos byte [edi]
jmp expression_argument_parsed
parse_expression:
mov al,'('
stos byte [edi]
call convert_expression
mov al,')'
stos byte [edi]
ret
not_string:
cmp byte [esi],'('
jne expression
mov eax,esp
sub eax,[stack_limit]
cmp eax,100h
jb stack_overflow
push esi edi
inc esi
mov al,91h
stos byte [edi]
inc [parenthesis_stack]
jmp parse_argument
expression_comparator:
stos byte [edi]
jmp forced_expression
greater:
cmp byte [esi],'='
jne separator
inc esi
mov al,0F2h
jmp separator
less:
cmp byte [edi-1],0F6h
je separator
cmp byte [esi],'>'
je not_equal
cmp byte [esi],'='
jne separator
inc esi
mov al,0F3h
jmp separator
not_equal:
inc esi
mov al,0F1h
jmp expression_comparator
expression:
call parse_expression
jmp expression_argument_parsed
forced_expression:
xor al,al
xchg al,[formatter_symbols_allowed]
push eax
call parse_expression
forced_expression_parsed:
pop eax
mov [formatter_symbols_allowed],al
jmp argument_parsed
forced_multipart_expression:
xor al,al
xchg al,[formatter_symbols_allowed]
push eax
call parse_expression
cmp byte [esi],':'
jne forced_expression_parsed
movs byte [edi],[esi]
call parse_expression
jmp forced_expression_parsed
address_argument:
call parse_address
lods byte [esi]
cmp al,']'
je address_parsed
cmp al,','
je divided_address
dec esi
mov al,')'
stos byte [edi]
jmp argument_parsed
divided_address:
mov ax,'),'
stos word [edi]
jmp expression
address_parsed:
mov al,']'
stos byte [edi]
jmp argument_parsed
parse_address:
mov al,'['
stos byte [edi]
cmp word [esi],021Ah
jne convert_address
push esi
add esi,4
lea ebx,[esi+1]
cmp byte [esi],':'
pop esi
jne convert_address
add esi,2
mov ecx,2
push ebx edi
call get_symbol
pop edi esi
jc unknown_segment_prefix
cmp al,10h
jne unknown_segment_prefix
mov al,ah
and ah,11110000b
cmp ah,30h
jne unknown_segment_prefix
add al,30h
stos byte [edi]
jmp convert_address
unknown_segment_prefix:
sub esi,5
convert_address:
push edi
mov edi,address_sizes
call get_operator
pop edi
or al,al
jz convert_expression
add al,70h
stos byte [edi]
jmp convert_expression
forced_parenthesis:
cmp byte [esi],'('
jne argument_parsed
inc esi
mov al,91h
jmp separator
unallowed_character:
mov al,0FFh
jmp separator
open_decorator:
inc [decorator_symbols_allowed]
jmp separator
close_decorator:
dec [decorator_symbols_allowed]
jmp separator
close_parenthesis:
mov al,92h
separator:
stos byte [edi]
argument_parsed:
cmp [parenthesis_stack],0
je parse_argument
dec [parenthesis_stack]
add esp,8
jmp argument_parsed
expression_argument_parsed:
cmp [parenthesis_stack],0
je parse_argument
cmp byte [esi],')'
jne argument_parsed
dec [parenthesis_stack]
pop edi esi
jmp expression
contents_parsed:
cmp [parenthesis_stack],0
je contents_ok
dec [parenthesis_stack]
add esp,8
jmp contents_parsed
contents_ok:
ret
identify_label:
cmp byte [esi],'.'
je local_label_name
call get_label_id
cmp eax,10h
jb label_identified
or ebx,ebx
jz anonymous_label_name
dec ebx
mov [current_locals_prefix],ebx
label_identified:
ret
anonymous_label_name:
cmp byte [esi-1],'@'
je anonymous_label_name_ok
mov eax,0Fh
anonymous_label_name_ok:
ret
local_label_name:
call get_label_id
ret
get_operator:
cmp byte [esi],1Ah
jne get_simple_operator
mov edx,esi
push ebp
inc esi
lods byte [esi]
movzx ebp,al
push edi
mov ecx,ebp
call lower_case
pop edi
check_operator:
mov esi,converted
movzx ecx,byte [edi]
jecxz no_operator
inc edi
mov ebx,edi
add ebx,ecx
cmp ecx,ebp
jne next_operator
repe cmps byte [esi],[edi]
je operator_found
jb no_operator
next_operator:
mov edi,ebx
inc edi
jmp check_operator
no_operator:
mov esi,edx
mov ecx,ebp
pop ebp
no_simple_operator:
xor al,al
ret
operator_found:
lea esi,[edx+2+ebp]
mov ecx,ebp
pop ebp
mov al,[edi]
ret
get_simple_operator:
mov al,[esi]
cmp al,22h
je no_simple_operator
simple_operator:
cmp byte [edi],1
jb no_simple_operator
ja simple_next_operator
cmp al,[edi+1]
je simple_operator_found
simple_next_operator:
movzx ecx,byte [edi]
lea edi,[edi+1+ecx+1]
jmp simple_operator
simple_operator_found:
inc esi
mov al,[edi+2]
ret
get_symbol:
push esi
mov ebp,ecx
call lower_case
mov ecx,ebp
cmp cl,11
ja no_symbol
sub cl,1
jc no_symbol
movzx ebx,word [symbols+ecx*4]
add ebx,symbols
movzx edx,word [symbols+ecx*4+2]
scan_symbols:
or edx,edx
jz no_symbol
mov eax,edx
shr eax,1
lea edi,[ebp+2]
imul eax,edi
lea edi,[ebx+eax]
mov esi,converted
mov ecx,ebp
repe cmps byte [esi],[edi]
ja symbols_up
jb symbols_down
mov ax,[edi]
cmp al,18h
jb symbol_ok
cmp al,1Fh
je decorator_symbol
cmp [formatter_symbols_allowed],0
je no_symbol
symbol_ok:
pop esi
add esi,ebp
clc
ret
decorator_symbol:
cmp [decorator_symbols_allowed],0
jne symbol_ok
no_symbol:
pop esi
mov ecx,ebp
stc
ret
symbols_down:
shr edx,1
jmp scan_symbols
symbols_up:
lea ebx,[edi+ecx+2]
shr edx,1
adc edx,-1
jmp scan_symbols
get_data_directive:
push esi
mov ebp,ecx
call lower_case
mov ecx,ebp
cmp cl,4
ja no_instruction
sub cl,2
jc no_instruction
movzx ebx,word [data_directives+ecx*4]
add ebx,data_directives
movzx edx,word [data_directives+ecx*4+2]
jmp scan_instructions
get_instruction:
push esi
mov ebp,ecx
call lower_case
mov ecx,ebp
cmp cl,17
ja no_instruction
sub cl,2
jc no_instruction
movzx ebx,word [instructions+ecx*4]
add ebx,instructions
movzx edx,word [instructions+ecx*4+2]
scan_instructions:
or edx,edx
jz no_instruction
mov eax,edx
shr eax,1
lea edi,[ebp+3]
imul eax,edi
lea edi,[ebx+eax]
mov esi,converted
mov ecx,ebp
repe cmps byte [esi],[edi]
ja instructions_up
jb instructions_down
pop esi
add esi,ebp
mov al,[edi]
mov bx,[edi+1]
clc
ret
no_instruction:
pop esi
mov ecx,ebp
stc
ret
instructions_down:
shr edx,1
jmp scan_instructions
instructions_up:
lea ebx,[edi+ecx+3]
shr edx,1
adc edx,-1
jmp scan_instructions
get_label_id:
cmp ecx,100h
jae name_too_long
cmp byte [esi],'@'
je anonymous_label
cmp byte [esi],'.'
jne standard_label
cmp byte [esi+1],'.'
je standard_label
cmp [current_locals_prefix],0
je standard_label
push edi
mov edi,[additional_memory_end]
sub edi,2
sub edi,ecx
push ecx esi
mov esi,[current_locals_prefix]
lods byte [esi]
movzx ecx,al
sub edi,ecx
cmp edi,[free_additional_memory]
jb out_of_memory
mov word [edi],0
add edi,2
mov ebx,edi
rep movs byte [edi],[esi]
pop esi ecx
add al,cl
jc name_too_long
rep movs byte [edi],[esi]
pop edi
push ebx esi
movzx ecx,al
mov byte [ebx-1],al
mov esi,ebx
call get_label_id
pop esi ebx
cmp ebx,[eax+24]
jne composed_label_id_ok
lea edx,[ebx-2]
mov [additional_memory_end],edx
composed_label_id_ok:
ret
anonymous_label:
cmp ecx,2
jne standard_label
mov al,[esi+1]
mov ebx,characters
xlat byte [ebx]
cmp al,'@'
je new_anonymous
cmp al,'b'
je anonymous_back
cmp al,'r'
je anonymous_back
cmp al,'f'
jne standard_label
add esi,2
mov eax,[anonymous_forward]
or eax,eax
jnz anonymous_ok
mov eax,[current_line]
mov [error_line],eax
call allocate_label
mov [anonymous_forward],eax
anonymous_ok:
xor ebx,ebx
ret
anonymous_back:
mov eax,[anonymous_reverse]
add esi,2
or eax,eax
jz bogus_anonymous
jmp anonymous_ok
bogus_anonymous:
call allocate_label
mov [anonymous_reverse],eax
jmp anonymous_ok
new_anonymous:
add esi,2
mov eax,[anonymous_forward]
or eax,eax
jnz new_anonymous_ok
call allocate_label
new_anonymous_ok:
mov [anonymous_reverse],eax
mov [anonymous_forward],0
jmp anonymous_ok
standard_label:
cmp byte [esi],'%'
je get_predefined_id
cmp byte [esi],'$'
je current_address_label
cmp byte [esi],'?'
jne find_label
cmp ecx,1
jne find_label
inc esi
mov eax,0Fh
ret
current_address_label:
cmp ecx,3
je current_address_label_3_characters
ja find_label
inc esi
cmp ecx,1
jbe get_current_offset_id
inc esi
cmp byte [esi-1],'$'
je get_org_origin_id
cmp byte [esi-1],'%'
je get_file_offset_id
sub esi,2
jmp find_label
get_current_offset_id:
xor eax,eax
ret
get_counter_id:
mov eax,1
ret
get_timestamp_id:
mov eax,2
ret
get_org_origin_id:
mov eax,3
ret
get_file_offset_id:
mov eax,4
ret
current_address_label_3_characters:
cmp word [esi+1],'%%'
jne find_label
add esi,3
get_actual_file_offset_id:
mov eax,5
ret
get_predefined_id:
cmp ecx,2
ja find_label
inc esi
cmp cl,1
je get_counter_id
lods byte [esi]
mov ebx,characters
xlat [ebx]
cmp al,'t'
je get_timestamp_id
sub esi,2
find_label:
xor ebx,ebx
mov eax,2166136261
mov ebp,16777619
hash_label:
xor al,[esi+ebx]
mul ebp
inc bl
cmp bl,cl
jb hash_label
mov ebp,eax
shl eax,8
and ebp,0FFh shl 24
xor ebp,eax
or ebp,ebx
mov [label_hash],ebp
push edi esi
push ecx
mov ecx,32
mov ebx,hash_tree
follow_tree:
mov edx,[ebx]
or edx,edx
jz extend_tree
xor eax,eax
shl ebp,1
adc eax,0
lea ebx,[edx+eax*4]
dec ecx
jnz follow_tree
mov [label_leaf],ebx
pop edx
mov eax,[ebx]
or eax,eax
jz add_label
mov ebx,esi
mov ebp,[label_hash]
compare_labels:
mov esi,ebx
mov ecx,edx
mov edi,[eax+4]
mov edi,[edi+24]
repe cmps byte [esi],[edi]
je label_found
mov eax,[eax]
or eax,eax
jnz compare_labels
jmp add_label
label_found:
add esp,4
pop edi
mov eax,[eax+4]
ret
extend_tree:
mov edx,[free_additional_memory]
lea eax,[edx+8]
cmp eax,[additional_memory_end]
ja out_of_memory
mov [free_additional_memory],eax
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_tree
mov [label_leaf],ebx
pop edx
add_label:
mov ecx,edx
pop esi
cmp byte [esi-2],0
je label_name_ok
mov al,[esi]
cmp al,30h
jb name_first_char_ok
cmp al,39h
jbe numeric_name
name_first_char_ok:
cmp al,'$'
jne check_for_reserved_word
numeric_name:
add esi,ecx
reserved_word:
mov eax,0Fh
pop edi
ret
check_for_reserved_word:
call get_instruction
jnc reserved_word
call get_data_directive
jnc reserved_word
call get_symbol
jnc reserved_word
sub esi,2
mov edi,operators
call get_operator
or al,al
jnz reserved_word
mov edi,single_operand_operators
call get_operator
or al,al
jnz reserved_word
mov edi,directive_operators
call get_operator
or al,al
jnz reserved_word
inc esi
movzx ecx,byte [esi]
inc esi
label_name_ok:
mov edx,[free_additional_memory]
lea eax,[edx+8]
cmp eax,[additional_memory_end]
ja out_of_memory
mov [free_additional_memory],eax
mov ebx,esi
add esi,ecx
mov eax,[label_leaf]
mov edi,[eax]
mov [edx],edi
mov [eax],edx
call allocate_label
mov [edx+4],eax
mov [eax+24],ebx
pop edi
ret
allocate_label:
mov eax,[labels_list]
mov ecx,LABEL_STRUCTURE_SIZE shr 2
initialize_label:
sub eax,4
mov dword [eax],0
loop initialize_label
mov [labels_list],eax
ret
LABEL_STRUCTURE_SIZE = 32