
; flat assembler core
; Copyright (c) 1999-2016, Tomasz Grysztar.
; All rights reserved.

formatter:
	mov	[current_offset],edi
	cmp	[output_file],0
	jne	output_path_ok
	mov	esi,[input_file]
	mov	edi,[free_additional_memory]
      copy_output_path:
	lods	byte [esi]
	cmp	edi,[structures_buffer]
	jae	out_of_memory
	stos	byte [edi]
	or	al,al
	jnz	copy_output_path
	dec	edi
	mov	eax,edi
      find_extension:
	dec	eax
	cmp	eax,[free_additional_memory]
	jb	extension_found
	cmp	byte [eax],'\'
	je	extension_found
	cmp	byte [eax],'/'
	je	extension_found
	cmp	byte [eax],'.'
	jne	find_extension
	mov	edi,eax
      extension_found:
	lea	eax,[edi+9]
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	cmp	[file_extension],0
	jne	extension_specified
	mov	al,[output_format]
	cmp	al,2
	je	exe_extension
	jb	bin_extension
	cmp	al,4
	je	obj_extension
	cmp	al,5
	je	o_extension
	cmp	al,3
	jne	no_extension
	cmp	[subsystem],1
	je	sys_extension
	cmp	[subsystem],10
	jae	efi_extension
	bt	[format_flags],8
	jnc	exe_extension
	mov	eax,'.dll'
	jmp	make_extension
      sys_extension:
	mov	eax,'.sys'
	jmp	make_extension
      efi_extension:
	mov	eax,'.efi'
	jmp	make_extension
      bin_extension:
	mov	eax,'.bin'
	bt	[format_flags],0
	jnc	make_extension
	mov	eax,'.com'
	jmp	make_extension
      obj_extension:
	mov	eax,'.obj'
	jmp	make_extension
      o_extension:
	mov	eax,'.o'
	bt	[format_flags],0
	jnc	make_extension
      no_extension:
	xor	eax,eax
	jmp	make_extension
      exe_extension:
	mov	eax,'.exe'
      make_extension:
	xchg	eax,[edi]
	scas	dword [edi]
	mov	byte [edi],0
	scas	byte [edi]
	mov	esi,edi
	stos	dword [edi]
	sub	edi,9
	xor	eax,eax
	mov	ebx,characters
      adapt_case:
	mov	al,[esi]
	or	al,al
	jz	adapt_next
	xlat	byte [ebx]
	cmp	al,[esi]
	je	adapt_ok
	sub	byte [edi],20h
      adapt_ok:
	inc	esi
      adapt_next:
	inc	edi
	cmp	byte [edi],0
	jne	adapt_case
	jmp	extension_ok
      extension_specified:
	mov	al,'.'
	stos	byte [edi]
	mov	esi,[file_extension]
      copy_extension:
	lods	byte [esi]
	stos	byte [edi]
	test	al,al
	jnz	copy_extension
	dec	edi
      extension_ok:
	mov	esi,edi
	lea	ecx,[esi+1]
	sub	ecx,[free_additional_memory]
	mov	edi,[structures_buffer]
	dec	edi
	std
	rep	movs byte [edi],[esi]
	cld
	inc	edi
	mov	[structures_buffer],edi
	mov	[output_file],edi
      output_path_ok:
	cmp	[symbols_file],0
	je	labels_table_ok
	mov	ecx,[memory_end]
	sub	ecx,[labels_list]
	mov	edi,[tagged_blocks]
	sub	edi,8
	mov	[edi],ecx
	or	dword [edi+4],-1
	sub	edi,ecx
	cmp	edi,[current_offset]
	jbe	out_of_memory
	mov	[tagged_blocks],edi
	mov	esi,[memory_end]
      copy_labels:
	sub	esi,32
	cmp	esi,[labels_list]
	jb	labels_table_ok
	mov	ecx,32 shr 2
	rep	movs dword [edi],[esi]
	sub	esi,32
	jmp	copy_labels
      labels_table_ok:
	mov	edi,[current_offset]
	cmp	[output_format],4
	je	coff_formatter
	cmp	[output_format],5
	jne	common_formatter
	bt	[format_flags],0
	jnc	elf_formatter
      common_formatter:
	mov	eax,edi
	sub	eax,[code_start]
	mov	[real_code_size],eax
	cmp	edi,[undefined_data_end]
	jne	calculate_code_size
	mov	edi,[undefined_data_start]
      calculate_code_size:
	mov	[current_offset],edi
	sub	edi,[code_start]
	mov	[code_size],edi
	and	[written_size],0
	mov	edx,[output_file]
	call	create
	jc	write_failed
	cmp	[output_format],3
	jne	stub_written
	mov	edx,[code_start]
	mov	ecx,[stub_size]
	sub	edx,ecx
	add	[written_size],ecx
	call	write
      stub_written:
	cmp	[output_format],2
	jne	write_output
	call	write_mz_header
      write_output:
	call	write_code
      output_written:
	call	close
	cmp	[symbols_file],0
	jne	dump_symbols
	ret
      write_code:
	mov	eax,[written_size]
	mov	[headers_size],eax
	mov	edx,[code_start]
	mov	ecx,[code_size]
	add	[written_size],ecx
	lea	eax,[edx+ecx]
	call	write
	jc	write_failed
	ret
format_directive:
	cmp	edi,[code_start]
	jne	unexpected_instruction
	mov	ebp,[addressing_space]
	test	byte [ds:ebp+0Ah],1
	jnz	unexpected_instruction
	cmp	[output_format],0
	jne	unexpected_instruction
	lods	byte [esi]
	cmp	al,1Ch
	je	format_prefix
	cmp	al,18h
	jne	invalid_argument
	lods	byte [esi]
      select_format:
	mov	dl,al
	shr	al,4
	mov	[output_format],al
	and	edx,0Fh
	or	[format_flags],edx
	cmp	al,2
	je	format_mz
	cmp	al,3
	je	format_pe
	cmp	al,4
	je	format_coff
	cmp	al,5
	je	format_elf
      format_defined:
	cmp	byte [esi],86h
	jne	instruction_assembled
	cmp	word [esi+1],'('
	jne	invalid_argument
	mov	eax,[esi+3]
	add	esi,3+4
	mov	[file_extension],esi
	lea	esi,[esi+eax+1]
	jmp	instruction_assembled
      format_prefix:
	lods	byte [esi]
	mov	ah,al
	lods	byte [esi]
	cmp	al,18h
	jne	invalid_argument
	lods	byte [esi]
	mov	edx,eax
	shr	dl,4
	shr	dh,4
	cmp	dl,dh
	jne	invalid_argument
	or	al,ah
	jmp	select_format
entry_directive:
	bts	[format_flags],10h
	jc	setting_already_specified
	mov	al,[output_format]
	cmp	al,2
	je	mz_entry
	cmp	al,3
	je	pe_entry
	cmp	al,5
	jne	illegal_instruction
	bt	[format_flags],0
	jc	elf_entry
	jmp	illegal_instruction
stack_directive:
	bts	[format_flags],11h
	jc	setting_already_specified
	mov	al,[output_format]
	cmp	al,2
	je	mz_stack
	cmp	al,3
	je	pe_stack
	jmp	illegal_instruction
heap_directive:
	bts	[format_flags],12h
	jc	setting_already_specified
	mov	al,[output_format]
	cmp	al,2
	je	mz_heap
	cmp	al,3
	je	pe_heap
	jmp	illegal_instruction
segment_directive:
	mov	al,[output_format]
	cmp	al,2
	je	mz_segment
	cmp	al,5
	je	elf_segment
	jmp	illegal_instruction
section_directive:
	mov	al,[output_format]
	cmp	al,3
	je	pe_section
	cmp	al,4
	je	coff_section
	cmp	al,5
	je	elf_section
	jmp	illegal_instruction
public_directive:
	mov	al,[output_format]
	cmp	al,4
	je	public_allowed
	cmp	al,5
	jne	illegal_instruction
	bt	[format_flags],0
	jc	illegal_instruction
      public_allowed:
	mov	[base_code],0C0h
	lods	byte [esi]
	cmp	al,2
	je	public_label
	cmp	al,1Dh
	jne	invalid_argument
	lods	byte [esi]
	and	al,7
	add	[base_code],al
	lods	byte [esi]
	cmp	al,2
	jne	invalid_argument
      public_label:
	lods	dword [esi]
	cmp	eax,0Fh
	jb	invalid_use_of_symbol
	je	reserved_word_used_as_symbol
	inc	esi
	mov	dx,[current_pass]
	mov	[eax+18],dx
	or	byte [eax+8],8
	cmp	[symbols_file],0
	je	public_reference_ok
	cmp	[next_pass_needed],0
	jne	public_reference_ok
	mov	ebx,eax
	call	store_label_reference
	mov	eax,ebx
      public_reference_ok:
	mov	ebx,[free_additional_memory]
	lea	edx,[ebx+10h]
	cmp	edx,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],edx
	mov	[ebx+8],eax
	mov	eax,[current_line]
	mov	[ebx+0Ch],eax
	lods	byte [esi]
	cmp	al,86h
	jne	invalid_argument
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	mov	[ebx+4],esi
	lods	dword [esi]
	lea	esi,[esi+eax+1]
	mov	al,[base_code]
	mov	[ebx],al
	jmp	instruction_assembled
extrn_directive:
	mov	al,[output_format]
	cmp	al,4
	je	extrn_allowed
	cmp	al,5
	jne	illegal_instruction
	bt	[format_flags],0
	jc	illegal_instruction
      extrn_allowed:
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	mov	ebx,esi
	lods	dword [esi]
	lea	esi,[esi+eax+1]
	mov	edx,[free_additional_memory]
	lea	eax,[edx+0Ch]
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],eax
	mov	byte [edx],80h
	mov	[edx+4],ebx
	lods	byte [esi]
	cmp	al,86h
	jne	invalid_argument
	lods	byte [esi]
	cmp	al,2
	jne	invalid_argument
	lods	dword [esi]
	cmp	eax,0Fh
	jb	invalid_use_of_symbol
	je	reserved_word_used_as_symbol
	inc	esi
	mov	ebx,eax
	xor	ah,ah
	lods	byte [esi]
	cmp	al,':'
	je	get_extrn_size
	dec	esi
	cmp	al,11h
	jne	extrn_size_ok
      get_extrn_size:
	lods	word [esi]
	cmp	al,11h
	jne	invalid_argument
      extrn_size_ok:
	mov	[address_symbol],edx
	mov	[label_size],ah
	movzx	ecx,ah
	mov	[edx+8],ecx
	xor	eax,eax
	xor	edx,edx
	xor	ebp,ebp
	mov	[address_sign],0
	mov	ch,2
	test	[format_flags],8
	jz	make_free_label
	mov	ch,4
	jmp	make_free_label
mark_relocation:
	cmp	[value_type],0
	je	relocation_ok
	mov	ebp,[addressing_space]
	test	byte [ds:ebp+0Ah],1
	jnz	relocation_ok
	cmp	[output_format],2
	je	mark_mz_relocation
	cmp	[output_format],3
	je	mark_pe_relocation
	cmp	[output_format],4
	je	mark_coff_relocation
	cmp	[output_format],5
	je	mark_elf_relocation
      relocation_ok:
	ret
close_pass:
	mov	al,[output_format]
	cmp	al,3
	je	close_pe
	cmp	al,4
	je	close_coff
	cmp	al,5
	je	close_elf
	ret

format_mz:
	mov	edx,[additional_memory]
	push	edi
	mov	edi,edx
	mov	ecx,1Ch shr 2
	xor	eax,eax
	rep	stos dword [edi]
	mov	[free_additional_memory],edi
	pop	edi
	mov	word [edx+0Ch],0FFFFh
	mov	word [edx+10h],1000h
	mov	[code_type],16
	jmp	format_defined
mark_mz_relocation:
	push	eax ebx
	inc	word [number_of_relocations]
	jz	format_limitations_exceeded
	mov	ebx,[free_additional_memory]
	mov	eax,edi
	sub	eax,[code_start]
	mov	[ebx],ax
	shr	eax,16
	shl	ax,12
	mov	[ebx+2],ax
	cmp	word [ebx],0FFFFh
	jne	mz_relocation_ok
	inc	word [ebx+2]
	sub	word [ebx],10h
      mz_relocation_ok:
	add	ebx,4
	cmp	ebx,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],ebx
	pop	ebx eax
	ret
mz_segment:
	lods	byte [esi]
	cmp	al,2
	jne	invalid_argument
	lods	dword [esi]
	cmp	eax,0Fh
	jb	invalid_use_of_symbol
	je	reserved_word_used_as_symbol
	inc	esi
	mov	ebx,eax
	mov	eax,edi
	sub	eax,[code_start]
	mov	ecx,0Fh
	add	eax,0Fh
	and	eax,1111b
	sub	ecx,eax
	mov	edx,edi
	xor	eax,eax
	rep	stos byte [edi]
	mov	eax,edx
	call	undefined_data
	push	ebx
	call	create_addressing_space
	pop	ebx
	mov	eax,edi
	sub	eax,[code_start]
	shr	eax,4
	cmp	eax,10000h
	jae	value_out_of_range
	mov	edx,eax
	mov	al,16
	cmp	byte [esi],13h
	jne	segment_type_ok
	inc	esi
	lods	byte [esi]
      segment_type_ok:
	mov	[code_type],al
	mov	eax,edx
	mov	ch,1
	mov	[address_sign],0
	xor	edx,edx
	xor	ebp,ebp
	mov	[label_size],0
	mov	[address_symbol],edx
	jmp	make_free_label
mz_entry:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	call	get_word_value
	cmp	[value_type],1
	je	initial_cs_ok
	call	recoverable_invalid_address
      initial_cs_ok:
	mov	edx,[additional_memory]
	mov	[edx+16h],ax
	lods	byte [esi]
	cmp	al,':'
	jne	invalid_argument
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	ja	invalid_address
	call	get_word_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	edx,[additional_memory]
	mov	[edx+14h],ax
	jmp	instruction_assembled
      recoverable_invalid_address:
	cmp	[error_line],0
	jne	ignore_invalid_address
	push	[current_line]
	pop	[error_line]
	mov	[error],invalid_address
      ignore_invalid_address:
	ret
