listing: mov edx,[input_file] call open jc input_not_found call load_file mov [input],eax cmp ecx,38h jb invalid_input cmp dword [eax],1A736166h jne invalid_input cmp dword [eax+44],0 je incomplete_input add [eax+16],eax add [eax+24],eax add [eax+32],eax add [eax+40],eax add [eax+48],eax mov edx,[eax+16] add [eax+8],edx add [eax+12],edx mov edx,[eax+12] call open jc code_not_found call load_file mov [assembled_code],eax mov [assembled_code_length],ecx call close mov [maximum_address_length],0 mov ebx,[input] mov esi,[ebx+40] lea ebp,[esi-4] add ebp,[ebx+44] get_offsets_for_lines: cmp esi,ebp je offsets_prepared mov edx,[esi+4] add edx,[ebx+32] find_line_loaded_from_source: test byte [edx+7],1 shl 7 jz store_offset_in_line mov edx,[edx+8] add edx,[ebx+32] jmp find_line_loaded_from_source store_offset_in_line: cmp dword [edx+12],0 jne get_next_offset mov [edx+12],esi movzx ecx,byte [esi+27] and cl,1 mov edi,[esi+20] test edi,edi jz base_name_length_ok xor ecx,ecx btr edi,31 jc count_base_name_characters dec edi shl edi,2 add edi,[ebx+48] mov edi,[edi] count_base_name_characters: mov ecx,[ebx+20] sub ecx,edi add edi,[ebx+16] mov edx,edi xor al,al repne scasb mov ecx,edi sub ecx,edx base_name_length_ok: cmp byte [esi+18],1 jb first_register_length_ok ja first_register_with_scale add ecx,5 jmp first_register_length_ok first_register_with_scale: add ecx,5+3 first_register_length_ok: cmp byte [esi+19],1 jb second_register_length_ok ja second_register_with_scale add ecx,5 jmp second_register_length_ok second_register_with_scale: add ecx,5+3 second_register_length_ok: cmp ecx,[maximum_address_length] jb get_next_offset mov [maximum_address_length],ecx get_next_offset: add esi,28 jmp get_offsets_for_lines offsets_prepared: mov eax,[esi] mov [code_end],eax add [maximum_address_length],19 mov edi,characters xor al,al make_characters_table: stosb inc al jnz make_characters_table mov edi,characters mov esi,symbol_characters+1 movzx ecx,byte [esi-1] xor eax,eax mark_symbol_characters: lodsb mov byte [edi+eax],0 loop mark_symbol_characters mov eax,[code_bytes_per_line] imul eax,3 add eax,[maximum_address_length] add eax,18 call alloc jc not_enough_memory mov [output_buffer],eax mov esi,[ebx+32] mov ebp,esi add ebp,[ebx+36] mov edx,[output_file] call create jc writing_error mov [output_handle],ebx xor eax,eax mov [current_source_file],eax mov [last_listed_address],eax mov [code_length],eax generate_listing: cmp esi,ebp jae listing_done mov edi,[output_buffer] test byte [esi+7],1 shl 7 jnz next_line mov ebx,[esi+12] test ebx,ebx jz no_code_listing test byte [ebx+26],11b jnz no_code_listing push esi mov edx,[esi] mov ecx,[esi+4] find_next_code_point: add esi,16 call skip_preprocessed_line cmp esi,ebp je last_code_point cmp edx,[esi] jne next_line_ok cmp ecx,[esi+4] je find_next_code_point next_line_ok: test byte [esi+7],1 shl 7 jnz find_next_code_point mov eax,[esi+12] test eax,eax jz find_next_code_point test byte [eax+26],11b jnz find_next_code_point mov eax,[eax] jmp calculate_code_length last_code_point: mov eax,[code_end] calculate_code_length: pop esi mov edx,[ebx] sub eax,edx jz no_code_listing mov [code_length],eax mov [code_offset],edx add eax,edx cmp eax,[assembled_code_length] jbe write_file_offset mov [code_length],0 write_file_offset: call write_hex_dword mov ax,': ' stosw call list_address call list_code jmp code_listing_ok no_code_listing: mov al,20h mov ecx,8+2 rep stosb call list_address mov ecx,[code_bytes_per_line] imul ecx,3 mov al,20h rep stosb code_listing_ok: call write_listing_data mov eax,[input] mov edx,[esi] test edx,edx jz main_source_file add edx,[eax+32] jmp source_name_ok main_source_file: mov edx,[eax+8] source_name_ok: cmp edx,[current_source_file] je source_loaded push ebx push edx call open jc source_not_found pop eax xchg eax,[current_source_file] test eax,eax jz load_source mov eax,[source] call free load_source: call load_file mov [source],eax mov [source_length],ecx call close pop ebx source_loaded: mov eax,[source] add eax,[esi+8] mov [current_source_line],eax push esi ebp call write_source_line pop ebp esi write_supplemental_rows: mov eax,[code_length] or eax,[current_source_line] jz next_line mov edi,[output_buffer] mov ecx,8+2 movzx eax,[show_addresses] imul eax,[maximum_address_length] add ecx,eax mov al,20h rep stosb call list_code call write_listing_data push esi ebp call write_source_line pop ebp esi jmp write_supplemental_rows next_line: mov edx,[esi] mov ecx,[esi+4] find_next_line: add esi,16 call skip_preprocessed_line cmp edx,[esi] jne generate_listing cmp ecx,[esi+4] jne generate_listing jmp find_next_line list_address: cmp [show_addresses],0 je address_ok mov [address_start],edi mov eax,[esi+12] test eax,eax jz address_finished cmp [last_listed_address],0 je make_address push esi edi lea esi,[eax+8] mov edi,[last_listed_address] mov ecx,17 repe cmpsb pop edi esi je address_finished make_address: mov ebx,[esi+12] lea eax,[ebx+8] mov [last_listed_address],eax mov al,'[' stosb mov edx,[ebx+20] test edx,edx jz write_main_address push esi mov esi,edx mov eax,[input] btr esi,31 jc base_name_ready dec esi shl esi,2 add esi,[eax+48] mov esi,[esi] base_name_ready: add esi,[eax+16] copy_section_name: lodsb test al,al jz section_name_ok stosb jmp copy_section_name section_name_ok: pop esi mov al,':' test edx,80000000h jz address_separator_ok cmp byte [ebx+27],0 jne address_separator_ok mov al,'+' address_separator_ok: stosb write_main_address: cmp byte [ebx+27],0 jne write_negative_address mov edx,[ebx+8+4] call write_hex_dword mov edx,[ebx+8] call write_hex_dword jmp write_address_registers write_negative_address: mov al,'-' stosb mov eax,[ebx+8] mov edx,[ebx+8+4] not eax not edx add eax,1 adc edx,0 push eax call write_hex_dword pop edx call write_hex_dword write_address_registers: mov dl,[ebx+16] mov dh,[ebx+18] call address_register mov dl,[ebx+17] mov dh,[ebx+19] call address_register mov ax,']' stosb address_finished: mov ecx,[maximum_address_length] sub ecx,edi add ecx,[address_start] mov al,20h rep stosb address_ok: ret address_register: cmp dh,0 je register_ok jl negative_register mov al,'+' jmp register_sign_ok negative_register: mov al,'-' register_sign_ok: stosb push esi mov esi,address_registers find_register: lodsb test al,al jz register_found cmp al,dl je register_found cmp dl,[esi] je register_found lodsb movzx eax,al add esi,eax jmp find_register register_found: lodsb movzx ecx,al rep movsb pop esi cmp dh,1 je register_ok mov al,'*' stosb test dh,0F0h jz first_scale_digit_ok mov al,dh shr al,4 cmp al,10 sbb al,69h das stosb first_scale_digit_ok: mov al,dh and al,1111b cmp al,10 sbb al,69h das stosb register_ok: ret list_code: mov ecx,[code_length] cmp ecx,[code_bytes_per_line] jb code_bytes_count_ready mov ecx,[code_bytes_per_line] code_bytes_count_ready: sub [code_length],ecx mov edx,[code_offset] add [code_offset],ecx jecxz code_bytes_ok push ecx add edx,[assembled_code] list_code_bytes: mov al,[edx] and al,1111b cmp al,10 sbb al,69h das mov ah,al mov al,[edx] shr al,4 cmp al,10 sbb al,69h das stosw mov al,20h stosb inc edx loop list_code_bytes pop ecx code_bytes_ok: neg ecx add ecx,[code_bytes_per_line] imul ecx,3 mov al,20h rep stosb ret write_listing_data: mov ecx,[output_buffer] sub ecx,edi and ecx,111b mov al,20h rep stosb mov edx,[output_buffer] mov ecx,edi sub ecx,edx mov ebx,[output_handle] call write jc writing_error ret write_source_line: mov esi,[current_source_line] test esi,esi je write_line_break mov ebp,[source_length] add ebp,[source] mov ebx,characters xor cl,cl start_cutting: xor dl,dl cut_source_line: cmp esi,ebp je end_of_file lodsb cmp al,0Dh je cr_character cmp al,0Ah je lf_character cmp al,1Ah je end_of_line or al,al jz end_of_line cmp dl,3Bh je cut_source_line cmp al,3Bh je start_special_block cmp dl,22h je inside_string cmp dl,27h je inside_string cmp al,'\' je check_for_line_continuation xlatb test al,al jz start_cutting cmp dl,0FFh je cut_source_line cmp al,22h je start_special_block cmp al,27h je start_special_block mov dl,0FFh jmp cut_source_line start_special_block: mov dl,al jmp cut_source_line inside_string: cmp al,dl jne cut_source_line jmp start_cutting check_for_line_continuation: or cl,0FFh cmp esi,ebp je end_of_file mov al,[esi] cmp al,20h je start_cutting cmp al,0Dh je start_cutting cmp al,0Ah je start_cutting cmp al,3Bh je start_cutting xor cl,cl jmp start_cutting cr_character: mov edx,esi mov word [line_break],0Dh cmp esi,ebp je line_with_break mov al,[esi] cmp al,0Ah jne line_with_break inc edx mov [line_break+1],al jmp line_with_break lf_character: mov edx,esi mov word [line_break],0Ah cmp esi,ebp je line_with_break mov al,[esi] cmp al,0Dh jne line_with_break inc edx mov [line_break+1],al line_with_break: dec esi jmp write_line end_of_line: dec esi end_of_file: mov edx,esi write_line: cmp cl,0FFh je continued_line xor edx,edx continued_line: xchg edx,[current_source_line] mov ecx,esi sub ecx,edx mov ebx,[output_handle] call write jc writing_error write_line_break: mov edx,line_break mov ecx,2 cmp [line_break+1],0 jne line_break_size_ok dec ecx line_break_size_ok: call write jc writing_error ret listing_done: mov ebx,[output_handle] call close ret load_file: push ebx mov al,2 xor edx,edx call lseek test eax,eax jz empty_file push eax call alloc jc not_enough_memory push eax xor al,al xor edx,edx call lseek mov ecx,[esp+4] mov edx,[esp] call read jc reading_error pop eax ecx pop ebx ret empty_file: pop ebx mov ecx,eax ret write_hex_dword: mov ecx,8 write_hex_digits: xor al,al shld eax,edx,4 cmp al,10 sbb al,69h das stosb shl edx,4 loop write_hex_digits ret skip_preprocessed_line: lods byte [esi] cmp al,1Ah je skip_preprocessed_symbol cmp al,3Bh je skip_preprocessed_symbol cmp al,22h je skip_preprocessed_string or al,al jnz skip_preprocessed_line ret skip_preprocessed_symbol: lods byte [esi] movzx eax,al add esi,eax jmp skip_preprocessed_line skip_preprocessed_string: lods dword [esi] add esi,eax jmp skip_preprocessed_line not_enough_memory: call error db 'not enough memory to load the required data',0 input_not_found: call error db 'the input file was not found',0 code_not_found: call error db 'the assembled file was not found',0 source_not_found: call error db 'could not find some of the source files',0 reading_error: call error db 'some error occured while trying to read file',0 writing_error: call error db 'some error occured while trying to write file',0 invalid_input: call error db 'input file is not a recognized assembly information format',0 incomplete_input: call error db 'input file does not contain an assembly dump',0 symbol_characters db 27, 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\' address_registers db 23h,2,'bx' db 25h,2,'bp' db 26h,2,'si' db 27h,2,'di' db 40h,3,'eax' db 41h,3,'ecx' db 42h,3,'edx' db 43h,3,'ebx' db 44h,3,'esp' db 45h,3,'ebp' db 46h,3,'esi' db 47h,3,'edi' db 48h,3,'r8d' db 49h,3,'r9d' db 4Ah,4,'r10d' db 4Bh,4,'r11d' db 4Ch,4,'r12d' db 4Dh,4,'r13d' db 4Eh,4,'r14d' db 4Fh,4,'r15d' db 80h,3,'rax' db 81h,3,'rcx' db 82h,3,'rdx' db 83h,3,'rbx' db 84h,3,'rsp' db 85h,3,'rbp' db 86h,3,'rsi' db 87h,3,'rdi' db 88h,2,'r8' db 89h,2,'r9' db 8Ah,3,'r10' db 8Bh,3,'r11' db 8Ch,3,'r12' db 8Dh,3,'r13' db 8Eh,3,'r14' db 8Fh,3,'r15' db 0F4h,3,'eip' db 0F8h,3,'rip' db 0,1,'?'