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 + -
显示快捷键?