mz_stack:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	call	get_word_value
	cmp	byte [esi],':'
	je	stack_pointer
	cmp	ax,10h
	jb	invalid_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	edx,[additional_memory]
	mov	[edx+10h],ax
	jmp	instruction_assembled
      stack_pointer:
	cmp	[value_type],1
	je	initial_ss_ok
	call	recoverable_invalid_address
      initial_ss_ok:
	mov	edx,[additional_memory]
	mov	[edx+0Eh],ax
	lods	byte [esi]
	cmp	al,':'
	jne	invalid_argument
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	call	get_word_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	edx,[additional_memory]
	mov	[edx+10h],ax
	bts	[format_flags],4
	jmp	instruction_assembled
mz_heap:
	cmp	[output_format],2
	jne	illegal_instruction
	lods	byte [esi]
	call	get_size_operator
	cmp	ah,1
	je	invalid_value
	cmp	ah,2
	ja	invalid_value
	cmp	al,'('
	jne	invalid_argument
	call	get_word_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	edx,[additional_memory]
	mov	[edx+0Ch],ax
	jmp	instruction_assembled
write_mz_header:
	mov	edx,[additional_memory]
	bt	[format_flags],4
	jc	mz_stack_ok
	mov	eax,[real_code_size]
	dec	eax
	shr	eax,4
	inc	eax
	mov	[edx+0Eh],ax
	shl	eax,4
	movzx	ecx,word [edx+10h]
	add	eax,ecx
	mov	[real_code_size],eax
      mz_stack_ok:
	mov	edi,[free_additional_memory]
	mov	eax,[number_of_relocations]
	shl	eax,2
	add	eax,1Ch
	sub	edi,eax
	xchg	edi,[free_additional_memory]
	mov	ecx,0Fh
	add	eax,0Fh
	and	eax,1111b
	sub	ecx,eax
	xor	al,al
	rep	stos byte [edi]
	sub	edi,[free_additional_memory]
	mov	ecx,edi
	shr	edi,4
	mov	word [edx],'MZ' 	; signature
	mov	[edx+8],di		; header size in paragraphs
	mov	eax,[number_of_relocations]
	mov	[edx+6],ax		; number of relocation entries
	mov	eax,[code_size]
	add	eax,ecx
	mov	esi,eax
	shr	esi,9
	and	eax,1FFh
	inc	si
	or	ax,ax
	jnz	mz_size_ok
	dec	si
      mz_size_ok:
	mov	[edx+2],ax		; number of bytes in last page
	mov	[edx+4],si		; number of pages
	mov	eax,[real_code_size]
	dec	eax
	shr	eax,4
	inc	eax
	mov	esi,[code_size]
	dec	esi
	shr	esi,4
	inc	esi
	sub	eax,esi
	mov	[edx+0Ah],ax		; minimum memory in addition to code
	add	[edx+0Ch],ax		; maximum memory in addition to code
	salc
	mov	ah,al
	or	[edx+0Ch],ax
	mov	word [edx+18h],1Ch	; offset of relocation table
	add	[written_size],ecx
	call	write
	jc	write_failed
	ret

make_stub:
	mov	[stub_file],edx
	or	edx,edx
	jnz	stub_from_file
	push	esi
	mov	edx,edi
	xor	eax,eax
	mov	ecx,20h
	rep	stos dword [edi]
	mov	eax,40h+default_stub_end-default_stub
	mov	cx,100h+default_stub_end-default_stub
	mov	word [edx],'MZ'
	mov	byte [edx+4],1
	mov	word [edx+2],ax
	mov	byte [edx+8],4
	mov	byte [edx+0Ah],10h
	mov	word [edx+0Ch],0FFFFh
	mov	word [edx+10h],cx
	mov	word [edx+3Ch],ax
	mov	byte [edx+18h],40h
	lea	edi,[edx+40h]
	mov	esi,default_stub
	mov	ecx,default_stub_end-default_stub
	rep	movs byte [edi],[esi]
	pop	esi
	jmp	stub_ok
      default_stub:
	use16
	push	cs
	pop	ds
	mov	dx,stub_message-default_stub
	mov	ah,9
	int	21h
	mov	ax,4C01h
	int	21h
      stub_message db 'This program cannot be run in DOS mode.',0Dh,0Ah,24h
	rq	1
      default_stub_end:
	use32
      stub_from_file:
	push	esi
	mov	esi,edx
	call	open_binary_file
	mov	edx,edi
	mov	ecx,1Ch
	mov	esi,edx
	call	read
	jc	binary_stub
	cmp	word [esi],'MZ'
	jne	binary_stub
	add	edi,1Ch
	movzx	ecx,word [esi+6]
	add	ecx,11b
	and	ecx,not 11b
	add	ecx,(40h-1Ch) shr 2
	lea	eax,[edi+ecx*4]
	cmp	edi,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	rep	stos dword [edi]
	mov	edx,40h
	xchg	dx,[esi+18h]
	xor	al,al
	call	lseek
	movzx	ecx,word [esi+6]
	shl	ecx,2
	lea	edx,[esi+40h]
	call	read
	mov	edx,edi
	sub	edx,esi
	shr	edx,4
	xchg	dx,[esi+8]
	shl	edx,4
	xor	al,al
	call	lseek
	movzx	ecx,word [esi+4]
	dec	ecx
	shl	ecx,9
	movzx	edx,word [esi+2]
	test	edx,edx
	jnz	stub_header_size_ok
	mov	dx,200h
     stub_header_size_ok:
	add	ecx,edx
	mov	edx,edi
	sub	ecx,eax
	je	read_stub_code
	jb	stub_code_ok
	push	ecx
	dec	ecx
	shr	ecx,3
	inc	ecx
	shl	ecx,1
	lea	eax,[edi+ecx*4]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	rep	stos dword [edi]
	pop	ecx
     read_stub_code:
	call	read
     stub_code_ok:
	call	close
	mov	edx,edi
	sub	edx,esi
	mov	ax,dx
	and	ax,1FFh
	mov	[esi+2],ax
	dec	edx
	shr	edx,9
	inc	edx
	mov	[esi+4],dx
	mov	eax,edi
	sub	eax,esi
	mov	[esi+3Ch],eax
	pop	esi
      stub_ok:
	ret
      binary_stub:
	mov	esi,edi
	mov	ecx,40h shr 2
	xor	eax,eax
	rep	stos dword [edi]
	mov	al,2
	xor	edx,edx
	call	lseek
	push	eax
	xor	al,al
	xor	edx,edx
	call	lseek
	mov	ecx,[esp]
	add	ecx,40h+111b
	and	ecx,not 111b
	mov	ax,cx
	and	ax,1FFh
	mov	[esi+2],ax
	lea	eax,[ecx+1FFh]
	shr	eax,9
	mov	[esi+4],ax
	mov	[esi+3Ch],ecx
	sub	ecx,40h
	mov	eax,10000h
	sub	eax,ecx
	jbe	binary_heap_ok
	shr	eax,4
	mov	[esi+0Ah],ax
      binary_heap_ok:
	mov	word [esi],'MZ'
	mov	byte [esi+8],4
	mov	ax,0FFFFh
	mov	[esi+0Ch],ax
	dec	ax
	mov	[esi+10h],ax
	sub	ax,0Eh
	mov	[esi+0Eh],ax
	mov	[esi+16h],ax
	mov	word [esi+14h],100h
	mov	byte [esi+18h],40h
	mov	eax,[tagged_blocks]
	sub	eax,ecx
	cmp	edi,eax
	jae	out_of_memory
	mov	edx,edi
	shr	ecx,2
	xor	eax,eax
	rep	stos dword [edi]
	pop	ecx
	call	read
	call	close
	pop	esi
	ret

format_pe:
	xor	edx,edx
	mov	[machine],14Ch
	mov	[subsystem],3
	mov	[subsystem_version],3 + 10 shl 16
	mov	[image_base],400000h
	and	[image_base_high],0
	test	[format_flags],8
	jz	pe_settings
	mov	[machine],8664h
	mov	[subsystem_version],5 + 0 shl 16
      pe_settings:
	cmp	byte [esi],84h
	je	get_stub_name
	cmp	byte [esi],80h
	je	get_pe_base
	cmp	byte [esi],1Bh
	jne	pe_settings_ok
	lods	byte [esi]
	lods	byte [esi]
	test	al,80h+40h
	jz	subsystem_setting
	cmp	al,80h
	je	dll_flag
	cmp	al,81h
	je	wdm_flag
	cmp	al,82h
	je	large_flag
	cmp	al,83h
	je	nx_flag
	jmp	pe_settings
      dll_flag:
	bts	[format_flags],8
	jc	setting_already_specified
	jmp	pe_settings
      wdm_flag:
	bts	[format_flags],9
	jc	setting_already_specified
	jmp	pe_settings
      large_flag:
	bts	[format_flags],11
	jc	setting_already_specified
	test	[format_flags],8
	jnz	invalid_argument
	jmp	pe_settings
      nx_flag:
	bts	[format_flags],12
	jc	setting_already_specified
	jmp	pe_settings
      subsystem_setting:
	bts	[format_flags],7
	jc	setting_already_specified
	and	ax,3Fh
	mov	[subsystem],ax
	cmp	ax,10
	jb	subsystem_type_ok
	or	[format_flags],4
      subsystem_type_ok:
	cmp	byte [esi],'('
	jne	pe_settings
	inc	esi
	cmp	byte [esi],'.'
	jne	invalid_value
	inc	esi
	push	edx
	cmp	byte [esi+11],0
	jne	invalid_value
	cmp	byte [esi+10],2
	ja	invalid_value
	mov	dx,[esi+8]
	cmp	dx,8000h
	je	zero_version
	mov	eax,[esi+4]
	cmp	dx,7
	jg	invalid_value
	mov	cx,7
	sub	cx,dx
	mov	eax,[esi+4]
	shr	eax,cl
	mov	ebx,eax
	shr	ebx,24
	cmp	bl,100
	jae	invalid_value
	and	eax,0FFFFFFh
	mov	ecx,100
	mul	ecx
	shrd	eax,edx,24
	jnc	version_value_ok
	inc	eax
      version_value_ok:
	shl	eax,16
	mov	ax,bx
	jmp	subsystem_version_ok
      zero_version:
	xor	eax,eax
      subsystem_version_ok:
	pop	edx
	add	esi,13
	mov	[subsystem_version],eax
	jmp	pe_settings
      get_pe_base:
	bts	[format_flags],10
	jc	setting_already_specified
	lods	word [esi]
	cmp	ah,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	push	edx edi
	add	edi,[stub_size]
	test	[format_flags],4
	jnz	get_peplus_base
	call	get_dword_value
	mov	[image_base],eax
	jmp	pe_base_ok
      get_peplus_base:
	call	get_qword_value
	mov	[image_base],eax
	mov	[image_base_high],edx
      pe_base_ok:
	pop	edi edx
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	cmp	byte [esi],84h
	jne	pe_settings_ok
      get_stub_name:
	lods	byte [esi]
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	lods	dword [esi]
	mov	edx,esi
	add	esi,eax
	inc	esi
      pe_settings_ok:
	mov	ebp,[stub_size]
	or	ebp,ebp
	jz	make_pe_stub
	cmp	edx,[stub_file]
	je	pe_stub_ok
	sub	edi,[stub_size]
	mov	[code_start],edi
      make_pe_stub:
	call	make_stub
	mov	eax,edi
	sub	eax,[code_start]
	mov	[stub_size],eax
	mov	[code_start],edi
	mov	ebp,eax
      pe_stub_ok:
	mov	edx,edi
	mov	ecx,18h+0E0h
	test	[format_flags],4
	jz	zero_pe_header
	add	ecx,10h
      zero_pe_header:
	add	ebp,ecx
	shr	ecx,2
	xor	eax,eax
	rep	stos dword [edi]
	mov	word [edx],'PE' 	; signature
	mov	ax,[machine]
	mov	word [edx+4],ax
	mov	byte [edx+38h+1],10h	; section alignment
	mov	byte [edx+3Ch+1],2	; file alignment
	mov	byte [edx+40h],1	; OS version
	mov	eax,[subsystem_version]
	mov	[edx+48h],eax
	mov	ax,[subsystem]
	mov	[edx+5Ch],ax
	cmp	ax,1
	jne	pe_alignment_ok
	mov	eax,20h
	mov	dword [edx+38h],eax
	mov	dword [edx+3Ch],eax
      pe_alignment_ok:
	mov	word [edx+1Ah],VERSION_MAJOR + VERSION_MINOR shl 8
	test	[format_flags],4
	jnz	init_peplus_specific
	mov	byte [edx+14h],0E0h	; size of optional header
	mov	dword [edx+16h],10B010Fh; flags and magic value
	mov	eax,[image_base]
	mov	[edx+34h],eax
	mov	byte [edx+60h+1],10h	; stack reserve
	mov	byte [edx+64h+1],10h	; stack commit
	mov	byte [edx+68h+2],1	; heap reserve
	mov	byte [edx+74h],16	; number of directories
	jmp	pe_header_ok
      init_peplus_specific:
	mov	byte [edx+14h],0F0h	; size of optional header
	mov	dword [edx+16h],20B002Fh; flags and magic value
	mov	eax,[image_base]
	mov	[edx+30h],eax
	mov	eax,[image_base_high]
	mov	[edx+34h],eax
	mov	byte [edx+60h+1],10h	; stack reserve
	mov	byte [edx+68h+1],10h	; stack commit
	mov	byte [edx+70h+2],1	; heap reserve
	mov	byte [edx+84h],16	; number of directories
      pe_header_ok:
	bsf	ecx,[edx+3Ch]
	imul	ebx,[number_of_sections],28h
	or	ebx,ebx
	jnz	reserve_space_for_section_headers
	mov	ebx,28h
      reserve_space_for_section_headers:
	add	ebx,ebp
	dec	ebx
	shr	ebx,cl
	inc	ebx
	shl	ebx,cl
	sub	ebx,ebp
	mov	ecx,ebx
	mov	eax,[tagged_blocks]
	sub	eax,ecx
	cmp	edi,eax
	jae	out_of_memory
	shr	ecx,2
	xor	eax,eax
	rep	stos dword [edi]
	mov	eax,edi
	sub	eax,[code_start]
	add	eax,[stub_size]
	mov	[edx+54h],eax		; size of headers
	mov	ecx,[edx+38h]
	dec	ecx
	add	eax,ecx
	not	ecx
	and	eax,ecx
	bt	[format_flags],8
	jc	pe_entry_init_ok
	mov	[edx+28h],eax		; entry point rva
      pe_entry_init_ok:
	and	[number_of_sections],0
	movzx	ebx,word [edx+14h]
	lea	ebx,[edx+18h+ebx]
	mov	[current_section],ebx
	mov	dword [ebx],'.fla'
	mov	dword [ebx+4],'t'
	mov	[ebx+14h],edi
	mov	[ebx+0Ch],eax
	mov	dword [ebx+24h],0E0000060h
	xor	ecx,ecx
	xor	bl,bl
	not	eax
	not	ecx
	not	bl
	add	eax,1
	adc	ecx,0
	adc	bl,0
	add	eax,edi
	adc	ecx,0
	adc	bl,0
	test	[format_flags],4
	jnz	peplus_org
	sub	eax,[edx+34h]
	sbb	ecx,0
	sbb	bl,0
	jmp	pe_org_ok
      peplus_org:
	sub	eax,[edx+30h]
	sbb	ecx,[edx+34h]
	sbb	bl,0
      pe_org_ok:
	test	[format_flags],8
	jnz	pe64_code
	mov	bh,2
	mov	[code_type],32
	jmp	pe_code_type_ok
      pe64_code:
	mov	bh,4
	mov	[code_type],64
      pe_code_type_ok:
	bt	[resolver_flags],0
	jc	pe_labels_type_ok
	xor	bh,bh
      pe_labels_type_ok:
	push	eax ebx
	call	init_addressing_space
	mov	ebp,ebx
	pop	ebx eax
	mov	[ds:ebp],eax
	mov	[ds:ebp+4],ecx
	mov	[ds:ebp+8],bx
	mov	[ds:ebp+18h],edi
	bt	[format_flags],8
	jnc	dll_flag_ok
	or	byte [edx+16h+1],20h
      dll_flag_ok:
	bt	[format_flags],9
	jnc	wdm_flag_ok
	or	byte [edx+5Eh+1],20h
      wdm_flag_ok:
	bt	[format_flags],11
	jnc	large_flag_ok
	or	byte [edx+16h],20h
      large_flag_ok:
	bt	[format_flags],12
	jnc	nx_ok
	or	byte [edx+5Eh+1],1
      nx_ok:
	jmp	format_defined
