; flat assembler core ; Copyright (c) 1999-2022, 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] duplicate_output_path: lods byte [esi] cmp edi,[structures_buffer] jae out_of_memory stos byte [edi] or al,al jnz duplicate_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 mov ebx,eax call store_label_reference mov eax,ebx 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 js out_of_memory 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 jc resource_headers_ok 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 jnc read_resource_headers resource_headers_ok: cmp esi,[free_additional_memory] je invalid_file_format 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 mov byte [edx+10h],2 cmp word [esi],1D19h je format_elf_exe mov byte [edx+10h],3 cmp word [esi],021Eh 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 mov byte [edx+10h],2 cmp word [esi],1D19h je format_elf64_exe mov byte [edx+10h],3 cmp word [esi],021Eh je format_elf64_exe jmp elf_header_ok 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: test [format_flags],1 jnz invalid_use_of_symbol 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: mov ecx,edi sub ecx,[code_start] neg ecx and ecx,111b test [format_flags],8 jnz align_elf_structures and ecx,11b align_elf_structures: xor al,al rep stos byte [edi] 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] xor ecx,ecx sub ecx,eax test [format_flags],8 jnz finish_elf64_header and ecx,11b add eax,ecx 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: and ecx,111b add eax,ecx 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 add ecx,10*4 rep stos byte [edi] test [format_flags],8 jz elf_null_section_ok mov ecx,6*4 rep stos byte [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+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 ebp,[image_base] and dword [ebx+4],0 mov [ebx+8],ebp mov [ebx+0Ch],ebp mov eax,edi sub eax,[code_start] add eax,ebp mov [edx+18h],eax and [image_base_high],0 elf_exe_addressing_setup: call init_addressing_space call setup_elf_exe_labels_type mov eax,[code_start] xor edx,edx xor cl,cl sub eax,[image_base] sbb edx,[image_base_high] sbb cl,0 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+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 mov ebp,[image_base] mov ecx,[image_base_high] and dword [ebx+8],0 mov [ebx+10h],ebp mov [ebx+10h+4],ecx mov [ebx+18h],ebp mov [ebx+18h+4],ecx mov eax,edi sub eax,[code_start] add eax,ebp adc ecx,0 mov [edx+18h],eax mov [edx+18h+4],ecx jmp elf_exe_addressing_setup setup_elf_exe_labels_type: mov eax,[code_start] cmp byte [eax+10h],3 jne elf_exe_labels_type_ok mov byte [ebx+9],2 test [format_flags],8 jz elf_exe_labels_type_ok mov byte [ebx+9],4 elf_exe_labels_type_ok: ret 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 mov edx,[code_start] mov [edx+18h],eax jmp instruction_assembled elf64_entry: call get_qword_value 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 call setup_elf_exe_labels_type 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 or [next_pass_needed],-1 new_elf_segment: mov byte [ebx],1 and dword [ebx+18h],0 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: pop edx cmp byte [ebx],1 jne no_elf_segment_merging cmp [merge_segment],0 jne merge_elf_segment no_elf_segment_merging: mov eax,edi sub eax,[code_start] mov [ebx+4],eax and eax,0FFFh add eax,edx mov [ebx+8],eax mov [ebx+0Ch],eax xor edx,edx elf_segment_addressing_setup: 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 mov [ds:ebp],eax mov [ds:ebp+4],edx mov [ds:ebp+8],cl inc [number_of_sections] jmp instruction_assembled merge_elf_segment: xor ecx,ecx xchg ecx,[merge_segment] cmp ecx,-1 je merge_elf_header mov eax,[ecx+8] mov ecx,[ecx+4] elf_segment_separated_base: mov [ebx+8],eax mov [ebx+0Ch],eax mov [ebx+4],ecx sub eax,ecx add eax,edi sub eax,[code_start] xor edx,edx jmp elf_segment_addressing_setup merge_elf_header: mov eax,[image_base] xor ecx,ecx jmp elf_segment_separated_base close_elf_segment: cmp [number_of_sections],0 jne finish_elf_segment cmp edi,[symbols_stream] jne first_elf_segment_ok or [merge_segment],-1 mov eax,[image_base] ret first_elf_segment_ok: and [merge_segment],0 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 cmp byte [ebx],1 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 je elf_segment_position_move_and_align cmp [merge_segment],0 jne elf_segment_position_move cmp byte [ebx],4 je elf_segment_position_ok cmp byte [ebx],51h je elf_segment_position_ok mov [merge_segment],ebx elf_segment_position_move: add eax,[ebx+14h] jmp elf_segment_position_ok elf_segment_position_move_and_align: 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 call setup_elf_exe_labels_type 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 or [next_pass_needed],-1 new_elf64_segment: mov byte [ebx],1 and dword [ebx+4],0 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: pop edx eax cmp byte [ebx],1 jne no_elf64_segment_merging cmp [merge_segment],0 jne merge_elf64_segment no_elf64_segment_merging: mov ecx,edi sub ecx,[code_start] mov [ebx+8],ecx 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 jmp elf_segment_addressing_setup merge_elf64_segment: xor ecx,ecx xchg ecx,[merge_segment] cmp ecx,-1 je merge_elf64_header mov eax,[ecx+10h] mov edx,[ecx+10h+4] mov ecx,[ecx+8] elf64_segment_separated_base: mov [ebx+10h],eax mov [ebx+10h+4],edx mov [ebx+18h],eax mov [ebx+18h+4],edx mov [ebx+8],ecx neg ecx add ecx,edi sub ecx,[code_start] add eax,ecx adc edx,0 jmp elf_segment_addressing_setup merge_elf64_header: mov eax,[image_base] mov edx,[image_base_high] xor ecx,ecx jmp elf64_segment_separated_base close_elf64_segment: cmp [number_of_sections],0 jne finish_elf64_segment cmp edi,[symbols_stream] jne first_elf64_segment_ok or [merge_segment],-1 mov eax,[image_base] mov edx,[image_base_high] ret first_elf64_segment_ok: and [merge_segment],0 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 cmp byte [ebx],1 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 je elf64_segment_position_move_and_align cmp [merge_segment],0 jne elf64_segment_position_move cmp byte [ebx],4 je elf64_segment_position_ok cmp byte [ebx],51h je elf64_segment_position_ok mov [merge_segment],ebx elf64_segment_position_move: add eax,[ebx+28h] adc edx,0 jmp elf64_segment_position_ok elf64_segment_position_move_and_align: 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