; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. assembler: xor eax,eax mov [stub_size],eax mov [current_pass],ax mov [resolver_flags],eax mov [number_of_sections],eax mov [actual_fixups_size],eax assembler_loop: mov eax,[labels_list] mov [tagged_blocks],eax mov eax,[additional_memory] mov [free_additional_memory],eax mov eax,[additional_memory_end] mov [structures_buffer],eax mov esi,[source_start] mov edi,[code_start] xor eax,eax mov dword [adjustment],eax mov dword [adjustment+4],eax mov [addressing_space],eax mov [error_line],eax mov [counter],eax mov [format_flags],eax mov [number_of_relocations],eax mov [undefined_data_end],eax mov [file_extension],eax mov [next_pass_needed],al mov [output_format],al mov [adjustment_sign],al mov [evex_mode],al mov [code_type],16 call init_addressing_space pass_loop: call assemble_line jnc pass_loop mov eax,[additional_memory_end] cmp eax,[structures_buffer] je pass_done sub eax,18h mov eax,[eax+4] mov [current_line],eax jmp missing_end_directive pass_done: call close_pass mov eax,[labels_list] check_symbols: cmp eax,[memory_end] jae symbols_checked test byte [eax+8],8 jz symbol_defined_ok mov cx,[current_pass] cmp cx,[eax+18] jne symbol_defined_ok test byte [eax+8],1 jz symbol_defined_ok sub cx,[eax+16] cmp cx,1 jne symbol_defined_ok and byte [eax+8],not 1 or [next_pass_needed],-1 symbol_defined_ok: test byte [eax+8],10h jz use_prediction_ok mov cx,[current_pass] and byte [eax+8],not 10h test byte [eax+8],20h jnz check_use_prediction cmp cx,[eax+18] jne use_prediction_ok test byte [eax+8],8 jz use_prediction_ok jmp use_misprediction check_use_prediction: test byte [eax+8],8 jz use_misprediction cmp cx,[eax+18] je use_prediction_ok use_misprediction: or [next_pass_needed],-1 use_prediction_ok: test byte [eax+8],40h jz check_next_symbol and byte [eax+8],not 40h test byte [eax+8],4 jnz define_misprediction mov cx,[current_pass] test byte [eax+8],80h jnz check_define_prediction cmp cx,[eax+16] jne check_next_symbol test byte [eax+8],1 jz check_next_symbol jmp define_misprediction check_define_prediction: test byte [eax+8],1 jz define_misprediction cmp cx,[eax+16] je check_next_symbol define_misprediction: or [next_pass_needed],-1 check_next_symbol: add eax,LABEL_STRUCTURE_SIZE jmp check_symbols symbols_checked: cmp [next_pass_needed],0 jne next_pass mov eax,[error_line] or eax,eax jz assemble_ok mov [current_line],eax cmp [error],undefined_symbol jne error_confirmed mov eax,[error_info] or eax,eax jz error_confirmed test byte [eax+8],1 jnz next_pass error_confirmed: call error_handler error_handler: mov eax,[error] sub eax,error_handler add [esp],eax ret next_pass: inc [current_pass] mov ax,[current_pass] cmp ax,[passes_limit] je code_cannot_be_generated jmp assembler_loop assemble_ok: ret create_addressing_space: mov ebx,[addressing_space] test ebx,ebx jz init_addressing_space test byte [ebx+0Ah],1 jnz illegal_instruction mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax init_addressing_space: mov ebx,[tagged_blocks] mov dword [ebx-4],10h mov dword [ebx-8],24h sub ebx,8+24h cmp ebx,edi jbe out_of_memory mov [tagged_blocks],ebx mov [addressing_space],ebx xor eax,eax mov [ebx],edi mov [ebx+4],eax mov [ebx+8],eax mov [ebx+10h],eax mov [ebx+14h],eax mov [ebx+18h],edi mov [ebx+1Ch],eax mov [ebx+20h],eax ret assemble_line: mov eax,[tagged_blocks] sub eax,100h cmp edi,eax ja out_of_memory lods byte [esi] cmp al,1 je assemble_instruction jb source_end cmp al,3 jb define_label je define_constant cmp al,4 je label_addressing_space cmp al,0Fh je new_line cmp al,13h je code_type_setting cmp al,10h jne illegal_instruction lods byte [esi] jmp segment_prefix code_type_setting: lods byte [esi] mov [code_type],al jmp instruction_assembled new_line: lods dword [esi] mov [current_line],eax and [prefix_flags],0 cmp [symbols_file],0 je continue_line cmp [next_pass_needed],0 jne continue_line mov ebx,[tagged_blocks] mov dword [ebx-4],1 mov dword [ebx-8],14h sub ebx,8+14h cmp ebx,edi jbe out_of_memory mov [tagged_blocks],ebx mov [ebx],eax mov [ebx+4],edi mov eax,[addressing_space] mov [ebx+8],eax mov al,[code_type] mov [ebx+10h],al continue_line: cmp byte [esi],0Fh je line_assembled jmp assemble_line define_label: lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol mov ebx,eax lods byte [esi] mov [label_size],al call make_label jmp continue_line make_label: mov eax,edi xor edx,edx xor cl,cl mov ebp,[addressing_space] sub eax,[ds:ebp] sbb edx,[ds:ebp+4] sbb cl,[ds:ebp+8] jp label_value_ok call recoverable_overflow label_value_ok: mov [address_sign],cl test byte [ds:ebp+0Ah],1 jnz make_virtual_label or byte [ebx+9],1 xchg eax,[ebx] xchg edx,[ebx+4] mov ch,[ebx+9] shr ch,1 and ch,1 neg ch sub eax,[ebx] sbb edx,[ebx+4] sbb ch,cl mov dword [adjustment],eax mov dword [adjustment+4],edx mov [adjustment_sign],ch or al,ch or eax,edx setnz ah jmp finish_label make_virtual_label: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al finish_label: mov ebp,[addressing_space] mov ch,[ds:ebp+9] mov cl,[label_size] mov edx,[ds:ebp+14h] mov ebp,[ds:ebp+10h] finish_label_symbol: mov al,[address_sign] xor al,[ebx+9] and al,10b or ah,al xor [ebx+9],al cmp cl,[ebx+10] mov [ebx+10],cl setne al or ah,al cmp ch,[ebx+11] mov [ebx+11],ch setne al or ah,al cmp ebp,[ebx+12] mov [ebx+12],ebp setne al or ah,al or ch,ch jz label_symbol_ok cmp edx,[ebx+20] mov [ebx+20],edx setne al or ah,al label_symbol_ok: mov cx,[current_pass] xchg [ebx+16],cx mov edx,[current_line] mov [ebx+28],edx and byte [ebx+8],not 2 test byte [ebx+8],1 jz new_label cmp cx,[ebx+16] je symbol_already_defined btr dword [ebx+8],10 jc requalified_label inc cx sub cx,[ebx+16] setnz al or ah,al jz label_made test byte [ebx+8],8 jz label_made mov cx,[current_pass] cmp cx,[ebx+18] jne label_made requalified_label: or [next_pass_needed],-1 label_made: ret new_label: or byte [ebx+8],1 ret define_constant: lods dword [esi] inc esi cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol push eax or [operand_flags],1 call get_value pop ebx xor cl,cl mov ch,[value_type] cmp ch,3 je invalid_use_of_symbol make_constant: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al mov al,[value_sign] xor al,[ebx+9] and al,10b or ah,al xor [ebx+9],al cmp cl,[ebx+10] mov [ebx+10],cl setne al or ah,al cmp ch,[ebx+11] mov [ebx+11],ch setne al or ah,al xor edx,edx cmp edx,[ebx+12] mov [ebx+12],edx setne al or ah,al or ch,ch jz constant_symbol_ok mov edx,[symbol_identifier] cmp edx,[ebx+20] mov [ebx+20],edx setne al or ah,al constant_symbol_ok: mov cx,[current_pass] xchg [ebx+16],cx mov edx,[current_line] mov [ebx+28],edx test byte [ebx+8],1 jz new_constant cmp cx,[ebx+16] jne redeclare_constant test byte [ebx+8],2 jz symbol_already_defined or byte [ebx+8],4 and byte [ebx+9],not 4 jmp instruction_assembled redeclare_constant: btr dword [ebx+8],10 jc requalified_constant inc cx sub cx,[ebx+16] setnz al or ah,al jz instruction_assembled test byte [ebx+8],4 jnz instruction_assembled test byte [ebx+8],8 jz instruction_assembled mov cx,[current_pass] cmp cx,[ebx+18] jne instruction_assembled requalified_constant: or [next_pass_needed],-1 jmp instruction_assembled new_constant: or byte [ebx+8],1+2 jmp instruction_assembled label_addressing_space: lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol mov cx,[current_pass] test byte [eax+8],1 jz make_addressing_space_label cmp cx,[eax+16] je symbol_already_defined test byte [eax+9],4 jnz make_addressing_space_label or [next_pass_needed],-1 make_addressing_space_label: mov dx,[eax+8] and dx,not (2 or 100h) or dx,1 or 4 or 400h mov [eax+8],dx mov [eax+16],cx mov edx,[current_line] mov [eax+28],edx mov ebx,[addressing_space] mov [eax],ebx or byte [ebx+0Ah],2 jmp continue_line assemble_instruction: ; mov [operand_size],0 ; mov [operand_flags],0 ; mov [operand_prefix],0 ; mov [rex_prefix],0 and dword [operand_size],0 ; mov [opcode_prefix],0 ; mov [vex_required],0 ; mov [vex_register],0 ; mov [immediate_size],0 and dword [opcode_prefix],0 call instruction_handler instruction_handler: movzx ebx,word [esi] mov al,[esi+2] add esi,3 add [esp],ebx ret instruction_assembled: test [prefix_flags],not 1 jnz illegal_instruction mov al,[esi] cmp al,0Fh je line_assembled or al,al jnz extra_characters_on_line line_assembled: clc ret source_end: dec esi stc ret org_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_qword_value mov cl,[value_type] test cl,1 jnz invalid_use_of_symbol push eax mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax test byte [ebx+0Ah],1 jnz in_virtual call init_addressing_space jmp org_space_ok in_virtual: call close_virtual_addressing_space call init_addressing_space or byte [ebx+0Ah],1 org_space_ok: pop eax mov [ebx+9],cl mov cl,[value_sign] sub [ebx],eax sbb [ebx+4],edx sbb byte [ebx+8],cl jp org_value_ok call recoverable_overflow org_value_ok: mov edx,[symbol_identifier] mov [ebx+14h],edx cmp [output_format],1 ja instruction_assembled cmp edi,[code_start] jne instruction_assembled cmp eax,100h jne instruction_assembled bts [format_flags],0 jmp instruction_assembled label_directive: 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 [label_size],0 lods byte [esi] cmp al,':' je get_label_size dec esi cmp al,11h jne label_size_ok get_label_size: lods word [esi] cmp al,11h jne invalid_argument mov [label_size],ah label_size_ok: cmp byte [esi],80h je get_free_label_value call make_label jmp instruction_assembled get_free_label_value: inc esi lods byte [esi] cmp al,'(' jne invalid_argument push ebx ecx or byte [ebx+8],4 cmp byte [esi],'.' je invalid_value call get_address_value or bh,bh setnz ch xchg ch,cl mov bp,cx shl ebp,16 xchg bl,bh mov bp,bx pop ecx ebx and byte [ebx+8],not 4 mov ch,[value_type] test ch,1 jnz invalid_use_of_symbol make_free_label: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al mov edx,[address_symbol] mov cl,[label_size] call finish_label_symbol jmp instruction_assembled load_directive: 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 push eax mov al,1 cmp byte [esi],11h jne load_size_ok lods byte [esi] lods byte [esi] load_size_ok: cmp al,8 ja invalid_value mov [operand_size],al and dword [value],0 and dword [value+4],0 lods byte [esi] cmp al,82h jne invalid_argument call get_data_point jc value_loaded push esi edi mov esi,ebx mov edi,value rep movs byte [edi],[esi] pop edi esi value_loaded: mov [value_sign],0 mov eax,dword [value] mov edx,dword [value+4] pop ebx xor cx,cx jmp make_constant get_data_point: lods byte [esi] cmp al,':' je get_data_offset cmp al,'(' jne invalid_argument mov ebx,[addressing_space] mov ecx,edi sub ecx,[ebx+18h] mov [ebx+1Ch],ecx cmp byte [esi],11h jne get_data_address cmp word [esi+1+4],'):' jne get_data_address inc esi lods dword [esi] add esi,2 cmp byte [esi],'(' jne invalid_argument inc esi cmp eax,0Fh jbe reserved_word_used_as_symbol mov edx,undefined_symbol test byte [eax+8],1 jz addressing_space_unavailable mov edx,symbol_out_of_scope mov cx,[eax+16] cmp cx,[current_pass] jne addressing_space_unavailable test byte [eax+9],4 jz invalid_use_of_symbol mov ebx,eax mov ax,[current_pass] mov [ebx+18],ax or byte [ebx+8],8 call store_label_reference get_addressing_space: mov ebx,[ebx] get_data_address: push ebx cmp byte [esi],'.' je invalid_value or [operand_flags],1 call get_address_value pop ebp call calculate_relative_offset cmp [next_pass_needed],0 jne data_address_type_ok cmp [value_type],0 jne invalid_use_of_symbol data_address_type_ok: mov ebx,edi xor ecx,ecx add ebx,eax adc edx,ecx mov eax,ebx sub eax,[ds:ebp+18h] sbb edx,ecx jnz bad_data_address mov cl,[operand_size] add eax,ecx cmp eax,[ds:ebp+1Ch] ja bad_data_address clc ret addressing_space_unavailable: cmp [error_line],0 jne get_data_address push [current_line] pop [error_line] mov [error],edx mov [error_info],eax jmp get_data_address bad_data_address: call recoverable_overflow stc ret get_data_offset: cmp [output_format],2 jae invalid_operand lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_dword_value cmp [value_type],0 je data_offset_ok call recoverable_invalid_address data_offset_ok: add eax,[code_start] jc bad_data_address mov ebx,eax movzx ecx,[operand_size] add eax,ecx jc bad_data_address mov edx,[addressing_space] test byte [edx+0Ah],1 jnz data_offset_from_virtual cmp eax,edi ja bad_data_address clc ret data_offset_from_virtual: cmp eax,[undefined_data_end] ja bad_data_address clc ret store_directive: cmp byte [esi],11h je sized_store lods byte [esi] cmp al,'(' jne invalid_argument call get_byte_value xor edx,edx movzx eax,al mov [operand_size],1 jmp store_value_ok sized_store: or [operand_flags],1 call get_value store_value_ok: cmp [value_type],0 jne invalid_use_of_symbol mov dword [value],eax mov dword [value+4],edx lods byte [esi] cmp al,80h jne invalid_argument call get_data_point jc instruction_assembled push esi edi mov esi,value mov edi,ebx rep movs byte [edi],[esi] mov eax,edi pop edi esi cmp ebx,[undefined_data_end] jae instruction_assembled cmp eax,[undefined_data_start] jbe instruction_assembled mov [undefined_data_start],eax jmp instruction_assembled display_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],0 jne display_byte inc esi lods dword [esi] mov ecx,eax push edi mov edi,[tagged_blocks] sub edi,8 sub edi,eax cmp edi,[esp] jbe out_of_memory mov [tagged_blocks],edi rep movs byte [edi],[esi] stos dword [edi] xor eax,eax stos dword [edi] pop edi inc esi jmp display_next display_byte: call get_byte_value push edi mov edi,[tagged_blocks] sub edi,8+1 mov [tagged_blocks],edi stos byte [edi] mov eax,1 stos dword [edi] dec eax stos dword [edi] pop edi display_next: cmp edi,[tagged_blocks] ja out_of_memory lods byte [esi] cmp al,',' je display_directive dec esi jmp instruction_assembled show_display_buffer: mov eax,[tagged_blocks] or eax,eax jz display_done mov esi,[labels_list] cmp esi,eax je display_done display_messages: sub esi,8 mov eax,[esi+4] mov ecx,[esi] sub esi,ecx cmp eax,10h je write_addressing_space test eax,eax jnz skip_block push esi call display_block pop esi skip_block: cmp esi,[tagged_blocks] jne display_messages display_done: ret write_addressing_space: mov ecx,[esi+20h] jecxz skip_block push esi mov edi,[free_additional_memory] mov esi,[output_file] test esi,esi jz addressing_space_written xor ebx,ebx copy_output_path: lodsb cmp edi,[structures_buffer] jae out_of_memory stosb test al,al jz output_path_copied cmp al,'/' je new_path_segment cmp al,'\' je new_path_segment cmp al,'.' jne copy_output_path mov ebx,edi jmp copy_output_path new_path_segment: xor ebx,ebx jmp copy_output_path output_path_copied: test ebx,ebx jnz append_extension mov byte [edi-1],'.' mov ebx,edi append_extension: mov edi,ebx add ebx,ecx inc ebx cmp ebx,[structures_buffer] jae out_of_memory mov esi,[esp] mov esi,[esi+18h] sub esi,ecx rep movs byte [edi],[esi] xor al,al stos byte [edi] mov edx,[free_additional_memory] call create jc write_failed mov esi,[esp] mov edx,[esi+18h] mov ecx,[esi+1Ch] call write jc write_failed call close addressing_space_written: pop esi jmp skip_block times_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value cmp eax,0 je zero_times cmp byte [esi],':' jne times_argument_ok inc esi times_argument_ok: push [counter] push [counter_limit] mov [counter_limit],eax mov [counter],1 times_loop: mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push esi or [prefix_flags],1 call continue_line mov eax,[counter_limit] cmp [counter],eax je times_done inc [counter] pop esi jmp times_loop times_done: pop eax pop [counter_limit] pop [counter] jmp instruction_assembled zero_times: call skip_symbol jnc zero_times jmp instruction_assembled virtual_directive: lods byte [esi] cmp al,'(' je continue_virtual_area cmp al,80h jne virtual_at_current lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_address_value mov ebp,[address_symbol] or bh,bh setnz ch jmp set_virtual virtual_at_current: dec esi virtual_fallback: mov ebp,[addressing_space] mov al,[ds:ebp+9] mov [value_type],al mov eax,edi xor edx,edx xor cl,cl sub eax,[ds:ebp] sbb edx,[ds:ebp+4] sbb cl,[ds:ebp+8] mov [address_sign],cl mov bx,[ds:ebp+10h] mov cx,[ds:ebp+10h+2] xchg bh,bl xchg ch,cl mov ebp,[ds:ebp+14h] set_virtual: xchg bl,bh xchg cl,ch shl ecx,16 mov cx,bx push ecx eax mov ebx,[addressing_space] test byte [ebx+0Ah],1 jnz non_virtual_end_ok mov eax,edi xchg eax,[undefined_data_end] cmp eax,edi je non_virtual_end_ok mov [undefined_data_start],edi non_virtual_end_ok: call allocate_virtual_structure_data call init_addressing_space or byte [ebx+0Ah],1 cmp byte [esi],86h jne addressing_space_extension_ok cmp word [esi+1],'(' jne invalid_argument mov ecx,[esi+3] add esi,3+4 add [ebx+18h],ecx mov [ebx+20h],ecx or byte [ebx+0Ah],2 push ebx mov ebx,characters get_extension: lods byte [esi] stos byte [edi] xlat byte [ebx] test al,al jz invalid_argument loop get_extension inc esi pop ebx addressing_space_extension_ok: pop eax mov cl,[address_sign] not eax not edx not cl add eax,1 adc edx,0 adc cl,0 add eax,edi adc edx,0 adc cl,0 mov [ebx],eax mov [ebx+4],edx mov [ebx+8],cl pop dword [ebx+10h] mov [ebx+14h],ebp mov al,[value_type] test al,1 jnz invalid_use_of_symbol mov [ebx+9],al jmp instruction_assembled allocate_structure_data: mov ebx,[structures_buffer] sub ebx,18h cmp ebx,[free_additional_memory] jb out_of_memory mov [structures_buffer],ebx ret find_structure_data: mov ebx,[structures_buffer] scan_structures: cmp ebx,[additional_memory_end] je no_such_structure cmp ax,[ebx] je structure_data_found add ebx,18h jmp scan_structures structure_data_found: ret no_such_structure: stc ret allocate_virtual_structure_data: call allocate_structure_data mov word [ebx],virtual_directive-instruction_handler mov ecx,[addressing_space] mov [ebx+12],ecx mov [ebx+8],edi mov ecx,[current_line] mov [ebx+4],ecx mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax ret continue_virtual_area: cmp byte [esi],11h jne invalid_argument cmp byte [esi+1+4],')' jne invalid_argument inc esi lods dword [esi] inc esi cmp eax,0Fh jbe reserved_word_used_as_symbol mov edx,undefined_symbol test byte [eax+8],1 jz virtual_area_unavailable mov edx,symbol_out_of_scope mov cx,[eax+16] cmp cx,[current_pass] jne virtual_area_unavailable mov edx,invalid_use_of_symbol test byte [eax+9],4 jz virtual_area_unavailable mov ebx,eax mov ax,[current_pass] mov [ebx+18],ax or byte [ebx+8],8 call store_label_reference mov ebx,[ebx] test byte [ebx+0Ah],4 jz virtual_area_unavailable and byte [ebx+0Ah],not 4 mov edx,ebx call allocate_virtual_structure_data mov [addressing_space],edx push esi mov esi,[edx+18h] mov ecx,[edx+1Ch] mov eax,[edx+20h] sub esi,eax add ecx,eax lea eax,[edi+ecx] cmp eax,[tagged_blocks] jae out_of_memory mov eax,esi sub eax,edi sub [edx+18h],eax sub [edx],eax sbb dword [edx+4],0 sbb byte [edx+8],0 mov al,cl shr ecx,2 rep movs dword [edi],[esi] mov cl,al and cl,11b rep movs byte [edi],[esi] pop esi jmp instruction_assembled virtual_area_unavailable: cmp [error_line],0 jne virtual_fallback push [current_line] pop [error_line] mov [error],edx mov [error_info],eax jmp virtual_fallback end_virtual: call find_structure_data jc unexpected_instruction push ebx call close_virtual_addressing_space pop ebx mov eax,[ebx+12] mov [addressing_space],eax mov edi,[ebx+8] remove_structure_data: push esi edi mov ecx,ebx sub ecx,[structures_buffer] shr ecx,2 lea esi,[ebx-4] lea edi,[esi+18h] std rep movs dword [edi],[esi] cld add [structures_buffer],18h pop edi esi ret close_virtual_addressing_space: mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax add eax,[ebx+20h] test byte [ebx+0Ah],2 jz addressing_space_closed or byte [ebx+0Ah],4 push esi edi ecx edx mov ecx,eax mov eax,[tagged_blocks] mov dword [eax-4],11h mov dword [eax-8],ecx sub eax,8 sub eax,ecx mov [tagged_blocks],eax lea edi,[eax+ecx-1] add eax,[ebx+20h] xchg eax,[ebx+18h] sub eax,[ebx+20h] lea esi,[eax+ecx-1] mov eax,edi sub eax,esi std shr ecx,1 jnc virtual_byte_ok movs byte [edi],[esi] virtual_byte_ok: dec esi dec edi shr ecx,1 jnc virtual_word_ok movs word [edi],[esi] virtual_word_ok: sub esi,2 sub edi,2 rep movs dword [edi],[esi] cld xor edx,edx add [ebx],eax adc dword [ebx+4],edx adc byte [ebx+8],dl pop edx ecx edi esi addressing_space_closed: ret repeat_directive: test [prefix_flags],1 jnz unexpected_instruction lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value cmp eax,0 je zero_repeat call allocate_structure_data mov word [ebx],repeat_directive-instruction_handler xchg eax,[counter_limit] mov [ebx+10h],eax mov eax,1 xchg eax,[counter] mov [ebx+14h],eax mov [ebx+8],esi mov eax,[current_line] mov [ebx+4],eax jmp instruction_assembled end_repeat: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction mov eax,[counter_limit] inc [counter] cmp [counter],eax jbe continue_repeating stop_repeat: mov eax,[ebx+10h] mov [counter_limit],eax mov eax,[ebx+14h] mov [counter],eax call remove_structure_data jmp instruction_assembled continue_repeating: mov esi,[ebx+8] jmp instruction_assembled zero_repeat: mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line call find_end_repeat jmp instruction_assembled find_end_repeat: call find_structure_end cmp ax,repeat_directive-instruction_handler jne unexpected_instruction ret while_directive: test [prefix_flags],1 jnz unexpected_instruction call allocate_structure_data mov word [ebx],while_directive-instruction_handler mov eax,1 xchg eax,[counter] mov [ebx+10h],eax mov [ebx+8],esi mov eax,[current_line] mov [ebx+4],eax do_while: push ebx call calculate_logical_expression or al,al jnz while_true mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line stop_while: call find_end_while pop ebx mov eax,[ebx+10h] mov [counter],eax call remove_structure_data jmp instruction_assembled while_true: pop ebx jmp instruction_assembled end_while: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction mov eax,[ebx+4] mov [current_line],eax inc [counter] jz too_many_repeats mov esi,[ebx+8] jmp do_while find_end_while: call find_structure_end cmp ax,while_directive-instruction_handler jne unexpected_instruction ret if_directive: test [prefix_flags],1 jnz unexpected_instruction call calculate_logical_expression mov dl,al mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line or dl,dl jnz if_true call find_else jc instruction_assembled mov al,[esi] cmp al,1 jne else_true cmp word [esi+1],if_directive-instruction_handler jne else_true add esi,4 jmp if_directive if_true: xor al,al make_if_structure: call allocate_structure_data mov word [ebx],if_directive-instruction_handler mov byte [ebx+2],al mov eax,[current_line] mov [ebx+4],eax jmp instruction_assembled else_true: or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line or al,-1 jmp make_if_structure else_directive: test [prefix_flags],1 jnz unexpected_instruction mov ax,if_directive-instruction_handler call find_structure_data jc unexpected_instruction cmp byte [ebx+2],0 jne unexpected_instruction found_else: mov al,[esi] cmp al,1 jne skip_else cmp word [esi+1],if_directive-instruction_handler jne skip_else add esi,4 call find_else jnc found_else call remove_structure_data jmp instruction_assembled skip_else: or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line call find_end_if call remove_structure_data jmp instruction_assembled end_if: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction call remove_structure_data jmp instruction_assembled find_else: call find_structure_end cmp ax,else_directive-instruction_handler je else_found cmp ax,if_directive-instruction_handler jne unexpected_instruction stc ret else_found: clc ret find_end_if: call find_structure_end cmp ax,if_directive-instruction_handler jne unexpected_instruction ret find_structure_end: push [error_line] mov eax,[current_line] mov [error_line],eax find_end_directive: call skip_symbol jnc find_end_directive lods byte [esi] cmp al,0Fh jne no_end_directive lods dword [esi] mov [current_line],eax skip_labels: cmp byte [esi],2 jne labels_ok add esi,6 jmp skip_labels labels_ok: cmp byte [esi],1 jne find_end_directive mov ax,[esi+1] cmp ax,prefix_instruction-instruction_handler je find_end_directive add esi,4 cmp ax,repeat_directive-instruction_handler je skip_repeat cmp ax,while_directive-instruction_handler je skip_while cmp ax,if_directive-instruction_handler je skip_if cmp ax,else_directive-instruction_handler je structure_end cmp ax,end_directive-instruction_handler jne find_end_directive cmp byte [esi],1 jne find_end_directive mov ax,[esi+1] add esi,4 cmp ax,repeat_directive-instruction_handler je structure_end cmp ax,while_directive-instruction_handler je structure_end cmp ax,if_directive-instruction_handler jne find_end_directive structure_end: pop [error_line] ret no_end_directive: mov eax,[error_line] mov [current_line],eax jmp missing_end_directive skip_repeat: call find_end_repeat jmp find_end_directive skip_while: call find_end_while jmp find_end_directive skip_if: call skip_if_block jmp find_end_directive skip_if_block: call find_else jc if_block_skipped cmp byte [esi],1 jne skip_after_else cmp word [esi+1],if_directive-instruction_handler jne skip_after_else add esi,4 jmp skip_if_block skip_after_else: call find_end_if if_block_skipped: ret end_directive: lods byte [esi] cmp al,1 jne invalid_argument lods word [esi] inc esi cmp ax,virtual_directive-instruction_handler je end_virtual cmp ax,repeat_directive-instruction_handler je end_repeat cmp ax,while_directive-instruction_handler je end_while cmp ax,if_directive-instruction_handler je end_if cmp ax,data_directive-instruction_handler je end_data jmp invalid_argument break_directive: mov ebx,[structures_buffer] mov al,[esi] or al,al jz find_breakable_structure cmp al,0Fh jne extra_characters_on_line find_breakable_structure: cmp ebx,[additional_memory_end] je unexpected_instruction mov ax,[ebx] cmp ax,repeat_directive-instruction_handler je break_repeat cmp ax,while_directive-instruction_handler je break_while cmp ax,if_directive-instruction_handler je break_if add ebx,18h jmp find_breakable_structure break_if: push [current_line] mov eax,[ebx+4] mov [current_line],eax call remove_structure_data call skip_if_block pop [current_line] mov ebx,[structures_buffer] jmp find_breakable_structure break_repeat: push ebx call find_end_repeat pop ebx jmp stop_repeat break_while: push ebx jmp stop_while define_data: cmp edi,[tagged_blocks] jae out_of_memory cmp byte [esi],'(' jne simple_data_value mov ebx,esi inc esi call skip_expression xchg esi,ebx cmp byte [ebx],81h jne simple_data_value inc esi call get_count_value inc esi or eax,eax jz duplicate_zero_times cmp byte [esi],91h jne duplicate_single_data_value inc esi duplicate_data: push eax esi duplicated_values: cmp edi,[tagged_blocks] jae out_of_memory clc call near dword [esp+8] lods byte [esi] cmp al,',' je duplicated_values cmp al,92h jne invalid_argument pop ebx eax dec eax jz data_defined mov esi,ebx jmp duplicate_data duplicate_single_data_value: cmp edi,[tagged_blocks] jae out_of_memory push eax esi clc call near dword [esp+8] pop ebx eax dec eax jz data_defined mov esi,ebx jmp duplicate_single_data_value duplicate_zero_times: cmp byte [esi],91h jne skip_single_data_value inc esi skip_data_value: call skip_symbol jc invalid_argument cmp byte [esi],92h jne skip_data_value inc esi jmp data_defined skip_single_data_value: call skip_symbol jmp data_defined simple_data_value: cmp edi,[tagged_blocks] jae out_of_memory clc call near dword [esp] data_defined: lods byte [esi] cmp al,',' je define_data dec esi stc ret data_bytes: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_byte cmp al,'?' jne invalid_argument mov eax,edi mov byte [edi],0 inc edi jmp undefined_data get_byte: cmp byte [esi],0 je get_string call get_byte_value stos byte [edi] ret get_string: inc esi lods dword [esi] mov ecx,eax lea eax,[edi+ecx] cmp eax,[tagged_blocks] ja out_of_memory rep movs byte [edi],[esi] inc esi ret undefined_data: mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jz mark_undefined_data ret mark_undefined_data: cmp eax,[undefined_data_end] je undefined_data_ok mov [undefined_data_start],eax undefined_data_ok: mov [undefined_data_end],edi ret data_unicode: or [base_code],-1 jmp define_words data_words: mov [base_code],0 define_words: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_word cmp al,'?' jne invalid_argument mov eax,edi and word [edi],0 scas word [edi] jmp undefined_data ret get_word: cmp [base_code],0 je word_data_value cmp byte [esi],0 je word_string word_data_value: call get_word_value call mark_relocation stos word [edi] ret word_string: inc esi lods dword [esi] mov ecx,eax jecxz word_string_ok lea eax,[edi+ecx*2] cmp eax,[tagged_blocks] ja out_of_memory xor ah,ah copy_word_string: lods byte [esi] stos word [edi] loop copy_word_string word_string_ok: inc esi ret data_dwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_dword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] jmp undefined_data get_dword: push esi call get_dword_value pop ebx cmp byte [esi],':' je complex_dword call mark_relocation stos dword [edi] ret complex_dword: mov esi,ebx cmp byte [esi],'.' je invalid_value call get_word_value push eax inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_word_value call mark_relocation stos word [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_pwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_pword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and word [edi],0 scas word [edi] jmp undefined_data get_pword: push esi call get_pword_value pop ebx cmp byte [esi],':' je complex_pword call mark_relocation stos dword [edi] mov ax,dx stos word [edi] ret complex_pword: mov esi,ebx cmp byte [esi],'.' je invalid_value call get_word_value push eax inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_dword_value call mark_relocation stos dword [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_qwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_qword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and dword [edi],0 scas dword [edi] jmp undefined_data get_qword: call get_qword_value call mark_relocation stos dword [edi] mov eax,edx stos dword [edi] ret data_twords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_tword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and dword [edi],0 scas dword [edi] and word [edi],0 scas word [edi] jmp undefined_data get_tword: cmp byte [esi],'.' jne complex_tword inc esi cmp word [esi+8],8000h je fp_zero_tword mov eax,[esi] stos dword [edi] mov eax,[esi+4] stos dword [edi] mov ax,[esi+8] add ax,3FFFh jo value_out_of_range cmp ax,7FFFh jge value_out_of_range cmp ax,0 jg tword_exp_ok mov cx,ax neg cx inc cx cmp cx,64 jae value_out_of_range cmp cx,32 ja large_shift mov eax,[esi] mov edx,[esi+4] mov ebx,edx shr edx,cl shrd eax,ebx,cl jmp tword_mantissa_shift_done large_shift: sub cx,32 xor edx,edx mov eax,[esi+4] shr eax,cl tword_mantissa_shift_done: jnc store_shifted_mantissa add eax,1 adc edx,0 store_shifted_mantissa: mov [edi-8],eax mov [edi-4],edx xor ax,ax test edx,1 shl 31 jz tword_exp_ok inc ax tword_exp_ok: mov bl,[esi+11] shl bx,15 or ax,bx stos word [edi] add esi,13 ret fp_zero_tword: xor eax,eax stos dword [edi] stos dword [edi] mov al,[esi+11] shl ax,15 stos word [edi] add esi,13 ret complex_tword: call get_word_value push eax cmp byte [esi],':' jne invalid_operand inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_qword_value call mark_relocation stos dword [edi] mov eax,edx stos dword [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_file: lods word [esi] cmp ax,'(' jne invalid_argument add esi,4 call open_binary_file mov eax,[esi-4] lea esi,[esi+eax+1] mov al,2 xor edx,edx call lseek push eax xor edx,edx cmp byte [esi],':' jne position_ok inc esi cmp byte [esi],'(' jne invalid_argument inc esi cmp byte [esi],'.' je invalid_value push ebx call get_count_value pop ebx mov edx,eax sub [esp],edx jc value_out_of_range position_ok: cmp byte [esi],',' jne size_ok inc esi cmp byte [esi],'(' jne invalid_argument inc esi cmp byte [esi],'.' je invalid_value push ebx edx call get_count_value pop edx ebx cmp eax,[esp] ja value_out_of_range mov [esp],eax size_ok: xor al,al call lseek pop ecx mov edx,edi add edi,ecx jc out_of_memory cmp edi,[tagged_blocks] ja out_of_memory call read jc error_reading_file call close lods byte [esi] cmp al,',' je data_file dec esi jmp instruction_assembled open_binary_file: push esi push edi mov eax,[current_line] find_current_source_path: mov esi,[eax] test byte [eax+7],80h jz get_current_path mov eax,[eax+8] jmp find_current_source_path get_current_path: lodsb stosb or al,al jnz get_current_path cut_current_path: cmp edi,[esp] je current_path_ok cmp byte [edi-1],'\' je current_path_ok cmp byte [edi-1],'/' je current_path_ok dec edi jmp cut_current_path current_path_ok: mov esi,[esp+4] call expand_path pop edx mov esi,edx call open jnc file_opened mov edx,[include_paths] search_in_include_paths: push edx esi mov edi,esi mov esi,[esp+4] call get_include_directory mov [esp+4],esi mov esi,[esp+8] call expand_path pop edx mov esi,edx call open pop edx jnc file_opened cmp byte [edx],0 jne search_in_include_paths mov edi,esi mov esi,[esp] push edi call expand_path pop edx mov esi,edx call open jc file_not_found file_opened: mov edi,esi pop esi ret reserve_bytes: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_bytes add edi,ecx jmp reserved_data zero_bytes: xor eax,eax shr ecx,1 jnc bytes_stosb_ok stos byte [edi] bytes_stosb_ok: shr ecx,1 jnc bytes_stosw_ok stos word [edi] bytes_stosw_ok: rep stos dword [edi] reserved_data: pop eax call undefined_data jmp instruction_assembled reserve_words: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data zero_words: xor eax,eax shr ecx,1 jnc words_stosw_ok stos word [edi] words_stosw_ok: rep stos dword [edi] jmp reserved_data reserve_dwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx shl edx,1 jc out_of_memory shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_dwords lea edi,[edi+ecx*4] jmp reserved_data zero_dwords: xor eax,eax rep stos dword [edi] jmp reserved_data reserve_pwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,1 jc out_of_memory add ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data reserve_qwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,1 jc out_of_memory mov edx,ecx shl edx,1 jc out_of_memory shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_dwords lea edi,[edi+ecx*4] jmp reserved_data reserve_twords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,2 jc out_of_memory add ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data align_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov edx,eax dec edx test eax,edx jnz invalid_align_value or eax,eax jz invalid_align_value cmp eax,1 je instruction_assembled mov ecx,edi mov ebp,[addressing_space] sub ecx,[ds:ebp] cmp dword [ds:ebp+10h],0 jne section_not_aligned_enough cmp byte [ds:ebp+9],0 je make_alignment cmp [output_format],3 je pe_alignment cmp [output_format],5 jne object_alignment test [format_flags],1 jnz pe_alignment object_alignment: mov ebx,[ds:ebp+14h] cmp byte [ebx],0 jne section_not_aligned_enough cmp eax,[ebx+10h] jbe make_alignment jmp section_not_aligned_enough pe_alignment: cmp eax,1000h ja section_not_aligned_enough make_alignment: dec eax and ecx,eax jz instruction_assembled neg ecx add ecx,eax inc ecx mov edx,ecx add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je nops add edi,ecx jmp reserved_data invalid_align_value: cmp [error_line],0 jne instruction_assembled mov eax,[current_line] mov [error_line],eax mov [error],invalid_value jmp instruction_assembled nops: mov eax,90909090h shr ecx,1 jnc nops_stosb_ok stos byte [edi] nops_stosb_ok: shr ecx,1 jnc nops_stosw_ok stos word [edi] nops_stosw_ok: rep stos dword [edi] jmp reserved_data err_directive: mov al,[esi] cmp al,0Fh je invoked_error or al,al jz invoked_error jmp extra_characters_on_line assert_directive: call calculate_logical_expression or al,al jnz instruction_assembled cmp [error_line],0 jne instruction_assembled mov eax,[current_line] mov [error_line],eax mov [error],assertion_failed jmp instruction_assembled