pe_section:
	call	close_pe_section
	push	eax ebx
	call	create_addressing_space
	mov	ebp,ebx
	pop	ebx eax
	bts	[format_flags],5
	lea	ecx,[ebx+28h]
	add	edx,[edx+54h]
	sub	edx,[stub_size]
	cmp	ecx,edx
	jbe	new_section
	lea	ebx,[edx-28h]
	or	[next_pass_needed],-1
	push	edi
	mov	edi,ebx
	mov	ecx,28h shr 4
	xor	eax,eax
	rep	stos dword [edi]
	pop	edi
      new_section:
	mov	[ebx+0Ch],eax
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	lea	edx,[esi+4]
	mov	ecx,[esi]
	lea	esi,[esi+4+ecx+1]
	cmp	ecx,8
	ja	name_too_long
	xor	eax,eax
	mov	[ebx],eax
	mov	[ebx+4],eax
	push	esi edi
	mov	edi,ebx
	mov	esi,edx
	rep	movs byte [edi],[esi]
	pop	edi esi
	and	dword [ebx+24h],0
	mov	[ebx+14h],edi
	mov	edx,[code_start]
	mov	eax,edi
	xor	ecx,ecx
	sub	eax,[ebx+0Ch]
	sbb	ecx,0
	sbb	byte [ds:ebp+8],0
	mov	byte [ds:ebp+9],2
	mov	[code_type],32
	test	[format_flags],8
	jz	pe_section_code_type_ok
	mov	byte [ds:ebp+9],4
	mov	[code_type],64
      pe_section_code_type_ok:
	test	[format_flags],4
	jnz	peplus_section_org
	sub	eax,[edx+34h]
	sbb	ecx,0
	sbb	byte [ds:ebp+8],0
	bt	[resolver_flags],0
	jc	pe_section_org_ok
	mov	byte [ds:ebp+9],0
	jmp	pe_section_org_ok
      peplus_section_org:
	sub	eax,[edx+30h]
	sbb	ecx,[edx+34h]
	sbb	byte [ds:ebp+8],0
	bt	[resolver_flags],0
	jc	pe_section_org_ok
	mov	byte [ds:ebp+9],0
      pe_section_org_ok:
	mov	[ds:ebp],eax
	mov	[ds:ebp+4],ecx
	mov	[ds:ebp+18h],edi
      get_section_flags:
	lods	byte [esi]
	cmp	al,1Ah
	je	set_directory
	cmp	al,19h
	je	section_flag
	dec	esi
	jmp	instruction_assembled
      set_directory:
	movzx	eax,byte [esi]
	inc	esi
	mov	ecx,ebx
	test	[format_flags],4
	jnz	peplus_directory
	xchg	ecx,[edx+78h+eax*8]
	mov	dword [edx+78h+eax*8+4],-1
	jmp	pe_directory_set
      peplus_directory:
	xchg	ecx,[edx+88h+eax*8]
	mov	dword [edx+88h+eax*8+4],-1
      pe_directory_set:
	or	ecx,ecx
	jnz	data_already_defined
	push	ebx edx
	call	generate_pe_data
	pop	edx ebx
	jmp	get_section_flags
      section_flag:
	lods	byte [esi]
	cmp	al,9
	je	invalid_argument
	cmp	al,11
	je	invalid_argument
	mov	cl,al
	mov	eax,1
	shl	eax,cl
	test	dword [ebx+24h],eax
	jnz	setting_already_specified
	or	dword [ebx+24h],eax
	jmp	get_section_flags
      close_pe_section:
	mov	ebx,[current_section]
	mov	edx,[code_start]
	mov	eax,edi
	sub	eax,[ebx+14h]
	jnz	finish_section
	bt	[format_flags],5
	jc	finish_section
	mov	eax,[ebx+0Ch]
	ret
      finish_section:
	mov	[ebx+8],eax
	cmp	edi,[undefined_data_end]
	jne	align_section
	cmp	dword [edx+38h],1000h
	jb	align_section
	mov	edi,[undefined_data_start]
      align_section:
	and	[undefined_data_end],0
	mov	ebp,edi
	sub	ebp,[ebx+14h]
	mov	ecx,[edx+3Ch]
	dec	ecx
	lea	eax,[ebp+ecx]
	not	ecx
	and	eax,ecx
	mov	[ebx+10h],eax
	sub	eax,ebp
	mov	ecx,eax
	xor	al,al
	rep	stos byte [edi]
	mov	eax,[code_start]
	sub	eax,[stub_size]
	sub	[ebx+14h],eax
	mov	ecx,[ebx+10h]
	test	byte [ebx+24h],20h
	jz	pe_code_sum_ok
	add	[edx+1Ch],ecx
	cmp	dword [edx+2Ch],0
	jne	pe_code_sum_ok
	mov	eax,[ebx+0Ch]
	mov	[edx+2Ch],eax
      pe_code_sum_ok:
	test	byte [ebx+24h],40h
	jz	pe_data_sum_ok
	add	[edx+20h],ecx
	test	[format_flags],4
	jnz	pe_data_sum_ok
	cmp	dword [edx+30h],0
	jne	pe_data_sum_ok
	mov	eax,[ebx+0Ch]
	mov	[edx+30h],eax
      pe_data_sum_ok:
	mov	eax,[ebx+8]
	or	eax,eax
	jz	udata_ok
	cmp	dword [ebx+10h],0
	jne	udata_ok
	or	byte [ebx+24h],80h
	add	[edx+24h],ecx
      udata_ok:
	mov	ecx,[edx+38h]
	dec	ecx
	add	eax,ecx
	not	ecx
	and	eax,ecx
	add	eax,[ebx+0Ch]
	add	ebx,28h
	mov	[current_section],ebx
	inc	word [number_of_sections]
	jz	format_limitations_exceeded
	ret
data_directive:
	cmp	[output_format],3
	jne	illegal_instruction
	lods	byte [esi]
	cmp	al,1Ah
	je	predefined_data_type
	cmp	al,'('
	jne	invalid_argument
	call	get_byte_value
	cmp	al,16
	jb	data_type_ok
	jmp	invalid_value
      predefined_data_type:
	movzx	eax,byte [esi]
	inc	esi
      data_type_ok:
	mov	ebx,[current_section]
	mov	ecx,edi
	sub	ecx,[ebx+14h]
	add	ecx,[ebx+0Ch]
	mov	edx,[code_start]
	test	[format_flags],4
	jnz	peplus_data
	xchg	ecx,[edx+78h+eax*8]
	jmp	init_pe_data
      peplus_data:
	xchg	ecx,[edx+88h+eax*8]
      init_pe_data:
	or	ecx,ecx
	jnz	data_already_defined
	call	allocate_structure_data
	mov	word [ebx],data_directive-instruction_handler
	mov	[ebx+2],al
	mov	edx,[current_line]
	mov	[ebx+4],edx
	call	generate_pe_data
	jmp	instruction_assembled
      end_data:
	cmp	[output_format],3
	jne	illegal_instruction
	call	find_structure_data
	jc	unexpected_instruction
	movzx	eax,byte [ebx+2]
	mov	edx,[current_section]
	mov	ecx,edi
	sub	ecx,[edx+14h]
	add	ecx,[edx+0Ch]
	mov	edx,[code_start]
	test	[format_flags],4
	jnz	end_peplus_data
	sub	ecx,[edx+78h+eax*8]
	mov	[edx+78h+eax*8+4],ecx
	jmp	remove_structure_data
      end_peplus_data:
	sub	ecx,[edx+88h+eax*8]
	mov	[edx+88h+eax*8+4],ecx
	jmp	remove_structure_data
pe_entry:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	test	[format_flags],8
	jnz	pe64_entry
	call	get_dword_value
	mov	bl,2
	bt	[resolver_flags],0
	jc	check_pe_entry_label_type
	xor	bl,bl
      check_pe_entry_label_type:
	cmp	[value_type],bl
	je	pe_entry_ok
	call	recoverable_invalid_address
      pe_entry_ok:
      cdq
	test	[format_flags],4
	jnz	pe64_entry_type_ok
	mov	edx,[code_start]
	sub	eax,[edx+34h]
	mov	[edx+28h],eax
	jmp	instruction_assembled
      pe64_entry:
	call	get_qword_value
	mov	bl,4
	bt	[resolver_flags],0
	jc	check_pe64_entry_label_type
	xor	bl,bl
      check_pe64_entry_label_type:
	cmp	[value_type],bl
	je	pe64_entry_type_ok
	call	recoverable_invalid_address
      pe64_entry_type_ok:
	mov	ecx,[code_start]
	sub	eax,[ecx+30h]
	sbb	edx,[ecx+34h]
	jz	pe64_entry_range_ok
	call	recoverable_overflow
      pe64_entry_range_ok:
	mov	[ecx+28h],eax
	jmp	instruction_assembled
pe_stack:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	test	[format_flags],4
	jnz	peplus_stack
	call	get_count_value
	mov	edx,[code_start]
	mov	[edx+60h],eax
	cmp	byte [esi],','
	jne	default_stack_commit
	lods	byte [esi]
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	call	get_count_value
	mov	edx,[code_start]
	mov	[edx+64h],eax
	cmp	eax,[edx+60h]
	ja	value_out_of_range
	jmp	instruction_assembled
      default_stack_commit:
	mov	dword [edx+64h],1000h
	mov	eax,[edx+60h]
	cmp	eax,1000h
	ja	instruction_assembled
	mov	dword [edx+64h],eax
	jmp	instruction_assembled
      peplus_stack:
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	ecx,[code_start]
	mov	[ecx+60h],eax
	mov	[ecx+64h],edx
	cmp	byte [esi],','
	jne	default_peplus_stack_commit
	lods	byte [esi]
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	ecx,[code_start]
	mov	[ecx+68h],eax
	mov	[ecx+6Ch],edx
	cmp	edx,[ecx+64h]
	ja	value_out_of_range
	jb	instruction_assembled
	cmp	eax,[ecx+60h]
	ja	value_out_of_range
	jmp	instruction_assembled
      default_peplus_stack_commit:
	mov	dword [ecx+68h],1000h
	cmp	dword [ecx+64h],0
	jne	instruction_assembled
	mov	eax,[ecx+60h]
	cmp	eax,1000h
	ja	instruction_assembled
	mov	dword [ecx+68h],eax
	jmp	instruction_assembled
pe_heap:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	test	[format_flags],4
	jnz	peplus_heap
	call	get_count_value
	mov	edx,[code_start]
	mov	[edx+68h],eax
	cmp	byte [esi],','
	jne	instruction_assembled
	lods	byte [esi]
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	call	get_count_value
	mov	edx,[code_start]
	mov	[edx+6Ch],eax
	cmp	eax,[edx+68h]
	ja	value_out_of_range
	jmp	instruction_assembled
      peplus_heap:
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	ecx,[code_start]
	mov	[ecx+70h],eax
	mov	[ecx+74h],edx
	cmp	byte [esi],','
	jne	instruction_assembled
	lods	byte [esi]
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	ecx,[code_start]
	mov	[ecx+78h],eax
	mov	[ecx+7Ch],edx
	cmp	edx,[ecx+74h]
	ja	value_out_of_range
	jb	instruction_assembled
	cmp	eax,[ecx+70h]
	ja	value_out_of_range
	jmp	instruction_assembled
