4 definition dd ? ; pointer to ValueDefinition
\r
9 base_address_length dd ?
\r
10 uninitialized_length dd ?
\r
15 AREA_SHIFT_TRACKING_DISABLED = 4
\r
19 ; esi - base address in format of VALTYPE_NUMERIC value
\r
20 ; ecx = length of base address value
\r
23 ; edx - ValueDefinition
\r
24 mov eax,[current_output_area_entry]
\r
26 jz create_first_output_area
\r
28 lea ecx,[eax+sizeof.OutputArea*2]
\r
29 cmp ecx,[output_areas_list_end]
\r
30 jbe get_next_output_entry
\r
31 mov eax,[output_areas_list]
\r
33 sub [current_output_area_entry],eax
\r
34 sub [initial_output_area_entry],eax
\r
35 sub [output_areas_list_end],eax
\r
37 mov [output_areas_list],eax
\r
38 add [current_output_area_entry],eax
\r
39 add [initial_output_area_entry],eax
\r
42 xchg [output_areas_list_end],eax
\r
48 mov eax,[current_output_area_entry]
\r
49 get_next_output_entry:
\r
50 add eax,sizeof.OutputArea
\r
51 cmp [initial_output_area_entry],0
\r
52 je another_initial_output_area
\r
53 mov edi,[eax-sizeof.OutputArea+OutputArea.definition]
\r
54 mov ecx,[edi+ValueDefinition.value_length]
\r
55 mov edi,[edi+ValueDefinition.value]
\r
56 mov ebx,[edi+AreaHeader.uninitialized_length]
\r
57 sub ecx,sizeof.AreaHeader
\r
58 sub ecx,[edi+AreaHeader.base_address_length]
\r
59 jz prior_uninitialized_length_ok
\r
60 and dword [prior_uninitialized_length],0
\r
61 and dword [prior_uninitialized_length+4],0
\r
62 prior_uninitialized_length_ok:
\r
63 add dword [prior_uninitialized_length],ebx
\r
64 adc dword [prior_uninitialized_length+4],0
\r
68 add ecx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset]
\r
69 adc edx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset+4]
\r
70 mov dword [eax+OutputArea.cached_offset],ecx
\r
71 mov dword [eax+OutputArea.cached_offset+4],edx
\r
73 jmp new_output_entry_ready
\r
74 another_initial_output_area:
\r
76 jmp create_initial_output_area
\r
77 create_first_output_area:
\r
78 mov eax,[output_areas_list]
\r
79 create_initial_output_area:
\r
80 mov [initial_output_area_entry],eax
\r
81 and dword [eax+OutputArea.cached_offset],0
\r
82 and dword [eax+OutputArea.cached_offset+4],0
\r
83 and dword [prior_uninitialized_length],0
\r
84 and dword [prior_uninitialized_length+4],0
\r
85 new_output_entry_ready:
\r
86 mov [current_output_area_entry],eax
\r
87 lea ebx,[eax+OutputArea.definition]
\r
93 ; ebx - where pointer to ValueDefinition should be stored, may already hold a previously used one (should contain null otherwise)
\r
94 ; esi - base address in format of VALTYPE_NUMERIC value
\r
95 ; ecx = length of base address value
\r
98 ; edx - ValueDefinition
\r
99 mov [address_length],ecx
\r
102 jz current_area_definition_unusable
\r
103 cmp [edx+ValueDefinition.reference_count],1
\r
104 je area_definition_ready
\r
105 dec [edx+ValueDefinition.reference_count]
\r
106 current_area_definition_unusable:
\r
107 mov ecx,retired_definition
\r
108 retrieve_retired_detached_value:
\r
111 jz create_area_definition
\r
112 cmp [edx+ValueDefinition.reference_count],0
\r
113 jne retired_detached_value_immutable
\r
115 xchg eax,[edx+ValueDefinition.previous]
\r
117 jmp adopt_area_definition
\r
118 retired_detached_value_immutable:
\r
119 lea ecx,[edx+ValueDefinition.previous]
\r
120 jmp retrieve_retired_detached_value
\r
121 create_area_definition:
\r
122 mov ecx,sizeof.ValueDefinition
\r
123 call create_tree_element
\r
125 xchg ecx,[value_definition_chain]
\r
126 mov [eax+ValueDefinition.interlink],ecx
\r
128 adopt_area_definition:
\r
130 or [edx+ValueDefinition.flags],VAL_DETACHED
\r
131 inc [edx+ValueDefinition.reference_count]
\r
132 area_definition_ready:
\r
133 mov ecx,[address_length]
\r
134 add ecx,sizeof.AreaHeader
\r
135 mov eax,[edx+ValueDefinition.block_length]
\r
137 jz allocate_area_block
\r
139 jbe initialize_area_block
\r
142 xchg eax,[edx+ValueDefinition.value]
\r
145 allocate_area_block:
\r
147 call malloc_growable
\r
149 mov [edx+ValueDefinition.value],eax
\r
150 mov [edx+ValueDefinition.block_length],ecx
\r
151 initialize_area_block:
\r
152 mov ebx,[edx+ValueDefinition.value]
\r
153 lea edi,[ebx+sizeof.AreaHeader]
\r
154 mov ecx,[address_length]
\r
155 mov [ebx+AreaHeader.base_address_length],ecx
\r
157 mov [ebx+AreaHeader.uninitialized_length],ecx
\r
158 mov [ebx+AreaHeader.flags],ecx
\r
160 mov [edx+ValueDefinition.value_length],edi
\r
161 mov [edx+ValueDefinition.type],VALTYPE_AREA
\r
162 mov ecx,[current_pass]
\r
163 mov [edx+ValueDefinition.pass],ecx
\r
167 ; in: ecx = number of bytes that should be added to output
\r
168 ; out: edi - output buffer to be filled with data
\r
170 mov edx,[current_area]
\r
171 mov ebx,[edx+ValueDefinition.value]
\r
172 add ecx,[ebx+AreaHeader.uninitialized_length]
\r
173 jc output_out_of_memory
\r
174 mov eax,[edx+ValueDefinition.value_length]
\r
177 jc output_out_of_memory
\r
178 mov [edx+ValueDefinition.value_length],ecx
\r
179 cmp ecx,[edx+ValueDefinition.block_length]
\r
180 jbe area_reserve_sufficient
\r
181 mov eax,[edx+ValueDefinition.value]
\r
193 jbe output_out_of_memory
\r
199 mov [edx+ValueDefinition.value],ebx
\r
200 mov [edx+ValueDefinition.block_length],ecx
\r
201 area_reserve_sufficient:
\r
202 mov ecx,[ebx+AreaHeader.uninitialized_length]
\r
203 jecxz output_buffer_ready
\r
211 mov [ebx+AreaHeader.uninitialized_length],eax
\r
212 output_buffer_ready:
\r
214 output_out_of_memory:
\r
217 uninitialized_output:
\r
218 ; in: ecx = number of uninitialized bytes to be added to output
\r
219 ; preserves: ebx, ecx, esi, edi
\r
220 mov edx,[current_area]
\r
221 mov eax,[edx+ValueDefinition.value]
\r
222 add [eax+AreaHeader.uninitialized_length],ecx
\r
224 mov edx,[edx+ValueDefinition.value_length]
\r
225 sub edx,sizeof.AreaHeader
\r
226 sub edx,[eax+AreaHeader.base_address_length]
\r
227 add edx,[eax+AreaHeader.uninitialized_length]
\r
231 mov edx,_area_overflow
\r
232 call register_error
\r
233 mov edx,[current_area]
\r
235 mov eax,[edx+ValueDefinition.value]
\r
236 sub ecx,[edx+ValueDefinition.value_length]
\r
237 add ecx,sizeof.AreaHeader
\r
238 add ecx,[eax+AreaHeader.base_address_length]
\r
239 mov [eax+AreaHeader.uninitialized_length],ecx
\r
243 ; preserves: ecx, esi
\r
245 mov dword [prior_uninitialized_length],eax
\r
246 mov dword [prior_uninitialized_length+4],eax
\r
247 mov edi,[current_output_area_entry]
\r
248 trim_current_output_area:
\r
249 mov edx,[edi+OutputArea.definition]
\r
250 mov eax,[edx+ValueDefinition.value]
\r
251 and [eax+AreaHeader.uninitialized_length],0
\r
252 mov ebx,[edx+ValueDefinition.value_length]
\r
253 sub ebx,sizeof.AreaHeader
\r
254 sub ebx,[eax+AreaHeader.base_address_length]
\r
256 cmp edi,[initial_output_area_entry]
\r
258 sub edi,sizeof.OutputArea
\r
259 jmp trim_current_output_area
\r
261 mov [current_output_area_entry],edi
\r
266 ; [file_offset] = offset within the output
\r
268 ; cf set when not found an area that would contain a byte at specified offset
\r
271 ; [file_offset] = offset relative to the beginning of the found area (upper 32 bits are zero)
\r
272 mov esi,[initial_output_area_entry]
\r
273 mov edi,[current_output_area_entry]
\r
274 add edi,sizeof.OutputArea
\r
278 jz output_area_not_found
\r
279 test ebx,1 shl bsf sizeof.OutputArea
\r
280 jz bisect_areas_list
\r
281 sub ebx,sizeof.OutputArea
\r
285 mov eax,dword [file_offset]
\r
286 mov edx,dword [file_offset+4]
\r
287 sub eax,dword [ebx+OutputArea.cached_offset]
\r
288 sbb edx,dword [ebx+OutputArea.cached_offset+4]
\r
289 jc search_earlier_areas
\r
290 jnz search_later_areas
\r
291 mov edx,[ebx+OutputArea.definition]
\r
292 mov ecx,[edx+ValueDefinition.value_length]
\r
293 mov edx,[edx+ValueDefinition.value]
\r
294 sub ecx,sizeof.AreaHeader
\r
295 sub ecx,[edx+AreaHeader.base_address_length]
\r
296 add ecx,[edx+AreaHeader.uninitialized_length]
\r
298 jae search_later_areas
\r
300 mov dword [file_offset],eax
\r
301 and dword [file_offset+4],0
\r
304 output_area_not_found:
\r
307 search_later_areas:
\r
308 lea esi,[ebx+sizeof.OutputArea]
\r
310 search_earlier_areas:
\r
316 ; edi - buffer for read data
\r
317 ; [value_length] = length of data to read
\r
318 ; [file_offset] = offset within the output
\r
320 ; [value_length] = number of bytes that were not in the existing output and could not be read
\r
322 call find_output_area
\r
324 jc output_reading_done
\r
326 cmp [value_length],0
\r
327 je output_reading_done
\r
328 mov edx,[ebx+OutputArea.definition]
\r
329 mov ecx,[edx+ValueDefinition.value_length]
\r
331 mov edx,[edx+ValueDefinition.value]
\r
332 sub ecx,sizeof.AreaHeader
\r
333 sub ecx,[edx+AreaHeader.base_address_length]
\r
334 sub dword [file_offset],ecx
\r
335 jnc initialized_load_done
\r
337 mov ecx,dword [file_offset]
\r
340 cmp ecx,[value_length]
\r
341 jbe initialized_load_length_ok
\r
342 mov ecx,[value_length]
\r
343 initialized_load_length_ok:
\r
344 sub [value_length],ecx
\r
346 mov dword [file_offset],ecx
\r
347 initialized_load_done:
\r
348 mov ecx,[edx+AreaHeader.uninitialized_length]
\r
349 sub dword [file_offset],ecx
\r
350 jnc uninitialized_load_done
\r
351 mov ecx,dword [file_offset]
\r
353 cmp ecx,[value_length]
\r
354 jbe uninitialized_load_length_ok
\r
355 mov ecx,[value_length]
\r
356 uninitialized_load_length_ok:
\r
357 sub [value_length],ecx
\r
360 mov dword [file_offset],ecx
\r
361 uninitialized_load_done:
\r
362 cmp ebx,[current_output_area_entry]
\r
363 je output_reading_done
\r
364 add ebx,sizeof.OutputArea
\r
365 jmp read_output_areas
\r
366 output_reading_done:
\r
371 ; esi - data to write
\r
372 ; [value_length] = length of data to write
\r
373 ; [file_offset] = offset within the output
\r
375 ; [value_length] = number of bytes that were not in the existing output and could not be rewritten
\r
377 call find_output_area
\r
379 jc output_rewriting_done
\r
380 rewrite_output_areas:
\r
381 cmp [value_length],0
\r
382 je output_rewriting_done
\r
383 mov edx,[ebx+OutputArea.definition]
\r
384 mov ecx,[edx+ValueDefinition.value_length]
\r
385 mov edx,[edx+ValueDefinition.value]
\r
386 sub ecx,sizeof.AreaHeader
\r
387 sub ecx,[edx+AreaHeader.base_address_length]
\r
388 mov edi,[edx+AreaHeader.uninitialized_length]
\r
390 sub dword [file_offset],ecx
\r
391 jnc rewrite_next_area
\r
392 mov eax,[value_length]
\r
396 add eax,dword [file_offset]
\r
397 jnc rewrite_initialized_data
\r
399 jbe rewrite_uninitialized_data
\r
401 rewrite_uninitialized_data:
\r
403 jz rewrite_initialized_data
\r
405 sub [edx+AreaHeader.uninitialized_length],eax
\r
406 mov edx,[ebx+OutputArea.definition]
\r
409 call update_output_offsets
\r
411 rewrite_initialized_data:
\r
412 mov edx,[ebx+OutputArea.definition]
\r
413 mov ecx,[edx+ValueDefinition.value_length]
\r
414 mov edi,[edx+ValueDefinition.value]
\r
415 or [edi+AreaHeader.flags],AREA_VARIABLE
\r
416 add edi,[edi+AreaHeader.uninitialized_length]
\r
418 mov ecx,dword [file_offset]
\r
421 cmp ecx,[value_length]
\r
422 jbe rewrite_length_ok
\r
423 mov ecx,[value_length]
\r
425 sub [value_length],ecx
\r
427 mov dword [file_offset],ecx
\r
429 cmp ebx,[current_output_area_entry]
\r
430 je output_rewriting_done
\r
431 add ebx,sizeof.OutputArea
\r
432 jmp rewrite_output_areas
\r
433 output_rewriting_done:
\r
436 update_output_offsets:
\r
438 ; edx - ValueDefinition of output area that had some of uninitialized data made initialized
\r
440 mov eax,[current_output_area_entry]
\r
441 cmp edx,[eax+OutputArea.definition]
\r
442 je output_offsets_ok
\r
443 and dword [prior_uninitialized_length],0
\r
444 and dword [prior_uninitialized_length+4],0
\r
445 recount_prior_uninitialized_length:
\r
446 cmp eax,[initial_output_area_entry]
\r
447 je output_offsets_ok
\r
448 sub eax,sizeof.OutputArea
\r
449 mov edi,[eax+OutputArea.definition]
\r
450 mov ebx,[edi+ValueDefinition.value]
\r
451 mov ecx,[ebx+AreaHeader.uninitialized_length]
\r
452 add dword [prior_uninitialized_length],ecx
\r
453 adc dword [prior_uninitialized_length+4],0
\r
455 je output_offsets_ok
\r
456 mov ecx,[edi+ValueDefinition.value_length]
\r
457 sub ecx,sizeof.AreaHeader
\r
458 sub ecx,[ebx+AreaHeader.base_address_length]
\r
459 jz recount_prior_uninitialized_length
\r
463 get_current_address_value:
\r
465 ; esi - address in format of VALTYPE_NUMERIC value
\r
466 ; ecx = length of address value
\r
467 ; note: the returned value is placed in assembly workspace
\r
468 mov eax,[current_area]
\r
469 mov esi,[eax+ValueDefinition.value]
\r
470 mov ebx,[eax+ValueDefinition.value_length]
\r
471 mov edx,assembly_workspace
\r
472 mov edi,[edx+Workspace.memory_start]
\r
473 mov ecx,[esi+AreaHeader.base_address_length]
\r
475 call reserve_workspace
\r
476 mov ecx,[esi+AreaHeader.base_address_length]
\r
478 sub ebx,sizeof.AreaHeader
\r
479 add ebx,[esi+AreaHeader.uninitialized_length]
\r
480 ; jc internal_error
\r
481 add esi,sizeof.AreaHeader
\r
487 jecxz offset_added_to_base_address
\r
488 add_offset_to_base_address:
\r
495 loop add_offset_to_base_address
\r
496 offset_added_to_base_address:
\r
497 mov edx,[assembly_workspace.memory_start]
\r
500 cmp byte [esi-1],80h
\r
504 optimize_base_address:
\r
505 movsx eax,byte [edi-2]
\r
507 jne base_address_ready
\r
510 jne optimize_base_address
\r
511 base_address_ready:
\r
516 measure_variable_terms:
\r
519 jz variable_terms_measured
\r
522 jmp measure_variable_terms
\r
523 variable_terms_measured:
\r
532 mov esi,[assembly_workspace.memory_start]
\r
539 ; edx:eax = length of current output (not counting uninitialized data)
\r
541 mov ebx,[current_output_area_entry]
\r
542 mov eax,dword [ebx+OutputArea.cached_offset]
\r
543 mov edx,dword [ebx+OutputArea.cached_offset+4]
\r
544 mov edi,[ebx+OutputArea.definition]
\r
545 mov ecx,[edi+ValueDefinition.value_length]
\r
546 mov edi,[edi+ValueDefinition.value]
\r
547 sub ecx,sizeof.AreaHeader
\r
548 sub ecx,[edi+AreaHeader.base_address_length]
\r
549 jz current_area_entirely_uninitialized
\r
553 current_area_entirely_uninitialized:
\r
554 sub eax,dword [prior_uninitialized_length]
\r
555 sbb edx,dword [prior_uninitialized_length+4]
\r
558 get_output_position:
\r
560 ; edx:eax = current position in the output (including uninitialized data)
\r
562 mov ebx,[current_output_area_entry]
\r
563 mov eax,dword [ebx+OutputArea.cached_offset]
\r
564 mov edx,dword [ebx+OutputArea.cached_offset+4]
\r
565 mov edi,[ebx+OutputArea.definition]
\r
566 mov ecx,[edi+ValueDefinition.value_length]
\r
567 mov edi,[edi+ValueDefinition.value]
\r
568 sub ecx,sizeof.AreaHeader
\r
569 sub ecx,[edi+AreaHeader.base_address_length]
\r
570 add ecx,[edi+AreaHeader.uninitialized_length]
\r
575 create_output_path:
\r
577 ; ebx - base path and name
\r
578 ; esi - file extension
\r
579 ; ecx = length of the extension
\r
581 ; edx - output path (generated in temporary storage)
\r
599 jne locate_extension
\r
604 mov edi,[preprocessing_workspace.memory_start]
\r
606 mov edx,preprocessing_workspace
\r
607 call reserve_workspace
\r
615 call reserve_workspace
\r
617 jecxz extension_attached
\r
621 extension_attached:
\r
624 mov edx,[preprocessing_workspace.memory_start]
\r
629 ; ebx - source path
\r
630 ; edi - output path
\r
632 ; cf set when write failed
\r
634 ; when output path is null, source path is used with replaced or attached extension
\r
635 mov [base_path],edi
\r
637 mov [output_failures],eax
\r
638 mov dword [uninitialized_length],eax
\r
639 mov dword [uninitialized_length+4],eax
\r
642 jnz create_output_file
\r
643 mov [base_path],ebx
\r
644 mov esi,[output_extension]
\r
645 mov ecx,[output_extension_length]
\r
646 call create_output_path
\r
647 create_output_file:
\r
649 jc output_write_failed
\r
650 mov esi,[initial_output_area_entry]
\r
652 mov edx,[esi+OutputArea.definition]
\r
653 mov eax,[edx+ValueDefinition.value]
\r
654 mov ecx,[edx+ValueDefinition.value_length]
\r
655 sub ecx,[eax+AreaHeader.base_address_length]
\r
656 sub ecx,sizeof.AreaHeader
\r
658 mov eax,dword [uninitialized_length]
\r
659 or eax,dword [uninitialized_length+4]
\r
660 jz write_initialized_data
\r
661 write_uninitialized_data:
\r
662 mov edi,[assembly_workspace.memory_start]
\r
663 mov ecx,1000h shr 2
\r
667 cmp dword [uninitialized_length+4],0
\r
668 jne portion_length_ok
\r
669 cmp ecx,dword [uninitialized_length]
\r
670 jbe portion_length_ok
\r
671 mov ecx,dword [uninitialized_length]
\r
673 sub dword [uninitialized_length],ecx
\r
674 sbb dword [uninitialized_length+4],0
\r
675 mov edx,[assembly_workspace.memory_start]
\r
677 jc file_write_failed
\r
678 mov eax,dword [uninitialized_length]
\r
679 or eax,dword [uninitialized_length+4]
\r
680 jnz write_uninitialized_data
\r
681 write_initialized_data:
\r
682 mov edx,[esi+OutputArea.definition]
\r
683 mov eax,[edx+ValueDefinition.value]
\r
684 mov ecx,[edx+ValueDefinition.value_length]
\r
685 mov edx,[eax+AreaHeader.base_address_length]
\r
686 add edx,sizeof.AreaHeader
\r
690 jc file_write_failed
\r
692 mov edx,[esi+OutputArea.definition]
\r
693 mov eax,[edx+ValueDefinition.value]
\r
694 mov eax,[eax+AreaHeader.uninitialized_length]
\r
695 add dword [uninitialized_length],eax
\r
696 adc dword [uninitialized_length+4],0
\r
697 cmp esi,[current_output_area_entry]
\r
698 je close_output_file
\r
699 add esi,sizeof.OutputArea
\r
703 mov ebx,[auxiliary_output_areas]
\r
704 mov edi,write_auxiliary_output_area
\r
705 call iterate_through_map
\r
706 cmp [output_failures],0
\r
707 jne output_write_failed
\r
712 output_write_failed:
\r
716 write_auxiliary_output_area:
\r
718 ; eax = ValueDefinition, null for cached extension not used for auxiliary output
\r
719 ; esi - file extension
\r
720 ; ecx = length of the extension
\r
722 jz auxiliary_output_processed
\r
723 mov ebx,[base_path]
\r
725 jz auxiliary_output_processed
\r
727 call create_output_path
\r
730 jc auxiliary_file_creation_failed
\r
731 mov eax,[edx+ValueDefinition.value]
\r
732 mov ecx,[edx+ValueDefinition.value_length]
\r
733 mov edx,[eax+AreaHeader.base_address_length]
\r
734 add edx,sizeof.AreaHeader
\r
738 jc auxiliary_file_write_failed
\r
740 auxiliary_output_processed:
\r
742 auxiliary_file_write_failed:
\r
744 auxiliary_file_creation_failed:
\r
745 inc [output_failures]
\r