parser.inc
来自「一个用纯汇编 写的操作系统 源代码 是用 TASM 编译器写的」· INC 代码 · 共 1,373 行 · 第 1/2 页
INC
1,373 行
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
jne forced_expression
jmp argument_parsed
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
mov al,'('
stos byte [edi]
call convert_expression
mov al,')'
stos byte [edi]
pop eax edx ecx ebx
cmp esi,ebx
jne expression_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_parsed
not_string:
cmp byte [esi],'('
jne expression
mov eax,esp
sub eax,100h
jc stack_overflow
cmp eax,[stack_limit]
jb stack_overflow
push esi edi
inc esi
mov al,'{'
stos byte [edi]
inc [parenthesis_stack]
jmp parse_argument
expression:
mov al,'('
stos byte [edi]
call convert_expression
mov al,')'
stos byte [edi]
jmp expression_parsed
forced_expression:
mov al,'('
stos byte [edi]
call convert_expression
mov al,')'
stos byte [edi]
jmp argument_parsed
address_argument:
call parse_address
lods byte [esi]
cmp al,']'
je address_parsed
dec esi
mov al,')'
stos byte [edi]
jmp argument_parsed
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,60h
jne unknown_segment_prefix
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,'{'
jmp separator
unallowed_character:
mov al,0FFh
jmp separator
close_parenthesis:
mov al,'}'
separator:
stos byte [edi]
jmp argument_parsed
instruction_separator:
stos byte [edi]
jmp allow_embedded_instruction
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 separator
argument_parsed:
cmp [parenthesis_stack],0
je parse_argument
dec [parenthesis_stack]
add esp,8
jmp argument_parsed
expression_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
jne invalid_expression
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
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,2
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
pop esi
add esi,ebp
mov ax,[edi]
clc
ret
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,11
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:
add esi,2
mov eax,[anonymous_reverse]
or eax,eax
jz invalid_value
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],'$'
jne find_label
cmp ecx,2
ja find_label
inc esi
jb get_current_offset_id
inc esi
cmp byte [esi-1],'$'
je get_org_origin_id
sub esi,ecx
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_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 invalid_name
name_first_char_ok:
cmp ecx,1
jne check_for_reserved_word
cmp al,'$'
je reserved_word
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
reserved_word:
mov eax,0Fh
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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?