mark_pe_relocation:
	push	eax ebx
	test	[format_flags],4
	jz	check_standard_pe_relocation_type
	cmp	[value_type],4
	je	pe_relocation_type_ok
      check_standard_pe_relocation_type:
	cmp	[value_type],2
	je	pe_relocation_type_ok
	call	recoverable_misuse
      pe_relocation_type_ok:
	mov	ebx,[current_section]
	mov	eax,edi
	sub	eax,[ebx+14h]
	add	eax,[ebx+0Ch]
	mov	ebx,[free_additional_memory]
	inc	[number_of_relocations]
	add	ebx,5
	cmp	ebx,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],ebx
	mov	[ebx-5],eax
	cmp	[value_type],2
	je	fixup_32bit
	mov	byte [ebx-1],0Ah
	jmp	fixup_ok
      fixup_32bit:
	mov	byte [ebx-1],3
      fixup_ok:
	pop	ebx eax
	ret
generate_pe_data:
	cmp	al,2
	je	make_pe_resource
	cmp	al,5
	je	make_pe_fixups
	ret
make_pe_fixups:
	mov	edx,[code_start]
	and	byte [edx+16h],not 1
	or	byte [edx+5Eh],40h
	bts	[resolver_flags],0
	jc	fixups_ready
	or	[next_pass_needed],-1
      fixups_ready:
	and	[last_fixup_base],0
	call	make_fixups
	xchg	eax,[actual_fixups_size]
	sub	eax,[actual_fixups_size]
	ja	reserve_forward_fixups
	xor	eax,eax
      reserve_forward_fixups:
	mov	[reserved_fixups],edi
	add	edi,eax
	mov	[reserved_fixups_size],eax
	ret
      make_fixups:
	push	esi
	xor	ecx,ecx
	xchg	ecx,[number_of_relocations]
	mov	esi,[free_additional_memory]
	lea	eax,[ecx*5]
	sub	esi,eax
	mov	[free_additional_memory],esi
	mov	edx,[last_fixup_base]
	mov	ebx,[last_fixup_header]
	mov	ebp,edi
	jecxz	fixups_done
      make_fixup:
	cmp	[esi],edx
	jb	store_fixup
	mov	eax,edi
	sub	eax,ebp
	test	eax,11b
	jz	fixups_block
	xor	ax,ax
	stos	word [edi]
	add	dword [ebx],2
      fixups_block:
	mov	eax,edx
	add	edx,1000h
	cmp	[esi],edx
	jae	fixups_block
	stos	dword [edi]
	mov	ebx,edi
	mov	eax,8
	stos	dword [edi]
      store_fixup:
	add	dword [ebx],2
	mov	ah,[esi+1]
	and	ah,0Fh
	mov	al,[esi+4]
	shl	al,4
	or	ah,al
	mov	al,[esi]
	stos	word [edi]
	add	esi,5
	loop	make_fixup
      fixups_done:
	mov	[last_fixup_base],edx
	mov	[last_fixup_header],ebx
	pop	esi
	mov	eax,edi
	sub	eax,ebp
	ret
make_pe_resource:
	cmp	byte [esi],82h
	jne	resource_done
	inc	esi
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	lods	dword [esi]
	mov	edx,esi
	lea	esi,[esi+eax+1]
	cmp	[next_pass_needed],0
	je	resource_from_file
	cmp	[current_pass],0
	jne	reserve_space_for_resource
	and	[resource_size],0
      reserve_space_for_resource:
	add	edi,[resource_size]
	cmp	edi,[tagged_blocks]
	ja	out_of_memory
	jmp	resource_done
      resource_from_file:
	push	esi
	mov	esi,edx
	call	open_binary_file
	push	ebx
	mov	esi,[free_additional_memory]
	lea	eax,[esi+20h]
	cmp	eax,[structures_buffer]
	ja	out_of_memory
	mov	edx,esi
	mov	ecx,20h
	call	read
	jc	invalid_file_format
	xor	eax,eax
	cmp	[esi],eax
	jne	invalid_file_format
	mov	ax,0FFFFh
	cmp	[esi+8],eax
	jne	invalid_file_format
	cmp	[esi+12],eax
	jne	invalid_file_format
	mov	eax,20h
	cmp	[esi+4],eax
	jne	invalid_file_format
      read_resource_headers:
	test	eax,11b
	jz	resource_file_alignment_ok
	mov	edx,4
	and	eax,11b
	sub	edx,eax
	mov	al,1
	call	lseek
      resource_file_alignment_ok:
	mov	[esi],eax
	lea	edx,[esi+12]
	mov	ecx,8
	call	read
	jc	resource_headers_ok
	mov	ecx,[esi+16]
	add	[esi],ecx
	lea	edx,[esi+20]
	sub	ecx,8
	mov	[esi+16],ecx
	lea	eax,[edx+ecx]
	cmp	eax,[structures_buffer]
	ja	out_of_memory
	call	read
	jc	invalid_file_format
	mov	edx,[esi]
	add	edx,[esi+12]
	mov	eax,[esi+16]
	lea	ecx,[esi+20]
	lea	esi,[ecx+eax]
	add	ecx,2
	cmp	word [ecx-2],0FFFFh
	je	resource_header_type_ok
      check_resource_header_type:
	cmp	ecx,esi
	jae	invalid_file_format
	cmp	word [ecx],0
	je	resource_header_type_ok
	add	ecx,2
	jmp	check_resource_header_type
      resource_header_type_ok:
	add	ecx,2
	cmp	word [ecx],0FFFFh
	je	resource_header_name_ok
      check_resource_header_name:
	cmp	ecx,esi
	jae	invalid_file_format
	cmp	word [ecx],0
	je	resource_header_name_ok
	add	ecx,2
	jmp	check_resource_header_name
      resource_header_name_ok:
	xor	al,al
	call	lseek
	jmp	read_resource_headers
      resource_headers_ok:
	xor	eax,eax
	mov	[esi],eax
	mov	[resource_data],edi
	lea	eax,[edi+16]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	stos	dword [edi]
	call	make_timestamp
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	xor	ebx,ebx
      make_type_name_directory:
	mov	esi,[free_additional_memory]
	xor	edx,edx
      find_type_name:
	cmp	dword [esi],0
	je	type_name_ok
	add	esi,20
	cmp	word [esi],0FFFFh
	je	check_next_type_name
	or	ebx,ebx
	jz	check_this_type_name
	xor	ecx,ecx
      compare_with_previous_type_name:
	mov	ax,[esi+ecx]
	cmp	ax,[ebx+ecx]
	ja	check_this_type_name
	jb	check_next_type_name
	add	ecx,2
	mov	ax,[esi+ecx]
	or	ax,[ebx+ecx]
	jnz	compare_with_previous_type_name
	jmp	check_next_type_name
      check_this_type_name:
	or	edx,edx
	jz	type_name_found
	xor	ecx,ecx
      compare_with_current_type_name:
	mov	ax,[esi+ecx]
	cmp	ax,[edx+ecx]
	ja	check_next_type_name
	jb	type_name_found
	add	ecx,2
	mov	ax,[esi+ecx]
	or	ax,[edx+ecx]
	jnz	compare_with_current_type_name
	jmp	same_type_name
      type_name_found:
	mov	edx,esi
      same_type_name:
	mov	[esi-16],edi
      check_next_type_name:
	mov	eax,[esi-4]
	add	esi,eax
	jmp	find_type_name
      type_name_ok:
	or	edx,edx
	jz	type_name_directory_done
	mov	ebx,edx
      make_type_name_entry:
	mov	eax,[resource_data]
	inc	word [eax+12]
	lea	eax,[edi+8]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,ebx
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	jmp	make_type_name_directory
      type_name_directory_done:
	mov	ebx,-1
      make_type_id_directory:
	mov	esi,[free_additional_memory]
	mov	edx,10000h
      find_type_id:
	cmp	dword [esi],0
	je	type_id_ok
	add	esi,20
	cmp	word [esi],0FFFFh
	jne	check_next_type_id
	movzx	eax,word [esi+2]
	cmp	eax,ebx
	jle	check_next_type_id
	cmp	eax,edx
	jg	check_next_type_id
	mov	edx,eax
	mov	[esi-16],edi
      check_next_type_id:
	mov	eax,[esi-4]
	add	esi,eax
	jmp	find_type_id
      type_id_ok:
	cmp	edx,10000h
	je	type_id_directory_done
	mov	ebx,edx
      make_type_id_entry:
	mov	eax,[resource_data]
	inc	word [eax+14]
	lea	eax,[edi+8]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,ebx
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	jmp	make_type_id_directory
      type_id_directory_done:
	mov	esi,[resource_data]
	add	esi,10h
	mov	ecx,[esi-4]
	or	cx,cx
	jz	resource_directories_ok
      make_resource_directories:
	push	ecx
	push	edi
	mov	edx,edi
	sub	edx,[resource_data]
	bts	edx,31
	mov	[esi+4],edx
	lea	eax,[edi+16]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	stos	dword [edi]
	call	make_timestamp
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	mov	ebp,esi
	xor	ebx,ebx
      make_resource_name_directory:
	mov	esi,[free_additional_memory]
	xor	edx,edx
      find_resource_name:
	cmp	dword [esi],0
	je	resource_name_ok
	push	esi
	cmp	[esi+4],ebp
	jne	check_next_resource_name
	add	esi,20
	call	skip_resource_name
	cmp	word [esi],0FFFFh
	je	check_next_resource_name
	or	ebx,ebx
	jz	check_this_resource_name
	xor	ecx,ecx
      compare_with_previous_resource_name:
	mov	ax,[esi+ecx]
	cmp	ax,[ebx+ecx]
	ja	check_this_resource_name
	jb	check_next_resource_name
	add	ecx,2
	mov	ax,[esi+ecx]
	or	ax,[ebx+ecx]
	jnz	compare_with_previous_resource_name
	jmp	check_next_resource_name
      skip_resource_name:
	cmp	word [esi],0FFFFh
	jne	skip_unicode_string
	add	esi,4
	ret
      skip_unicode_string:
	add	esi,2
	cmp	word [esi-2],0
	jne	skip_unicode_string
	ret
      check_this_resource_name:
	or	edx,edx
	jz	resource_name_found
	xor	ecx,ecx
      compare_with_current_resource_name:
	mov	ax,[esi+ecx]
	cmp	ax,[edx+ecx]
	ja	check_next_resource_name
	jb	resource_name_found
	add	ecx,2
	mov	ax,[esi+ecx]
	or	ax,[edx+ecx]
	jnz	compare_with_current_resource_name
	jmp	same_resource_name
      resource_name_found:
	mov	edx,esi
      same_resource_name:
	mov	eax,[esp]
	mov	[eax+8],edi
      check_next_resource_name:
	pop	esi
	mov	eax,[esi+16]
	lea	esi,[esi+20+eax]
	jmp	find_resource_name
      resource_name_ok:
	or	edx,edx
	jz	resource_name_directory_done
	mov	ebx,edx
      make_resource_name_entry:
	mov	eax,[esp]
	inc	word [eax+12]
	lea	eax,[edi+8]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,ebx
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	jmp	make_resource_name_directory
      resource_name_directory_done:
	mov	ebx,-1
      make_resource_id_directory:
	mov	esi,[free_additional_memory]
	mov	edx,10000h
      find_resource_id:
	cmp	dword [esi],0
	je	resource_id_ok
	push	esi
	cmp	[esi+4],ebp
	jne	check_next_resource_id
	add	esi,20
	call	skip_resource_name
	cmp	word [esi],0FFFFh
	jne	check_next_resource_id
	movzx	eax,word [esi+2]
	cmp	eax,ebx
	jle	check_next_resource_id
	cmp	eax,edx
	jg	check_next_resource_id
	mov	edx,eax
	mov	eax,[esp]
	mov	[eax+8],edi
      check_next_resource_id:
	pop	esi
	mov	eax,[esi+16]
	lea	esi,[esi+20+eax]
	jmp	find_resource_id
      resource_id_ok:
	cmp	edx,10000h
	je	resource_id_directory_done
	mov	ebx,edx
      make_resource_id_entry:
	mov	eax,[esp]
	inc	word [eax+14]
	lea	eax,[edi+8]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,ebx
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	jmp	make_resource_id_directory
      resource_id_directory_done:
	pop	eax
	mov	esi,ebp
	pop	ecx
	add	esi,8
	dec	cx
	jnz	make_resource_directories
      resource_directories_ok:
	shr	ecx,16
	jnz	make_resource_directories
	mov	esi,[resource_data]
	add	esi,10h
	movzx	eax,word [esi-4]
	movzx	edx,word [esi-2]
	add	eax,edx
	lea	esi,[esi+eax*8]
	push	edi			; address of language directories
      update_resource_directories:
	cmp	esi,[esp]
	je	resource_directories_updated
	add	esi,10h
	mov	ecx,[esi-4]
	or	cx,cx
	jz	language_directories_ok
      make_language_directories:
	push	ecx
	push	edi
	mov	edx,edi
	sub	edx,[resource_data]
	bts	edx,31
	mov	[esi+4],edx
	lea	eax,[edi+16]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	stos	dword [edi]
	call	make_timestamp
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	mov	ebp,esi
	mov	ebx,-1
      make_language_id_directory:
	mov	esi,[free_additional_memory]
	mov	edx,10000h
      find_language_id:
	cmp	dword [esi],0
	je	language_id_ok
	push	esi
	cmp	[esi+8],ebp
	jne	check_next_language_id
	add	esi,20
	mov	eax,esi
	call	skip_resource_name
	call	skip_resource_name
	neg	eax
	add	eax,esi
	and	eax,11b
	add	esi,eax
      get_language_id:
	movzx	eax,word [esi+6]
	cmp	eax,ebx
	jle	check_next_language_id
	cmp	eax,edx
	jge	check_next_language_id
	mov	edx,eax
	mov	eax,[esp]
	mov	dword [value],eax
      check_next_language_id:
	pop	esi
	mov	eax,[esi+16]
	lea	esi,[esi+20+eax]
	jmp	find_language_id
      language_id_ok:
	cmp	edx,10000h
	je	language_id_directory_done
	mov	ebx,edx
      make_language_id_entry:
	mov	eax,[esp]
	inc	word [eax+14]
	lea	eax,[edi+8]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,ebx
	stos	dword [edi]
	mov	eax,dword [value]
	stos	dword [edi]
	jmp	make_language_id_directory
      language_id_directory_done:
	pop	eax
	mov	esi,ebp
	pop	ecx
	add	esi,8
	dec	cx
	jnz	make_language_directories
      language_directories_ok:
	shr	ecx,16
	jnz	make_language_directories
	jmp	update_resource_directories
      resource_directories_updated:
	mov	esi,[resource_data]
	push	edi
      make_name_strings:
	add	esi,10h
	movzx	eax,word [esi-2]
	movzx	ecx,word [esi-4]
	add	eax,ecx
	lea	eax,[esi+eax*8]
	push	eax
	or	ecx,ecx
	jz	string_entries_processed
      process_string_entries:
	push	ecx
	mov	edx,edi
	sub	edx,[resource_data]
	bts	edx,31
	xchg	[esi],edx
	mov	ebx,edi
	xor	ax,ax
	stos	word [edi]
      copy_string_data:
	lea	eax,[edi+2]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	ax,[edx]
	or	ax,ax
	jz	string_data_copied
	stos	word [edi]
	inc	word [ebx]
	add	edx,2
	jmp	copy_string_data
      string_data_copied:
	add	esi,8
	pop	ecx
	loop	process_string_entries
      string_entries_processed:
	pop	esi
	cmp	esi,[esp]
	jb	make_name_strings
	mov	eax,edi
	sub	eax,[resource_data]
	test	al,11b
	jz	resource_strings_alignment_ok
	xor	ax,ax
	stos	word [edi]
      resource_strings_alignment_ok:
	pop	edx
	pop	ebx			; address of language directories
	mov	ebp,edi
      update_language_directories:
	add	ebx,10h
	movzx	eax,word [ebx-2]
	movzx	ecx,word [ebx-4]
	add	ecx,eax
      make_data_records:
	push	ecx
	mov	esi,edi
	sub	esi,[resource_data]
	xchg	esi,[ebx+4]
	lea	eax,[edi+16]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	mov	eax,esi
	stos	dword [edi]
	mov	eax,[esi+12]
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	pop	ecx
	add	ebx,8
	loop	make_data_records
	cmp	ebx,edx
	jb	update_language_directories
	pop	ebx			; file handle
	mov	esi,ebp
	mov	ebp,edi
      update_data_records:
	push	ebp
	mov	ecx,edi
	mov	eax,[current_section]
	sub	ecx,[eax+14h]
	add	ecx,[eax+0Ch]
	xchg	ecx,[esi]
	mov	edx,[ecx]
	xor	al,al
	call	lseek
	mov	edx,edi
	mov	ecx,[esi+4]
	add	edi,ecx
	cmp	edi,[tagged_blocks]
	ja	out_of_memory
	call	read
	mov	eax,edi
	sub	eax,[resource_data]
	and	eax,11b
	jz	resource_data_alignment_ok
	mov	ecx,4
	sub	ecx,eax
	xor	al,al
	rep	stos byte [edi]
      resource_data_alignment_ok:
	pop	ebp
	add	esi,16
	cmp	esi,ebp
	jb	update_data_records
	pop	esi
	call	close
	mov	eax,edi
	sub	eax,[resource_data]
	mov	[resource_size],eax
      resource_done:
	ret
close_pe:
	call	close_pe_section
	mov	edx,[code_start]
	mov	[edx+50h],eax
	call	make_timestamp
	mov	edx,[code_start]
	mov	[edx+8],eax
	mov	eax,[number_of_sections]
	mov	[edx+6],ax
	imul	eax,28h
	movzx	ecx,word [edx+14h]
	lea	eax,[eax+18h+ecx]
	add	eax,[stub_size]
	mov	ecx,[edx+3Ch]
	dec	ecx
	add	eax,ecx
	not	ecx
	and	eax,ecx
	cmp	eax,[edx+54h]
	je	pe_sections_ok
	or	[next_pass_needed],-1
      pe_sections_ok:
	xor	ecx,ecx
	add	edx,78h
	test	[format_flags],4
	jz	process_directories
	add	edx,10h
      process_directories:
	mov	eax,[edx+ecx*8]
	or	eax,eax
	jz	directory_ok
	cmp	dword [edx+ecx*8+4],-1
	jne	directory_ok
      section_data:
	mov	ebx,[edx+ecx*8]
	mov	eax,[ebx+0Ch]
	mov	[edx+ecx*8],eax 	; directory rva
	mov	eax,[ebx+8]
	mov	[edx+ecx*8+4],eax	; directory size
      directory_ok:
	inc	cl
	cmp	cl,10h
	jb	process_directories
	cmp	dword [edx+5*8],0
	jne	finish_pe_relocations
	mov	eax,[number_of_relocations]
	shl	eax,2
	sub	[free_additional_memory],eax
	btr	[resolver_flags],0
	jnc	pe_relocations_ok
	or	[next_pass_needed],-1
	jmp	pe_relocations_ok
      finish_pe_relocations:
	push	edi
	mov	edi,[reserved_fixups]
	call	make_fixups
	pop	edi
	add	[actual_fixups_size],eax
	cmp	eax,[reserved_fixups_size]
	je	pe_relocations_ok
	or	[next_pass_needed],-1
      pe_relocations_ok:
	mov	ebx,[code_start]
	sub	ebx,[stub_size]
	mov	ecx,edi
	sub	ecx,ebx
	mov	ebp,ecx
	shr	ecx,1
	xor	eax,eax
	cdq
      calculate_checksum:
	mov	dx,[ebx]
	add	eax,edx
	mov	dx,ax
	shr	eax,16
	add	eax,edx
	add	ebx,2
	loop	calculate_checksum
	add	eax,ebp
	mov	ebx,[code_start]
	mov	[ebx+58h],eax
	ret

format_coff:
	mov	eax,[additional_memory]
	mov	[symbols_stream],eax
	mov	ebx,eax
	add	eax,20h
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],eax
	xor	eax,eax
	mov	[ebx],al
	mov	[ebx+4],eax
	mov	[ebx+8],edi
	mov	al,4
	mov	[ebx+10h],eax
	mov	al,60h
	bt	[format_flags],0
	jnc	flat_section_flags_ok
	or	eax,0E0000000h
      flat_section_flags_ok:
	mov	dword [ebx+14h],eax
	mov	[current_section],ebx
	xor	eax,eax
	mov	[number_of_sections],eax
	mov	edx,ebx
	call	init_addressing_space
	mov	[ebx+14h],edx
	mov	byte [ebx+9],2
	mov	[code_type],32
	test	[format_flags],8
	jz	format_defined
	mov	byte [ebx+9],4
	mov	[code_type],64
	jmp	format_defined
coff_section:
	call	close_coff_section
	mov	ebx,[free_additional_memory]
	lea	eax,[ebx+20h]
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],eax
	mov	[current_section],ebx
	inc	[number_of_sections]
	xor	eax,eax
	mov	[ebx],al
	mov	[ebx+8],edi
	mov	[ebx+10h],eax
	mov	[ebx+14h],eax
	mov	edx,ebx
	call	create_addressing_space
	xchg	edx,ebx
	mov	[edx+14h],ebx
	mov	byte [edx+9],2
	test	[format_flags],8
	jz	coff_labels_type_ok
	mov	byte [edx+9],4
      coff_labels_type_ok:
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	mov	[ebx+4],esi
	mov	ecx,[esi]
	lea	esi,[esi+4+ecx+1]
	cmp	ecx,8
	ja	name_too_long
      coff_section_flags:
	cmp	byte [esi],8Ch
	je	coff_section_alignment
	cmp	byte [esi],19h
	jne	coff_section_settings_ok
	inc	esi
	lods	byte [esi]
	bt	[format_flags],0
	jc	coff_section_flag_ok
	cmp	al,7
	ja	invalid_argument
      coff_section_flag_ok:
	mov	cl,al
	mov	eax,1
	shl	eax,cl
	test	dword [ebx+14h],eax
	jnz	setting_already_specified
	or	dword [ebx+14h],eax
	jmp	coff_section_flags
      coff_section_alignment:
	bt	[format_flags],0
	jnc	invalid_argument
	inc	esi
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	push	ebx
	call	get_count_value
	pop	ebx
	mov	edx,eax
	dec	edx
	test	eax,edx
	jnz	invalid_value
	or	eax,eax
	jz	invalid_value
	cmp	eax,2000h
	ja	invalid_value
	bsf	edx,eax
	inc	edx
	shl	edx,20
	or	[ebx+14h],edx
	xchg	[ebx+10h],eax
	or	eax,eax
	jnz	setting_already_specified
	jmp	coff_section_flags
      coff_section_settings_ok:
	cmp	dword [ebx+10h],0
	jne	instruction_assembled
	mov	dword [ebx+10h],4
	bt	[format_flags],0
	jnc	instruction_assembled
	or	dword [ebx+14h],300000h
	jmp	instruction_assembled
      close_coff_section:
	mov	ebx,[current_section]
	mov	eax,edi
	mov	edx,[ebx+8]
	sub	eax,edx
	mov	[ebx+0Ch],eax
	xor	eax,eax
	xchg	[undefined_data_end],eax
	cmp	eax,edi
	jne	coff_section_ok
	cmp	edx,[undefined_data_start]
	jne	coff_section_ok
	mov	edi,edx
	or	byte [ebx+14h],80h
      coff_section_ok:
	ret
mark_coff_relocation:
	cmp	[value_type],3
	je	coff_relocation_relative
	push	ebx eax
	test	[format_flags],8
	jnz	coff_64bit_relocation
	mov	al,6
	cmp	[value_type],2
	je	coff_relocation
	cmp	[value_type],5
	jne	invalid_use_of_symbol
	inc	al
	jmp	coff_relocation
      coff_64bit_relocation:
	mov	al,1
	cmp	[value_type],4
	je	coff_relocation
	mov	al,2
	cmp	[value_type],2
	je	coff_relocation
	cmp	[value_type],5
	jne	invalid_use_of_symbol
	inc	al
	jmp	coff_relocation
      coff_relocation_relative:
	push	ebx
	bt	[format_flags],0
	jnc	relative_ok
	mov	ebx,[current_section]
	mov	ebx,[ebx+8]
	sub	ebx,edi
	sub	eax,ebx
	add	eax,4
      relative_ok:
	mov	ebx,[addressing_space]
	push	eax
	mov	al,20
	test	[format_flags],8
	jnz	relative_coff_64bit_relocation
	cmp	byte [ebx+9],2
	jne	invalid_use_of_symbol
	jmp	coff_relocation
      relative_coff_64bit_relocation:
	mov	al,4
	cmp	byte [ebx+9],4
	jne	invalid_use_of_symbol
      coff_relocation:
	mov	ebx,[free_additional_memory]
	add	ebx,0Ch
	cmp	ebx,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],ebx
	mov	byte [ebx-0Ch],al
	mov	eax,[current_section]
	mov	eax,[eax+8]
	neg	eax
	add	eax,edi
	mov	[ebx-0Ch+4],eax
	mov	eax,[symbol_identifier]
	mov	[ebx-0Ch+8],eax
	pop	eax ebx
	ret
close_coff:
	call	close_coff_section
	cmp	[next_pass_needed],0
	je	coff_closed
	mov	eax,[symbols_stream]
	mov	[free_additional_memory],eax
      coff_closed:
	ret
coff_formatter:
	sub	edi,[code_start]
	mov	[code_size],edi
	call	prepare_default_section
	mov	edi,[free_additional_memory]
	mov	ebx,edi
	mov	ecx,28h shr 2
	imul	ecx,[number_of_sections]
	add	ecx,14h shr 2
	lea	eax,[edi+ecx*4]
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	xor	eax,eax
	rep	stos dword [edi]
	mov	word [ebx],14Ch
	test	[format_flags],8
	jz	coff_magic_ok
	mov	word [ebx],8664h
      coff_magic_ok:
	mov	word [ebx+12h],104h
	bt	[format_flags],0
	jnc	coff_flags_ok
	or	byte [ebx+12h],80h
      coff_flags_ok:
	push	ebx
	call	make_timestamp
	pop	ebx
	mov	[ebx+4],eax
	mov	eax,[number_of_sections]
	mov	[ebx+2],ax
	mov	esi,[symbols_stream]
	xor	eax,eax
	xor	ecx,ecx
      enumerate_symbols:
	cmp	esi,[free_additional_memory]
	je	symbols_enumerated
	mov	dl,[esi]
	or	dl,dl
	jz	enumerate_section
	cmp	dl,0C0h
	jae	enumerate_public
	cmp	dl,80h
	jae	enumerate_extrn
	add	esi,0Ch
	jmp	enumerate_symbols
      enumerate_section:
	mov	edx,eax
	shl	edx,8
	mov	[esi],edx
	inc	eax
	inc	ecx
	mov	[esi+1Eh],cx
	add	esi,20h
	jmp	enumerate_symbols
      enumerate_public:
	mov	edx,eax
	shl	edx,8
	mov	dl,[esi]
	mov	[esi],edx
	mov	edx,[esi+8]
	add	esi,10h
	inc	eax
	cmp	byte [edx+11],0
	je	enumerate_symbols
	mov	edx,[edx+20]
	cmp	byte [edx],0C0h
	jae	enumerate_symbols
	cmp	byte [edx],80h
	jb	enumerate_symbols
	inc	eax
	jmp	enumerate_symbols
      enumerate_extrn:
	mov	edx,eax
	shl	edx,8
	mov	dl,[esi]
	mov	[esi],edx
	add	esi,0Ch
	inc	eax
	jmp	enumerate_symbols
      prepare_default_section:
	mov	ebx,[symbols_stream]
	cmp	dword [ebx+0Ch],0
	jne	default_section_ok
	cmp	[number_of_sections],0
	je	default_section_ok
	mov	edx,ebx
      find_references_to_default_section:
	cmp	ebx,[free_additional_memory]
	jne	check_reference
	add	[symbols_stream],20h
	ret
      check_reference:
	mov	al,[ebx]
	or	al,al
	jz	skip_other_section
	cmp	al,0C0h
	jae	check_public_reference
	cmp	al,80h
	jae	next_reference
	cmp	edx,[ebx+8]
	je	default_section_ok
      next_reference:
	add	ebx,0Ch
	jmp	find_references_to_default_section
      check_public_reference:
	mov	eax,[ebx+8]
	add	ebx,10h
	test	byte [eax+8],1
	jz	find_references_to_default_section
	mov	cx,[current_pass]
	cmp	cx,[eax+16]
	jne	find_references_to_default_section
	cmp	edx,[eax+20]
	je	default_section_ok
	jmp	find_references_to_default_section
      skip_other_section:
	add	ebx,20h
	jmp	find_references_to_default_section
      default_section_ok:
	inc	[number_of_sections]
	ret
      symbols_enumerated:
	mov	[ebx+0Ch],eax
	mov	ebp,edi
	sub	ebp,ebx
	push	ebp
	lea	edi,[ebx+14h]
	mov	esi,[symbols_stream]
      find_section:
	cmp	esi,[free_additional_memory]
	je	sections_finished
	mov	al,[esi]
	or	al,al
	jz	section_found
	add	esi,0Ch
	cmp	al,0C0h
	jb	find_section
	add	esi,4
	jmp	find_section
      section_found:
	push	esi edi
	mov	esi,[esi+4]
	or	esi,esi
	jz	default_section
	mov	ecx,[esi]
	add	esi,4
	rep	movs byte [edi],[esi]
	jmp	section_name_ok
      default_section:
	mov	al,'.'
	stos	byte [edi]
	mov	eax,'flat'
	stos	dword [edi]
      section_name_ok:
	pop	edi esi
	mov	eax,[esi+0Ch]
	mov	[edi+10h],eax
	mov	eax,[esi+14h]
	mov	[edi+24h],eax
	test	al,80h
	jnz	section_ptr_ok
	mov	eax,[esi+8]
	sub	eax,[code_start]
	add	eax,ebp
	mov	[edi+14h],eax
      section_ptr_ok:
	mov	ebx,[code_start]
	mov	edx,[code_size]
	add	ebx,edx
	add	edx,ebp
	xor	ecx,ecx
	add	esi,20h
      find_relocations:
	cmp	esi,[free_additional_memory]
	je	section_relocations_done
	mov	al,[esi]
	or	al,al
	jz	section_relocations_done
	cmp	al,80h
	jb	add_relocation
	cmp	al,0C0h
	jb	next_relocation
	add	esi,10h
	jmp	find_relocations
      add_relocation:
	lea	eax,[ebx+0Ah]
	cmp	eax,[tagged_blocks]
	ja	out_of_memory
	mov	eax,[esi+4]
	mov	[ebx],eax
	mov	eax,[esi+8]
	mov	eax,[eax]
	shr	eax,8
	mov	[ebx+4],eax
	movzx	ax,byte [esi]
	mov	[ebx+8],ax
	add	ebx,0Ah
	inc	ecx
      next_relocation:
	add	esi,0Ch
	jmp	find_relocations
      section_relocations_done:
	cmp	ecx,10000h
	jb	section_relocations_count_16bit
	bt	[format_flags],0
	jnc	format_limitations_exceeded
	mov	word [edi+20h],0FFFFh
	or	dword [edi+24h],1000000h
	mov	[edi+18h],edx
	push	esi edi
	push	ecx
	lea	esi,[ebx-1]
	add	ebx,0Ah
	lea	edi,[ebx-1]
	imul	ecx,0Ah
	std
	rep	movs byte [edi],[esi]
	cld
	pop	ecx
	inc	esi
	inc	ecx
	mov	[esi],ecx
	xor	eax,eax
	mov	[esi+4],eax
	mov	[esi+8],ax
	pop	edi esi
	jmp	section_relocations_ok
      section_relocations_count_16bit:
	mov	[edi+20h],cx
	jcxz	section_relocations_ok
	mov	[edi+18h],edx
      section_relocations_ok:
	sub	ebx,[code_start]
	mov	[code_size],ebx
	add	edi,28h
	jmp	find_section
      sections_finished:
	mov	edx,[free_additional_memory]
	mov	ebx,[code_size]
	add	ebp,ebx
	mov	[edx+8],ebp
	add	ebx,[code_start]
	mov	edi,ebx
	mov	ecx,[edx+0Ch]
	imul	ecx,12h shr 1
	xor	eax,eax
	shr	ecx,1
	jnc	zero_symbols_table
	stos	word [edi]
      zero_symbols_table:
	rep	stos dword [edi]
	mov	edx,edi
	stos	dword [edi]
	mov	esi,[symbols_stream]
      make_symbols_table:
	cmp	esi,[free_additional_memory]
	je	symbols_table_ok
	mov	al,[esi]
	cmp	al,0C0h
	jae	add_public_symbol
	cmp	al,80h
	jae	add_extrn_symbol
	or	al,al
	jz	add_section_symbol
	add	esi,0Ch
	jmp	make_symbols_table
      add_section_symbol:
	call	store_symbol_name
	movzx	eax,word [esi+1Eh]
	mov	[ebx+0Ch],ax
	mov	byte [ebx+10h],3
	add	esi,20h
	add	ebx,12h
	jmp	make_symbols_table
      add_extrn_symbol:
	call	store_symbol_name
	mov	byte [ebx+10h],2
	add	esi,0Ch
	add	ebx,12h
	jmp	make_symbols_table
      add_public_symbol:
	call	store_symbol_name
	mov	eax,[esi+0Ch]
	mov	[current_line],eax
	mov	eax,[esi+8]
	test	byte [eax+8],1
	jz	undefined_coff_public
	mov	cx,[current_pass]
	cmp	cx,[eax+16]
	jne	undefined_coff_public
	mov	cl,[eax+11]
	or	cl,cl
	jz	public_constant
	test	[format_flags],8
	jnz	check_64bit_public_symbol
	cmp	cl,2
	je	public_symbol_type_ok
	jmp	invalid_use_of_symbol
      undefined_coff_public:
	mov	[error_info],eax
	jmp	undefined_symbol
      check_64bit_public_symbol:
	cmp	cl,4
	jne	invalid_use_of_symbol
      public_symbol_type_ok:
	mov	ecx,[eax+20]
	cmp	byte [ecx],80h
	je	alias_symbol
	cmp	byte [ecx],0
	jne	invalid_use_of_symbol
	mov	cx,[ecx+1Eh]
	mov	[ebx+0Ch],cx
      public_symbol_section_ok:
	movzx	ecx,byte [eax+9]
	shr	cl,1
	and	cl,1
	neg	ecx
	cmp	ecx,[eax+4]
	jne	value_out_of_range
	xor	ecx,[eax]
	js	value_out_of_range
	mov	eax,[eax]
	mov	[ebx+8],eax
	mov	al,2
	cmp	byte [esi],0C0h
	je	store_symbol_class
	inc	al
	cmp	byte [esi],0C1h
	je	store_symbol_class
	mov	al,105
      store_symbol_class:
	mov	byte [ebx+10h],al
	add	esi,10h
	add	ebx,12h
	jmp	make_symbols_table
      alias_symbol:
	bt	[format_flags],0
	jnc	invalid_use_of_symbol
	mov	ecx,[eax]
	or	ecx,[eax+4]
	jnz	invalid_use_of_symbol
	mov	byte [ebx+10h],69h
	mov	byte [ebx+11h],1
	add	ebx,12h
	mov	ecx,[eax+20]
	mov	ecx,[ecx]
	shr	ecx,8
	mov	[ebx],ecx
	mov	byte [ebx+4],3
	add	esi,10h
	add	ebx,12h
	jmp	make_symbols_table
      public_constant:
	mov	word [ebx+0Ch],0FFFFh
	jmp	public_symbol_section_ok
      symbols_table_ok:
	mov	eax,edi
	sub	eax,edx
	mov	[edx],eax
	sub	edi,[code_start]
	mov	[code_size],edi
	and	[written_size],0
	mov	edx,[output_file]
	call	create
	jc	write_failed
	mov	edx,[free_additional_memory]
	pop	ecx
	add	[written_size],ecx
	call	write
	jc	write_failed
	jmp	write_output
      store_symbol_name:
	push	esi
	mov	esi,[esi+4]
	or	esi,esi
	jz	default_name
	lods	dword [esi]
	mov	ecx,eax
	cmp	ecx,8
	ja	add_string
	push	edi
	mov	edi,ebx
	rep	movs byte [edi],[esi]
	pop	edi esi
	ret
      default_name:
	mov	dword [ebx],'.fla'
	mov	dword [ebx+4],'t'
	pop	esi
	ret
      add_string:
	mov	eax,edi
	sub	eax,edx
	mov	[ebx+4],eax
	inc	ecx
	rep	movs byte [edi],[esi]
	pop	esi
	ret

format_elf:
	test	[format_flags],8
	jnz	format_elf64
	mov	edx,edi
	mov	ecx,34h shr 2
	lea	eax,[edi+ecx*4]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	rep	stos dword [edi]
	mov	dword [edx],7Fh + 'ELF' shl 8
	mov	al,1
	mov	[edx+4],al
	mov	[edx+5],al
	mov	[edx+6],al
	mov	[edx+14h],al
	mov	byte [edx+12h],3
	mov	byte [edx+28h],34h
	mov	byte [edx+2Eh],28h
	mov	[code_type],32
	cmp	word [esi],1D19h
	je	format_elf_exe
      elf_header_ok:
	mov	byte [edx+10h],1
	mov	eax,[additional_memory]
	mov	[symbols_stream],eax
	mov	ebx,eax
	add	eax,20h
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],eax
	xor	eax,eax
	mov	[current_section],ebx
	mov	[number_of_sections],eax
	mov	[ebx],al
	mov	[ebx+4],eax
	mov	[ebx+8],edi
	mov	al,111b
	mov	[ebx+14h],eax
	mov	al,4
	mov	[ebx+10h],eax
	mov	edx,ebx
	call	init_addressing_space
	xchg	edx,ebx
	mov	[edx+14h],ebx
	mov	byte [edx+9],2
	test	[format_flags],8
	jz	format_defined
	mov	byte [edx+9],4
	mov	byte [ebx+10h],8
	jmp	format_defined
      format_elf64:
	mov	edx,edi
	mov	ecx,40h shr 2
	lea	eax,[edi+ecx*4]
	cmp	eax,[tagged_blocks]
	jae	out_of_memory
	xor	eax,eax
	rep	stos dword [edi]
	mov	dword [edx],7Fh + 'ELF' shl 8
	mov	al,1
	mov	[edx+5],al
	mov	[edx+6],al
	mov	[edx+14h],al
	mov	byte [edx+4],2
	mov	byte [edx+12h],62
	mov	byte [edx+34h],40h
	mov	byte [edx+3Ah],40h
	mov	[code_type],64
	cmp	word [esi],1D19h
	jne	elf_header_ok
	jmp	format_elf64_exe
elf_section:
	bt	[format_flags],0
	jc	illegal_instruction
	call	close_coff_section
	mov	ebx,[free_additional_memory]
	lea	eax,[ebx+20h]
	cmp	eax,[structures_buffer]
	jae	out_of_memory
	mov	[free_additional_memory],eax
	mov	[current_section],ebx
	inc	word [number_of_sections]
	jz	format_limitations_exceeded
	xor	eax,eax
	mov	[ebx],al
	mov	[ebx+8],edi
	mov	[ebx+10h],eax
	mov	al,10b
	mov	[ebx+14h],eax
	mov	edx,ebx
	call	create_addressing_space
	xchg	edx,ebx
	mov	[edx+14h],ebx
	mov	byte [edx+9],2
	test	[format_flags],8
	jz	elf_labels_type_ok
	mov	byte [edx+9],4
      elf_labels_type_ok:
	lods	word [esi]
	cmp	ax,'('
	jne	invalid_argument
	mov	[ebx+4],esi
	mov	ecx,[esi]
	lea	esi,[esi+4+ecx+1]
      elf_section_flags:
	cmp	byte [esi],8Ch
	je	elf_section_alignment
	cmp	byte [esi],19h
	jne	elf_section_settings_ok
	inc	esi
	lods	byte [esi]
	sub	al,28
	xor	al,11b
	test	al,not 10b
	jnz	invalid_argument
	mov	cl,al
	mov	al,1
	shl	al,cl
	test	byte [ebx+14h],al
	jnz	setting_already_specified
	or	byte [ebx+14h],al
	jmp	elf_section_flags
      elf_section_alignment:
	inc	esi
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	push	ebx
	call	get_count_value
	pop	ebx
	mov	edx,eax
	dec	edx
	test	eax,edx
	jnz	invalid_value
	or	eax,eax
	jz	invalid_value
	xchg	[ebx+10h],eax
	or	eax,eax
	jnz	setting_already_specified
	jmp	elf_section_flags
      elf_section_settings_ok:
	cmp	dword [ebx+10h],0
	jne	instruction_assembled
	mov	dword [ebx+10h],4
	test	[format_flags],8
	jz	instruction_assembled
	mov	byte [ebx+10h],8
	jmp	instruction_assembled
mark_elf_relocation:
	push	ebx
	mov	ebx,[addressing_space]
	cmp	[value_type],3
	je	elf_relocation_relative
	cmp	[value_type],7
	je	elf_relocation_relative
	push	eax
	cmp	[value_type],5
	je	elf_gotoff_relocation
	ja	invalid_use_of_symbol
	mov	al,1			; R_386_32 / R_AMD64_64
	test	[format_flags],8
	jz	coff_relocation
	cmp	[value_type],4
	je	coff_relocation
	mov	al,11			; R_AMD64_32S
	jmp	coff_relocation
      elf_gotoff_relocation:
	test	[format_flags],8
	jnz	invalid_use_of_symbol
	mov	al,9			; R_386_GOTOFF
	jmp	coff_relocation
      elf_relocation_relative:
	cmp	byte [ebx+9],0
	je	invalid_use_of_symbol
	mov	ebx,[current_section]
	mov	ebx,[ebx+8]
	sub	ebx,edi
	sub	eax,ebx
	push	eax
	mov	al,2			; R_386_PC32 / R_AMD64_PC32
	cmp	[value_type],3
	je	coff_relocation
	mov	al,4			; R_386_PLT32 / R_AMD64_PLT32
	jmp	coff_relocation
close_elf:
	bt	[format_flags],0
	jc	close_elf_exe
	call	close_coff_section
	cmp	[next_pass_needed],0
	je	elf_closed
	mov	eax,[symbols_stream]
	mov	[free_additional_memory],eax
      elf_closed:
	ret
elf_formatter:
	push	edi
	call	prepare_default_section
	mov	esi,[symbols_stream]
	mov	edi,[free_additional_memory]
	xor	eax,eax
	mov	ecx,4
	rep	stos dword [edi]
	test	[format_flags],8
	jz	find_first_section
	mov	ecx,2
	rep	stos dword [edi]
      find_first_section:
	mov	al,[esi]
	or	al,al
	jz	first_section_found
	cmp	al,0C0h
	jb	skip_other_symbol
	add	esi,4
      skip_other_symbol:
	add	esi,0Ch
	jmp	find_first_section
      first_section_found:
	mov	ebx,esi
	mov	ebp,esi
	add	esi,20h
	xor	ecx,ecx
	xor	edx,edx
      find_next_section:
	cmp	esi,[free_additional_memory]
	je	make_section_symbol
	mov	al,[esi]
	or	al,al
	jz	make_section_symbol
	cmp	al,0C0h
	jae	skip_public
	cmp	al,80h
	jae	skip_extrn
	or	byte [ebx+14h],40h
      skip_extrn:
	add	esi,0Ch
	jmp	find_next_section
      skip_public:
	add	esi,10h
	jmp	find_next_section
      make_section_symbol:
	mov	eax,edi
	xchg	eax,[ebx+4]
	stos	dword [edi]
	test	[format_flags],8
	jnz	elf64_section_symbol
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	call	store_section_index
	jmp	section_symbol_ok
      store_section_index:
	inc	ecx
	mov	eax,ecx
	shl	eax,8
	mov	[ebx],eax
	inc	dx
	jz	format_limitations_exceeded
	mov	eax,edx
	shl	eax,16
	mov	al,3
	test	byte [ebx+14h],40h
	jz	section_index_ok
	or	ah,-1
	inc	dx
	jz	format_limitations_exceeded
      section_index_ok:
	stos	dword [edi]
	ret
      elf64_section_symbol:
	call	store_section_index
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	stos	dword [edi]
	stos	dword [edi]
      section_symbol_ok:
	mov	ebx,esi
	add	esi,20h
	cmp	ebx,[free_additional_memory]
	jne	find_next_section
	inc	dx
	jz	format_limitations_exceeded
	mov	[current_section],edx
	mov	esi,[symbols_stream]
      find_other_symbols:
	cmp	esi,[free_additional_memory]
	je	elf_symbol_table_ok
	mov	al,[esi]
	or	al,al
	jz	skip_section
	cmp	al,0C0h
	jae	make_public_symbol
	cmp	al,80h
	jae	make_extrn_symbol
	add	esi,0Ch
	jmp	find_other_symbols
      skip_section:
	add	esi,20h
	jmp	find_other_symbols
      make_public_symbol:
	mov	eax,[esi+0Ch]
	mov	[current_line],eax
	cmp	byte [esi],0C0h
	jne	invalid_argument
	mov	ebx,[esi+8]
	test	byte [ebx+8],1
	jz	undefined_public
	mov	ax,[current_pass]
	cmp	ax,[ebx+16]
	jne	undefined_public
	mov	dl,[ebx+11]
	or	dl,dl
	jz	public_absolute
	mov	eax,[ebx+20]
	cmp	byte [eax],0
	jne	invalid_use_of_symbol
	mov	eax,[eax+4]
	test	[format_flags],8
	jnz	elf64_public
	cmp	dl,2
	jne	invalid_use_of_symbol
	mov	dx,[eax+0Eh]
	jmp	section_for_public_ok
      undefined_public:
	mov	[error_info],ebx
	jmp	undefined_symbol
      elf64_public:
	cmp	dl,4
	jne	invalid_use_of_symbol
	mov	dx,[eax+6]
	jmp	section_for_public_ok
      public_absolute:
	mov	dx,0FFF1h
      section_for_public_ok:
	mov	eax,[esi+4]
	stos	dword [edi]
	test	[format_flags],8
	jnz	elf64_public_symbol
	movzx	eax,byte [ebx+9]
	shr	al,1
	and	al,1
	neg	eax
	cmp	eax,[ebx+4]
	jne	value_out_of_range
	xor	eax,[ebx]
	js	value_out_of_range
	mov	eax,[ebx]
	stos	dword [edi]
	xor	eax,eax
	mov	al,[ebx+10]
	stos	dword [edi]
	mov	eax,edx
	shl	eax,16
	mov	al,10h
	cmp	byte [ebx+10],0
	je	elf_public_function
	or	al,1
	jmp	store_elf_public_info
      elf_public_function:
	or	al,2
      store_elf_public_info:
	stos	dword [edi]
	jmp	public_symbol_ok
      elf64_public_symbol:
	mov	eax,edx
	shl	eax,16
	mov	al,10h
	cmp	byte [ebx+10],0
	je	elf64_public_function
	or	al,1
	jmp	store_elf64_public_info
      elf64_public_function:
	or	al,2
      store_elf64_public_info:
	stos	dword [edi]
	mov	al,[ebx+9]
	shl	eax,31-1
	xor	eax,[ebx+4]
	js	value_out_of_range
	mov	eax,[ebx]
	stos	dword [edi]
	mov	eax,[ebx+4]
	stos	dword [edi]
	mov	al,[ebx+10]
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
      public_symbol_ok:
	inc	ecx
	mov	eax,ecx
	shl	eax,8
	mov	al,0C0h
	mov	[esi],eax
	add	esi,10h
	jmp	find_other_symbols
      make_extrn_symbol:
	mov	eax,[esi+4]
	stos	dword [edi]
	test	[format_flags],8
	jnz	elf64_extrn_symbol
	xor	eax,eax
	stos	dword [edi]
	mov	eax,[esi+8]
	stos	dword [edi]
	mov	eax,10h
	stos	dword [edi]
	jmp	extrn_symbol_ok
      elf64_extrn_symbol:
	mov	eax,10h
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
	stos	dword [edi]
	mov	eax,[esi+8]
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
      extrn_symbol_ok:
	inc	ecx
	mov	eax,ecx
	shl	eax,8
	mov	al,80h
	mov	[esi],eax
	add	esi,0Ch
	jmp	find_other_symbols
      elf_symbol_table_ok:
	mov	edx,edi
	mov	ebx,[free_additional_memory]
	xor	al,al
	stos	byte [edi]
	add	edi,16
	mov	[edx+1],edx
	add	ebx,10h
	test	[format_flags],8
	jz	make_string_table
	add	ebx,8
      make_string_table:
	cmp	ebx,edx
	je	elf_string_table_ok
	test	[format_flags],8
	jnz	make_elf64_string
	cmp	byte [ebx+0Dh],0
	je	rel_prefix_ok
	mov	byte [ebx+0Dh],0
	mov	eax,'.rel'
	stos	dword [edi]
      rel_prefix_ok:
	mov	esi,edi
	sub	esi,edx
	xchg	esi,[ebx]
	add	ebx,10h
      make_elf_string:
	or	esi,esi
	jz	default_string
	lods	dword [esi]
	mov	ecx,eax
	rep	movs byte [edi],[esi]
	xor	al,al
	stos	byte [edi]
	jmp	make_string_table
      make_elf64_string:
	cmp	byte [ebx+5],0
	je	elf64_rel_prefix_ok
	mov	byte [ebx+5],0
	mov	eax,'.rel'
	stos	dword [edi]
	mov	al,'a'
	stos	byte [edi]
      elf64_rel_prefix_ok:
	mov	esi,edi
	sub	esi,edx
	xchg	esi,[ebx]
	add	ebx,18h
	jmp	make_elf_string
      default_string:
	mov	eax,'.fla'
	stos	dword [edi]
	mov	ax,'t'
	stos	word [edi]
	jmp	make_string_table
      elf_string_table_ok:
	mov	[edx+1+8],edi
	mov	ebx,[code_start]
	mov	eax,edi
	sub	eax,[free_additional_memory]
	test	[format_flags],8
	jnz	finish_elf64_header
	mov	[ebx+20h],eax
	mov	eax,[current_section]
	inc	ax
	jz	format_limitations_exceeded
	mov	[ebx+32h],ax
	inc	ax
	jz	format_limitations_exceeded
	mov	[ebx+30h],ax
	jmp	elf_header_finished
      finish_elf64_header:
	mov	[ebx+28h],eax
	mov	eax,[current_section]
	inc	ax
	jz	format_limitations_exceeded
	mov	[ebx+3Eh],ax
	inc	ax
	jz	format_limitations_exceeded
	mov	[ebx+3Ch],ax
      elf_header_finished:
	xor	eax,eax
	mov	ecx,10
	rep	stos dword [edi]
	test	[format_flags],8
	jz	elf_null_section_ok
	mov	ecx,6
	rep	stos dword [edi]
      elf_null_section_ok:
	mov	esi,ebp
	xor	ecx,ecx
      make_section_entry:
	mov	ebx,edi
	mov	eax,[esi+4]
	mov	eax,[eax]
	stos	dword [edi]
	mov	eax,1
	cmp	dword [esi+0Ch],0
	je	bss_section
	test	byte [esi+14h],80h
	jz	section_type_ok
      bss_section:
	mov	al,8
      section_type_ok:
	stos	dword [edi]
	mov	eax,[esi+14h]
	and	al,3Fh
	call	store_elf_machine_word
	xor	eax,eax
	call	store_elf_machine_word
	mov	eax,[esi+8]
	mov	[image_base],eax
	sub	eax,[code_start]
	call	store_elf_machine_word
	mov	eax,[esi+0Ch]
	call	store_elf_machine_word
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	mov	eax,[esi+10h]
	call	store_elf_machine_word
	xor	eax,eax
	call	store_elf_machine_word
	inc	ecx
	add	esi,20h
	xchg	edi,[esp]
	mov	ebp,edi
      convert_relocations:
	cmp	esi,[free_additional_memory]
	je	relocations_converted
	mov	al,[esi]
	or	al,al
	jz	relocations_converted
	cmp	al,80h
	jb	make_relocation_entry
	cmp	al,0C0h
	jb	relocation_entry_ok
	add	esi,10h
	jmp	convert_relocations
      make_relocation_entry:
	test	[format_flags],8
	jnz	make_elf64_relocation_entry
	mov	eax,[esi+4]
	stos	dword [edi]
	mov	eax,[esi+8]
	mov	eax,[eax]
	mov	al,[esi]
	stos	dword [edi]
	jmp	relocation_entry_ok
      make_elf64_relocation_entry:
	mov	eax,[esi+4]
	stos	dword [edi]
	xor	eax,eax
	stos	dword [edi]
	movzx	eax,byte [esi]
	stos	dword [edi]
	mov	eax,[esi+8]
	mov	eax,[eax]
	shr	eax,8
	stos	dword [edi]
	xor	eax,eax
	push	edx
	mov	edx,[esi+4]
	add	edx,[image_base]
	xchg	eax,[edx]
	stos	dword [edi]
	cmp	byte [esi],1
	je	addend_64bit
	pop	edx
	sar	eax,31
	stos	dword [edi]
	jmp	relocation_entry_ok
      addend_64bit:
	xor	eax,eax
	xchg	eax,[edx+4]
	stos	dword [edi]
	pop	edx
      relocation_entry_ok:
	add	esi,0Ch
	jmp	convert_relocations
      store_elf_machine_word:
	stos	dword [edi]
	test	[format_flags],8
	jz	elf_machine_word_ok
	and	dword [edi],0
	add	edi,4
      elf_machine_word_ok:
	ret
      relocations_converted:
	cmp	edi,ebp
	xchg	edi,[esp]
	je	rel_section_ok
	mov	eax,[ebx]
	sub	eax,4
	test	[format_flags],8
	jz	store_relocations_name_offset
	dec	eax
      store_relocations_name_offset:
	stos	dword [edi]
	test	[format_flags],8
	jnz	rela_section
	mov	eax,9
	jmp	store_relocations_type
      rela_section:
	mov	eax,4
      store_relocations_type:
	stos	dword [edi]
	xor	al,al
	call	store_elf_machine_word
	call	store_elf_machine_word
	mov	eax,ebp
	sub	eax,[code_start]
	call	store_elf_machine_word
	mov	eax,[esp]
	sub	eax,ebp
	call	store_elf_machine_word
	mov	eax,[current_section]
	stos	dword [edi]
	mov	eax,ecx
	stos	dword [edi]
	inc	ecx
	test	[format_flags],8
	jnz	finish_elf64_rela_section
	mov	eax,4
	stos	dword [edi]
	mov	al,8
	stos	dword [edi]
	jmp	rel_section_ok
      finish_elf64_rela_section:
	mov	eax,8
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
	mov	al,24
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
      rel_section_ok:
	cmp	esi,[free_additional_memory]
	jne	make_section_entry
	pop	eax
	mov	ebx,[code_start]
	sub	eax,ebx
	mov	[code_size],eax
	mov	ecx,20h
	test	[format_flags],8
	jz	adjust_elf_section_headers_offset
	mov	ecx,28h
      adjust_elf_section_headers_offset:
	add	[ebx+ecx],eax
	mov	eax,1
	stos	dword [edi]
	mov	al,2
	stos	dword [edi]
	xor	al,al
	call	store_elf_machine_word
	call	store_elf_machine_word
	mov	eax,[code_size]
	call	store_elf_machine_word
	mov	eax,[edx+1]
	sub	eax,[free_additional_memory]
	call	store_elf_machine_word
	mov	eax,[current_section]
	inc	eax
	stos	dword [edi]
	mov	eax,[number_of_sections]
	inc	eax
	stos	dword [edi]
	test	[format_flags],8
	jnz	finish_elf64_sym_section
	mov	eax,4
	stos	dword [edi]
	mov	al,10h
	stos	dword [edi]
	jmp	sym_section_ok
      finish_elf64_sym_section:
	mov	eax,8
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
	mov	al,18h
	stos	dword [edi]
	xor	al,al
	stos	dword [edi]
      sym_section_ok:
	mov	al,1+8
	stos	dword [edi]
	mov	al,3
	stos	dword [edi]
	xor	al,al
	call	store_elf_machine_word
	call	store_elf_machine_word
	mov	eax,[edx+1]
	sub	eax,[free_additional_memory]
	add	eax,[code_size]
	call	store_elf_machine_word
	mov	eax,[edx+1+8]
	sub	eax,[edx+1]
	call	store_elf_machine_word
	xor	eax,eax
	stos	dword [edi]
	stos	dword [edi]
	mov	al,1
	call	store_elf_machine_word
	xor	eax,eax
	call	store_elf_machine_word
	mov	eax,'tab'
	mov	dword [edx+1],'.sym'
	mov	[edx+1+4],eax
	mov	dword [edx+1+8],'.str'
	mov	[edx+1+8+4],eax
	mov	[resource_data],edx
	mov	[written_size],0
	mov	edx,[output_file]
	call	create
	jc	write_failed
	call	write_code
	mov	ecx,edi
	mov	edx,[free_additional_memory]
	sub	ecx,edx
	add	[written_size],ecx
	call	write
	jc	write_failed
	jmp	output_written

format_elf_exe:
	add	esi,2
	or	[format_flags],1
	cmp	byte [esi],'('
	jne	elf_exe_brand_ok
	inc	esi
	cmp	byte [esi],'.'
	je	invalid_value
	push	edx
	call	get_byte_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	pop	edx
	mov	[edx+7],al
      elf_exe_brand_ok:
	mov	[image_base],8048000h
	cmp	byte [esi],80h
	jne	elf_exe_base_ok
	lods	word [esi]
	cmp	ah,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	push	edx
	call	get_dword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	[image_base],eax
	pop	edx
      elf_exe_base_ok:
	mov	byte [edx+10h],2
	mov	byte [edx+2Ah],20h
	mov	ebx,edi
	mov	ecx,20h shr 2
	cmp	[current_pass],0
	je	init_elf_segments
	imul	ecx,[number_of_sections]
      init_elf_segments:
	xor	eax,eax
	rep	stos dword [edi]
	and	[number_of_sections],0
	mov	byte [ebx],1
	mov	word [ebx+1Ch],1000h
	mov	byte [ebx+18h],111b
	mov	eax,edi
	xor	ebp,ebp
	xor	cl,cl
	sub	eax,[code_start]
	sbb	ebp,0
	sbb	cl,0
	mov	[ebx+4],eax
	add	eax,[image_base]
	adc	ebp,0
	adc	cl,0
	mov	[ebx+8],eax
	mov	[ebx+0Ch],eax
	mov	[edx+18h],eax
	not	eax
	not	ebp
	not	cl
	add	eax,1
	adc	ebp,0
	adc	cl,0
	add	eax,edi
	adc	ebp,0
	adc	cl,0
	mov	edx,ebp
      elf_exe_addressing_setup:
	push	eax
	call	init_addressing_space
	pop	eax
	mov	[ebx],eax
	mov	[ebx+4],edx
	mov	[ebx+8],cl
	mov	[symbols_stream],edi
	jmp	format_defined
      format_elf64_exe:
	add	esi,2
	or	[format_flags],1
	cmp	byte [esi],'('
	jne	elf64_exe_brand_ok
	inc	esi
	cmp	byte [esi],'.'
	je	invalid_value
	push	edx
	call	get_byte_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	pop	edx
	mov	[edx+7],al
      elf64_exe_brand_ok:
	mov	[image_base],400000h
	and	[image_base_high],0
	cmp	byte [esi],80h
	jne	elf64_exe_base_ok
	lods	word [esi]
	cmp	ah,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	push	edx
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	[image_base],eax
	mov	[image_base_high],edx
	pop	edx
      elf64_exe_base_ok:
	mov	byte [edx+10h],2
	mov	byte [edx+36h],38h
	mov	ebx,edi
	mov	ecx,38h shr 2
	cmp	[current_pass],0
	je	init_elf64_segments
	imul	ecx,[number_of_sections]
      init_elf64_segments:
	xor	eax,eax
	rep	stos dword [edi]
	and	[number_of_sections],0
	mov	byte [ebx],1
	mov	word [ebx+30h],1000h
	mov	byte [ebx+4],111b
	push	edx
	mov	eax,edi
	sub	eax,[code_start]
	mov	[ebx+8],eax
	xor	edx,edx
	xor	cl,cl
	add	eax,[image_base]
	adc	edx,[image_base_high]
	adc	cl,0
	mov	[ebx+10h],eax
	mov	[ebx+10h+4],edx
	mov	[ebx+18h],eax
	mov	[ebx+18h+4],edx
	pop	ebx
	mov	[ebx+18h],eax
	mov	[ebx+18h+4],edx
	not	eax
	not	edx
	not	cl
	add	eax,1
	adc	edx,0
	adc	cl,0
	add	eax,edi
	adc	edx,0
	adc	cl,0
	jmp	elf_exe_addressing_setup
elf_entry:
	lods	byte [esi]
	cmp	al,'('
	jne	invalid_argument
	cmp	byte [esi],'.'
	je	invalid_value
	test	[format_flags],8
	jnz	elf64_entry
	call	get_dword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	edx,[code_start]
	mov	[edx+18h],eax
	jmp	instruction_assembled
      elf64_entry:
	call	get_qword_value
	cmp	[value_type],0
	jne	invalid_use_of_symbol
	mov	ebx,[code_start]
	mov	[ebx+18h],eax
	mov	[ebx+1Ch],edx
	jmp	instruction_assembled
elf_segment:
	bt	[format_flags],0
	jnc	illegal_instruction
	test	[format_flags],8
	jnz	elf64_segment
	call	close_elf_segment
	push	eax
	call	create_addressing_space
	mov	ebp,ebx
	mov	ebx,[number_of_sections]
	shl	ebx,5
	add	ebx,[code_start]
	add	ebx,34h
	cmp	ebx,[symbols_stream]
	jb	new_elf_segment
	mov	ebx,[symbols_stream]
	sub	ebx,20h
	push	edi
	mov	edi,ebx
	mov	ecx,20h shr 2
	xor	eax,eax
	rep	stos dword [edi]
	pop	edi
	or	[next_pass_needed],-1
      new_elf_segment:
	mov	byte [ebx],1
	mov	word [ebx+1Ch],1000h
      elf_segment_flags:
	cmp	byte [esi],1Eh
	je	elf_segment_type
	cmp	byte [esi],19h
	jne	elf_segment_flags_ok
	lods	word [esi]
	sub	ah,28
	jbe	invalid_argument
	cmp	ah,1
	je	mark_elf_segment_flag
	cmp	ah,3
	ja	invalid_argument
	xor	ah,1
	cmp	ah,2
	je	mark_elf_segment_flag
	inc	ah
      mark_elf_segment_flag:
	test	[ebx+18h],ah
	jnz	setting_already_specified
	or	[ebx+18h],ah
	jmp	elf_segment_flags
      elf_segment_type:
	cmp	byte [ebx],1
	jne	setting_already_specified
	lods	word [esi]
	mov	ecx,[number_of_sections]
	jecxz	elf_segment_type_ok
	mov	edx,[code_start]
	add	edx,34h
      scan_elf_segment_types:
	cmp	edx,[symbols_stream]
	jae	elf_segment_type_ok
	cmp	[edx],ah
	je	data_already_defined
	add	edx,20h
	loop	scan_elf_segment_types
      elf_segment_type_ok:
	mov	[ebx],ah
	mov	word [ebx+1Ch],1
	cmp	ah,50h
	jb	elf_segment_flags
	or	dword [ebx],6474E500h
	jmp	elf_segment_flags
      elf_segment_flags_ok:
	mov	eax,edi
	sub	eax,[code_start]
	mov	[ebx+4],eax
	pop	edx
	and	eax,0FFFh
	add	edx,eax
	mov	[ebx+8],edx
	mov	[ebx+0Ch],edx
	mov	eax,edx
	xor	edx,edx
	xor	cl,cl
	not	eax
	not	edx
	not	cl
	add	eax,1
	adc	edx,0
	adc	cl,0
	add	eax,edi
	adc	edx,0
	adc	cl,0
      elf_segment_addressing_setup:
	mov	[ds:ebp],eax
	mov	[ds:ebp+4],edx
	mov	[ds:ebp+8],cl
	inc	[number_of_sections]
	jmp	instruction_assembled
      close_elf_segment:
	cmp	[number_of_sections],0
	jne	finish_elf_segment
	cmp	edi,[symbols_stream]
	jne	first_elf_segment_ok
	push	edi
	mov	edi,[code_start]
	add	edi,34h
	mov	ecx,20h shr 2
	xor	eax,eax
	rep	stos dword [edi]
	pop	edi
	mov	eax,[image_base]
	ret
      first_elf_segment_ok:
	inc	[number_of_sections]
      finish_elf_segment:
	mov	ebx,[number_of_sections]
	dec	ebx
	shl	ebx,5
	add	ebx,[code_start]
	add	ebx,34h
	mov	eax,edi
	sub	eax,[code_start]
	sub	eax,[ebx+4]
	mov	edx,edi
	cmp	edi,[undefined_data_end]
	jne	elf_segment_size_ok
	mov	edi,[undefined_data_start]
      elf_segment_size_ok:
	mov	[ebx+14h],eax
	add	eax,edi
	sub	eax,edx
	mov	[ebx+10h],eax
	and	[undefined_data_end],0
	mov	eax,[ebx+8]
	cmp	byte [ebx],1
	jne	elf_segment_position_ok
	add	eax,[ebx+14h]
	add	eax,0FFFh
      elf_segment_position_ok:
	and	eax,not 0FFFh
	ret
      elf64_segment:
	call	close_elf64_segment
	push	eax edx
	call	create_addressing_space
	mov	ebp,ebx
	mov	ebx,[number_of_sections]
	imul	ebx,38h
	add	ebx,[code_start]
	add	ebx,40h
	cmp	ebx,[symbols_stream]
	jb	new_elf64_segment
	mov	ebx,[symbols_stream]
	sub	ebx,38h
	push	edi
	mov	edi,ebx
	mov	ecx,38h shr 2
	xor	eax,eax
	rep	stos dword [edi]
	pop	edi
	or	[next_pass_needed],-1
      new_elf64_segment:
	mov	byte [ebx],1
	mov	word [ebx+30h],1000h
      elf64_segment_flags:
	cmp	byte [esi],1Eh
	je	elf64_segment_type
	cmp	byte [esi],19h
	jne	elf64_segment_flags_ok
	lods	word [esi]
	sub	ah,28
	jbe	invalid_argument
	cmp	ah,1
	je	mark_elf64_segment_flag
	cmp	ah,3
	ja	invalid_argument
	xor	ah,1
	cmp	ah,2
	je	mark_elf64_segment_flag
	inc	ah
      mark_elf64_segment_flag:
	test	[ebx+4],ah
	jnz	setting_already_specified
	or	[ebx+4],ah
	jmp	elf64_segment_flags
      elf64_segment_type:
	cmp	byte [ebx],1
	jne	setting_already_specified
	lods	word [esi]
	mov	ecx,[number_of_sections]
	jecxz	elf64_segment_type_ok
	mov	edx,[code_start]
	add	edx,40h
      scan_elf64_segment_types:
	cmp	edx,[symbols_stream]
	jae	elf64_segment_type_ok
	cmp	[edx],ah
	je	data_already_defined
	add	edx,38h
	loop	scan_elf64_segment_types
      elf64_segment_type_ok:
	mov	[ebx],ah
	mov	word [ebx+30h],1
	cmp	ah,50h
	jb	elf64_segment_flags
	or	dword [ebx],6474E500h
	jmp	elf64_segment_flags
      elf64_segment_flags_ok:
	mov	ecx,edi
	sub	ecx,[code_start]
	mov	[ebx+8],ecx
	pop	edx eax
	and	ecx,0FFFh
	add	eax,ecx
	adc	edx,0
	mov	[ebx+10h],eax
	mov	[ebx+10h+4],edx
	mov	[ebx+18h],eax
	mov	[ebx+18h+4],edx
	xor	cl,cl
	not	eax
	not	edx
	not	cl
	add	eax,1
	adc	edx,0
	adc	cl,0
	add	eax,edi
	adc	edx,0
	adc	cl,0
	jmp	elf_segment_addressing_setup
      close_elf64_segment:
	cmp	[number_of_sections],0
	jne	finish_elf64_segment
	cmp	edi,[symbols_stream]
	jne	first_elf64_segment_ok
	push	edi
	mov	edi,[code_start]
	add	edi,40h
	mov	ecx,38h shr 2
	xor	eax,eax
	rep	stos dword [edi]
	pop	edi
	mov	eax,[image_base]
	mov	edx,[image_base_high]
	ret
      first_elf64_segment_ok:
	inc	[number_of_sections]
      finish_elf64_segment:
	mov	ebx,[number_of_sections]
	dec	ebx
	imul	ebx,38h
	add	ebx,[code_start]
	add	ebx,40h
	mov	eax,edi
	sub	eax,[code_start]
	sub	eax,[ebx+8]
	mov	edx,edi
	cmp	edi,[undefined_data_end]
	jne	elf64_segment_size_ok
	mov	edi,[undefined_data_start]
      elf64_segment_size_ok:
	mov	[ebx+28h],eax
	add	eax,edi
	sub	eax,edx
	mov	[ebx+20h],eax
	and	[undefined_data_end],0
	mov	eax,[ebx+10h]
	mov	edx,[ebx+10h+4]
	cmp	byte [ebx],1
	jne	elf64_segment_position_ok
	add	eax,[ebx+28h]
	adc	edx,0
	add	eax,0FFFh
	adc	edx,0
      elf64_segment_position_ok:
	and	eax,not 0FFFh
	ret
close_elf_exe:
	test	[format_flags],8
	jnz	close_elf64_exe
	call	close_elf_segment
	mov	edx,[code_start]
	mov	eax,[number_of_sections]
	mov	byte [edx+1Ch],34h
	mov	[edx+2Ch],ax
	shl	eax,5
	add	eax,edx
	add	eax,34h
	cmp	eax,[symbols_stream]
	je	elf_exe_ok
	or	[next_pass_needed],-1
      elf_exe_ok:
	ret
      close_elf64_exe:
	call	close_elf64_segment
	mov	edx,[code_start]
	mov	eax,[number_of_sections]
	mov	byte [edx+20h],40h
	mov	[edx+38h],ax
	imul	eax,38h
	add	eax,edx
	add	eax,40h
	cmp	eax,[symbols_stream]
	je	elf64_exe_ok
	or	[next_pass_needed],-1
      elf64_exe_ok:
	ret
