initial commit: a mess of assembly code
[fmap.git] / x86_64_sse2_x87 / fasm / examples / x86 / include / format / pe.inc
blob40d812f2f217edc422bcf0a4ed39aa5466706278
1 \r
2 IMAGE_FILE_MACHINE_UNKNOWN   = 0x0\r
3 IMAGE_FILE_MACHINE_AM33      = 0x1D3\r
4 IMAGE_FILE_MACHINE_AMD64     = 0x8664\r
5 IMAGE_FILE_MACHINE_ARM       = 0x1C0\r
6 IMAGE_FILE_MACHINE_ARMNT     = 0x1C4\r
7 IMAGE_FILE_MACHINE_ARM64     = 0xAA64\r
8 IMAGE_FILE_MACHINE_EBC       = 0xEBC\r
9 IMAGE_FILE_MACHINE_I386      = 0x14C\r
10 IMAGE_FILE_MACHINE_IA64      = 0x200\r
11 IMAGE_FILE_MACHINE_M32R      = 0x9041\r
12 IMAGE_FILE_MACHINE_MIPS16    = 0x266\r
13 IMAGE_FILE_MACHINE_MIPSFPU   = 0x366\r
14 IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466\r
15 IMAGE_FILE_MACHINE_POWERPC   = 0x1F0\r
16 IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1\r
17 IMAGE_FILE_MACHINE_R4000     = 0x166\r
18 IMAGE_FILE_MACHINE_SH3       = 0x1A2\r
19 IMAGE_FILE_MACHINE_SH3DSP    = 0x1A3\r
20 IMAGE_FILE_MACHINE_SH4       = 0x1A6\r
21 IMAGE_FILE_MACHINE_SH5       = 0x1A8\r
22 IMAGE_FILE_MACHINE_THUMB     = 0x1C2\r
23 IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169\r
25 IMAGE_FILE_RELOCS_STRIPPED          = 0x0001\r
26 IMAGE_FILE_EXECUTABLE_IMAGE         = 0x0002\r
27 IMAGE_FILE_LINE_NUMS_STRIPPED       = 0x0004\r
28 IMAGE_FILE_LOCAL_SYMS_STRIPPED      = 0x0008\r
29 IMAGE_FILE_AGGRESSIVE_WS_TRIM       = 0x0010\r
30 IMAGE_FILE_LARGE_ADDRESS_AWARE      = 0x0020\r
31 IMAGE_FILE_BYTES_REVERSED_LO        = 0x0080\r
32 IMAGE_FILE_32BIT_MACHINE            = 0x0100\r
33 IMAGE_FILE_DEBUG_STRIPPED           = 0x0200\r
34 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP  = 0x0400\r
35 IMAGE_FILE_NET_RUN_FROM_SWAP        = 0x0800\r
36 IMAGE_FILE_SYSTEM                   = 0x1000\r
37 IMAGE_FILE_DLL                      = 0x2000\r
38 IMAGE_FILE_UP_SYSTEM_ONLY           = 0x4000\r
39 IMAGE_FILE_BYTES_REVERSED_HI        = 0x8000\r
41 IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA       = 0x0020\r
42 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE          = 0x0040\r
43 IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY       = 0x0080\r
44 IMAGE_DLLCHARACTERISTICS_NX_COMPAT             = 0x0100\r
45 IMAGE_DLLCHARACTERISTICS_NO_ISOLATION          = 0x0200\r
46 IMAGE_DLLCHARACTERISTICS_NO_SEH                = 0x0400\r
47 IMAGE_DLLCHARACTERISTICS_NO_BIND               = 0x0800\r
48 IMAGE_DLLCHARACTERISTICS_APPCONTAINER          = 0x1000\r
49 IMAGE_DLLCHARACTERISTICS_WDM_DRIVER            = 0x2000\r
50 IMAGE_DLLCHARACTERISTICS_GUARD_CF              = 0x4000\r
51 IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000\r
53 IMAGE_SUBSYSTEM_UNKNOWN                 = 0\r
54 IMAGE_SUBSYSTEM_NATIVE                  = 1\r
55 IMAGE_SUBSYSTEM_WINDOWS_GUI             = 2\r
56 IMAGE_SUBSYSTEM_WINDOWS_CUI             = 3\r
57 IMAGE_SUBSYSTEM_POSIX_CUI               = 7\r
58 IMAGE_SUBSYSTEM_WINDOWS_CE_GUI          = 9\r
59 IMAGE_SUBSYSTEM_EFI_APPLICATION         = 10\r
60 IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11\r
61 IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      = 12\r
62 IMAGE_SUBSYSTEM_EFI_ROM                 = 13\r
63 IMAGE_SUBSYSTEM_XBOX                    = 14\r
65 IMAGE_SCN_TYPE_NO_PAD            = 0x00000008\r
66 IMAGE_SCN_CNT_CODE               = 0x00000020\r
67 IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040\r
68 IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080\r
69 IMAGE_SCN_LNK_OTHER              = 0x00000100\r
70 IMAGE_SCN_LNK_INFO               = 0x00000200\r
71 IMAGE_SCN_LNK_REMOVE             = 0x00000800\r
72 IMAGE_SCN_LNK_COMDAT             = 0x00001000\r
73 IMAGE_SCN_GPREL                  = 0x00008000\r
74 IMAGE_SCN_MEM_PURGEABLE          = 0x00020000\r
75 IMAGE_SCN_MEM_16BIT              = 0x00020000\r
76 IMAGE_SCN_MEM_LOCKED             = 0x00040000\r
77 IMAGE_SCN_MEM_PRELOAD            = 0x00080000\r
78 IMAGE_SCN_ALIGN_1BYTES           = 0x00100000\r
79 IMAGE_SCN_ALIGN_2BYTES           = 0x00200000\r
80 IMAGE_SCN_ALIGN_4BYTES           = 0x00300000\r
81 IMAGE_SCN_ALIGN_8BYTES           = 0x00400000\r
82 IMAGE_SCN_ALIGN_16BYTES          = 0x00500000\r
83 IMAGE_SCN_ALIGN_32BYTES          = 0x00600000\r
84 IMAGE_SCN_ALIGN_64BYTES          = 0x00700000\r
85 IMAGE_SCN_ALIGN_128BYTES         = 0x00800000\r
86 IMAGE_SCN_ALIGN_256BYTES         = 0x00900000\r
87 IMAGE_SCN_ALIGN_512BYTES         = 0x00A00000\r
88 IMAGE_SCN_ALIGN_1024BYTES        = 0x00B00000\r
89 IMAGE_SCN_ALIGN_2048BYTES        = 0x00C00000\r
90 IMAGE_SCN_ALIGN_4096BYTES        = 0x00D00000\r
91 IMAGE_SCN_ALIGN_8192BYTES        = 0x00E00000\r
92 IMAGE_SCN_LNK_NRELOC_OVFL        = 0x01000000\r
93 IMAGE_SCN_MEM_DISCARDABLE        = 0x02000000\r
94 IMAGE_SCN_MEM_NOT_CACHED         = 0x04000000\r
95 IMAGE_SCN_MEM_NOT_PAGED          = 0x08000000\r
96 IMAGE_SCN_MEM_SHARED             = 0x10000000\r
97 IMAGE_SCN_MEM_EXECUTE            = 0x20000000\r
98 IMAGE_SCN_MEM_READ               = 0x40000000\r
99 IMAGE_SCN_MEM_WRITE              = 0x80000000\r
101 IMAGE_REL_BASED_ABSOLUTE = 0\r
102 IMAGE_REL_BASED_HIGH     = 1\r
103 IMAGE_REL_BASED_LOW      = 2\r
104 IMAGE_REL_BASED_HIGHLOW  = 3\r
105 IMAGE_REL_BASED_HIGHADJ  = 4\r
106 IMAGE_REL_BASED_DIR64    = 10\r
108 calminstruction align? boundary,value:?\r
109         check   $ relativeto 0 | ( $ relativeto PE.RELOCATION & PE.SECTION_ALIGNMENT mod boundary = 0 )\r
110         jyes    allowed\r
111         arrange value, =err 'section not aligned enough'\r
112         assemble value\r
113         exit\r
114     allowed:\r
115         compute boundary, (boundary-1)-((0 scaleof $)+boundary-1) mod boundary\r
116         arrange value, =db boundary =dup value\r
117         assemble value\r
118 end calminstruction\r
120 PE::\r
122 namespace PE\r
124         if defined Settings.Magic\r
125                 MAGIC = Settings.Magic\r
126         else\r
127                 MAGIC = 0x10B\r
128         end if\r
130         if defined Settings.Machine\r
131                 MACHINE = Settings.Machine\r
132         else\r
133                 MACHINE = IMAGE_FILE_MACHINE_I386\r
134         end if\r
136         if defined Settings.Characteristics\r
137                 CHARACTERISTICS = Settings.Characteristics\r
138         else\r
139                 CHARACTERISTICS = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE\r
140         end if\r
142         if defined Settings.DllCharacteristics\r
143                 DLL_CHARACTERISTICS = Settings.DllCharacteristics\r
144         else\r
145                 DLL_CHARACTERISTICS = 0\r
146         end if\r
148         if defined Settings.Subsystem\r
149                 SUBSYSTEM = Settings.Subsystem\r
150         else\r
151                 SUBSYSTEM = IMAGE_SUBSYSTEM_WINDOWS_CUI\r
152         end if\r
154         if defined Settings.MajorSubsystemVersion\r
155                 MAJOR_SUBSYSTEM_VERSION = Settings.MajorSubsystemVersion\r
156         else\r
157                 MAJOR_SUBSYSTEM_VERSION = 3\r
158         end if\r
160         if defined Settings.MinorSubsystemVersion\r
161                 MINOR_SUBSYSTEM_VERSION = Settings.MinorSubsystemVersion\r
162         else\r
163                 MINOR_SUBSYSTEM_VERSION = 10\r
164         end if\r
166         if defined Fixups\r
167                 element RELOCATION\r
168                 DLL_CHARACTERISTICS = DLL_CHARACTERISTICS or IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE\r
169         else\r
170                 RELOCATION := 0\r
171                 CHARACTERISTICS = CHARACTERISTICS or IMAGE_FILE_RELOCS_STRIPPED\r
172         end if\r
174         if defined Settings.ImageBase\r
175                 IMAGE_BASE := RELOCATION + Settings.ImageBase\r
176         else\r
177                 IMAGE_BASE := RELOCATION + 400000h\r
178         end if\r
180         if defined Settings.SectionAlignment\r
181                 SECTION_ALIGNMENT := Settings.SectionAlignment\r
182         else\r
183                 SECTION_ALIGNMENT := 1000h\r
184         end if\r
186         if defined Settings.FileAlignment\r
187                 FILE_ALIGNMENT := Settings.FileAlignment\r
188         else\r
189                 FILE_ALIGNMENT := 512\r
190         end if\r
192         if defined Settings.LegacyHeaders\r
193                 LEGACY_HEADERS := Settings.LegacyHeaders\r
194         else\r
195                 LEGACY_HEADERS := 1\r
196         end if\r
198         NUMBER_OF_DIRECTORIES := 16\r
200         if defined Settings.Stub\r
202                 virtual at 0\r
203                         file Settings.Stub\r
204                         if $ >= 1Ch\r
205                                 load SIGNATURE : word from 0\r
206                                 if SIGNATURE = "MZ" | SIGNATURE = "ZM"\r
207                                         StubTemplate::\r
208                                 end if\r
209                         end if\r
210                 end virtual\r
212                 if defined StubTemplate\r
214                         load .BYTES_IN_LAST_PAGE : word from StubTemplate:2\r
215                         load .NUMBER_OF_PAGES : word from StubTemplate:4\r
216                         .TEMPLATE_LENGTH = .NUMBER_OF_PAGES shl 9 - (-.BYTES_IN_LAST_PAGE) and 1FFh\r
218                         load .RELOCATIONS_OFFSET : word from StubTemplate:18h\r
219                         if .RELOCATIONS_OFFSET >= 40h\r
220                                 file Settings.Stub,.TEMPLATE_LENGTH\r
221                         else\r
222                                 load .NUMBER_OF_RELOCATIONS : word from StubTemplate:6\r
223                                 .RELOCATIONS_LENGTH = .NUMBER_OF_RELOCATIONS shl 2\r
224                                 load .NUMBER_OF_HEADER_PARAGRAPHS : word from StubTemplate:8\r
225                                 .TEMPLATE_HEADER_LENGTH = .NUMBER_OF_HEADER_PARAGRAPHS shl 4\r
227                                 file Settings.Stub,1Ch\r
228                                 rb 40h - $\r
229                                 file Settings.Stub:.RELOCATIONS_OFFSET,.RELOCATIONS_LENGTH\r
230                                 align 16\r
231                                 .HEADER_LENGTH = $\r
232                                 file Settings.Stub:.TEMPLATE_HEADER_LENGTH,.TEMPLATE_LENGTH-.TEMPLATE_HEADER_LENGTH\r
233                                 .LENGTH = $\r
235                                 store 40h : word at 18h\r
236                                 store .HEADER_LENGTH shr 4 : word at 8\r
237                                 store .LENGTH and 1FFh : word at 2\r
238                                 store (.LENGTH-1) shr 9 + 1 : word at 4\r
239                         end if\r
241                         store Header : dword at 3Ch\r
243                 else\r
245                         Stub:\r
246                         .signature                     dw "MZ"\r
247                         .bytes_in_last_page            dw .LENGTH and 1FFh\r
248                         .number_of_pages               dw (.LENGTH-1) shr 9 + 1\r
249                         .number_of_relocations         dw 0\r
250                         .number_of_header_paragraphs   dw .HEADER_LENGTH shr 4\r
251                         .minimum_heap                  dw (10000h - (.LENGTH-.HEADER_LENGTH)) shr 4\r
252                         .maximum_heap                  dw 0FFFFh\r
253                         .initial_ss                    dw (-100h) shr 4\r
254                         .initial_sp                    dw 0FFFEh\r
255                         .checksum                      dw 0\r
256                         .initial_ip                    dw 100h\r
257                         .initial_cs                    dw (-100h) shr 4\r
258                         .relocations_offset            dw 40h\r
259                         .overlay_number                dw 0\r
260                                                        rb 3Ch - $\r
261                         .new_header_offset             dd Header\r
263                         .HEADER_LENGTH = $\r
265                         file Settings.Stub\r
267                         .LENGTH = $\r
269                 end if\r
271         else\r
273                 Stub:\r
274                 .signature                     dw "MZ"\r
275                 .bytes_in_last_page            dw .LENGTH and 1FFh\r
276                 .number_of_pages               dw (.LENGTH-1) shr 9 + 1\r
277                 .number_of_relocations         dw 0\r
278                 .number_of_header_paragraphs   dw .HEADER_LENGTH shr 4\r
279                 .minimum_heap                  dw .STACK_LENGTH shr 4\r
280                 .maximum_heap                  dw 0FFFFh\r
281                 .initial_ss                    dw 0\r
282                 .initial_sp                    dw .LENGTH - .HEADER_LENGTH + .STACK_LENGTH\r
283                 .checksum                      dw 0\r
284                 .initial_ip                    dw 0\r
285                 .initial_cs                    dw 0\r
286                 .relocations_offset            dw 40h\r
287                 .overlay_number                dw 0\r
288                                                rb 3Ch - $\r
289                 .new_header_offset             dd Header\r
291                 .HEADER_LENGTH = $\r
292                 .STACK_LENGTH = 100h\r
294                 namespace Stub\r
296                       include '../8086.inc'\r
298                 start:\r
299                       push    cs\r
300                       pop     ds\r
301                       mov     dx,message - start\r
302                       mov     ah,9\r
303                       int     21h\r
304                       mov     ax,4C01h\r
305                       int     21h\r
307                 message db 'This program cannot be run in DOS mode.',0Dh,0Ah,24h\r
309                 end namespace\r
311                 align 16\r
313                 .LENGTH = $\r
315         end if\r
317         if defined Settings.Stamp\r
318                 TIMESTAMP := Settings.Stamp\r
319         else\r
320                 TIMESTAMP := __TIME__\r
321         end if\r
323         align 8\r
325         Header:\r
326         .Signature                    dw "PE",0\r
327         .Machine                      dw MACHINE\r
328         .NumberOfSections             dw NUMBER_OF_SECTIONS\r
329         .TimeDateStamp                dd TIMESTAMP\r
330         .PointerToSymbolTable         dd 0\r
331         .NumberOfSymbols              dd 0\r
332         .SizeOfOptionalHeader         dw SectionTable - OptionalHeader\r
333         .Characteristics              dw CHARACTERISTICS\r
335         OptionalHeader:\r
336         .Magic                        dw MAGIC\r
337         .MajorLinkerVersion           db 0\r
338         .MinorLinkerVersion           db 0\r
339         .SizeOfCode                   dd 0\r
340         .SizeOfInitializedData        dd 0\r
341         .SizeOfUninitializedData      dd 0\r
342         .AddressOfEntryPoint          dd 0\r
343         .BaseOfCode                   dd 0\r
344         if MAGIC <> 0x20B\r
345          .BaseOfData                  dd 0\r
346          .ImageBase                   dd IMAGE_BASE - RELOCATION\r
347         else\r
348          .ImageBase                   dq IMAGE_BASE - RELOCATION\r
349         end if\r
350         .SectionAlignment             dd SECTION_ALIGNMENT\r
351         .FileAlignment                dd FILE_ALIGNMENT\r
352         .MajorOperatingSystemVersion  dw 1\r
353         .MinorOperatingSystemVersion  dw 0\r
354         .MajorImageVersion            dw 0\r
355         .MinorImageVersion            dw 0\r
356         .MajorSubsystemVersion        dw MAJOR_SUBSYSTEM_VERSION\r
357         .MinorSubsystemVersion        dw MINOR_SUBSYSTEM_VERSION\r
358         .Win32VersionValue            dd 0\r
359         .SizeOfImage                  dd SIZE_OF_IMAGE\r
360         .SizeOfHeaders                dd SIZE_OF_HEADERS\r
361         .CheckSum                     dd 0\r
362         .Subsystem                    dw SUBSYSTEM\r
363         .DllCharacteristics           dw DLL_CHARACTERISTICS\r
364         if MAGIC <> 0x20B\r
365          .SizeOfStackReserve          dd 1000h\r
366          .SizeOfStackCommit           dd 1000h\r
367          .SizeOfHeapReserve           dd 10000h\r
368          .SizeOfHeapCommit            dd 0\r
369         else\r
370          .SizeOfStackReserve          dq 1000h\r
371          .SizeOfStackCommit           dq 1000h\r
372          .SizeOfHeapReserve           dq 10000h\r
373          .SizeOfHeapCommit            dq 0\r
374         end if\r
375         .LoaderFlags                  dd 0\r
376         .NumberOfRvaAndSizes          dd NUMBER_OF_DIRECTORIES\r
377         RvaAndSizes:\r
378         .Rva                          dd 0\r
379         .Size                         dd 0\r
380         .ENTRY_LENGTH = $ - RvaAndSizes\r
381                                       db (NUMBER_OF_DIRECTORIES-1)*RvaAndSizes.ENTRY_LENGTH dup 0\r
382         SectionTable:\r
383         .Name                         dq '.flat'\r
384         .VirtualSize                  dd 0\r
385         .VirtualAddress               dd 0\r
386         .SizeOfRawData                dd 0\r
387         .PointerToRawData             dd 0\r
388         .PointerToRelocations         dd 0\r
389         .PointerToLineNumbers         dd 0\r
390         .NumberOfRelocations          dw 0\r
391         .NumberOfLineNumbers          dw 0\r
392         .Characteristics              dd IMAGE_SCN_MEM_EXECUTE + IMAGE_SCN_MEM_READ + IMAGE_SCN_MEM_WRITE\r
393         .ENTRY_LENGTH = $ - SectionTable\r
394                                       db (NUMBER_OF_SECTIONS-1)*SectionTable.ENTRY_LENGTH dup 0\r
396         HeadersEnd:\r
397         define CheckSumBlocks PE,0,HeadersEnd\r
399         SECTION_INDEX = 0\r
400         RELOCATION_INDEX = 0\r
401         DEFINED_SECTION = 0\r
402         SECTION_DIRECTORIES = 0\r
403         align SECTION_ALIGNMENT\r
404         FIRST_SECTION_RVA:\r
405         section $%%\r
406         align FILE_ALIGNMENT,0\r
407         SIZE_OF_HEADERS = $%\r
408         FILE_OFFSET = $%\r
409         SECTION_BASE = IMAGE_BASE + FIRST_SECTION_RVA\r
410         org SECTION_BASE\r
412         store SECTION_BASE-IMAGE_BASE at PE:OptionalHeader.AddressOfEntryPoint\r
413         store SECTION_BASE-IMAGE_BASE at PE:SectionTable.VirtualAddress\r
414         store FILE_OFFSET at PE:SectionTable.PointerToRawData\r
416         virtual at 0\r
417              relocated_addresses:: rd NUMBER_OF_RELOCATIONS\r
418         end virtual\r
420         virtual at 0\r
421              relocation_types:: rw NUMBER_OF_RELOCATIONS\r
422         end virtual\r
424 end namespace\r
426 RVA? equ -PE.IMAGE_BASE +\r
428 macro entry? address*\r
429         namespace PE\r
430                 store address-IMAGE_BASE at PE:OptionalHeader.AddressOfEntryPoint\r
431         end namespace\r
432 end macro\r
434 macro stack? reserve*,commit:1000h\r
435         namespace PE\r
436                 store reserve at PE:OptionalHeader.SizeOfStackReserve\r
437                 store commit at PE:OptionalHeader.SizeOfStackCommit\r
438         end namespace\r
439 end macro\r
441 macro heap? reserve*,commit:0\r
442         namespace PE\r
443                 store reserve at PE:OptionalHeader.SizeOfHeapReserve\r
444                 store commit at PE:OptionalHeader.SizeOfHeapCommit\r
445         end namespace\r
446 end macro\r
448 calminstruction calminstruction?.init? var*, val:0\r
449         compute val, val\r
450         publish var, val\r
451 end calminstruction\r
453 calminstruction calminstruction?.initsym? var*, val&\r
454         publish var, val\r
455 end calminstruction\r
457 calminstruction calminstruction?.unique? name\r
458         local counter, buffer\r
459         init counter\r
460         compute counter, counter + 1\r
461         arrange buffer, name#counter\r
462         publish name, buffer\r
463 end calminstruction\r
465 calminstruction calminstruction?.asm? line&\r
466         local tmp, ln, buffer\r
467         initsym tmp, unique ln\r
468         assemble tmp\r
469         publish ln, line\r
470         arrange buffer, =assemble ln\r
471         assemble buffer\r
472 end calminstruction\r
474 macro section?\r
475         namespace PE\r
477                 repeat SECTION_DIRECTORIES\r
478                         end data\r
479                 end repeat\r
481                 local AREA,DATA_START,DATA_END\r
482                 AREA::\r
483                 DATA_START = $$\r
484                 DATA_END = $-($%-$%%)\r
485                 CheckSumBlocks reequ CheckSumBlocks,AREA,DATA_START,DATA_END\r
487                 SECTION_SIZE = $ - SECTION_BASE\r
488                 store SECTION_SIZE at PE:SectionTable.VirtualSize+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
489                 align SECTION_ALIGNMENT\r
490                 SECTION_BASE = $\r
491                 section $%%\r
492                 align FILE_ALIGNMENT,0\r
493                 RAW_DATA_SIZE = $% - FILE_OFFSET\r
494                 store RAW_DATA_SIZE at PE:SectionTable.SizeOfRawData+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
495                 FILE_OFFSET = $%\r
496                 org SECTION_BASE\r
498                 load SECTION_CHARACTERISTICS from PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
499                 if SECTION_SIZE > 0 & RAW_DATA_SIZE = 0\r
500                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_UNINITIALIZED_DATA\r
501                         store SECTION_CHARACTERISTICS at PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
502                 end if\r
504                 if LEGACY_HEADERS\r
505                         if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_CODE & RAW_DATA_SIZE > 0\r
506                                 load CODE_SIZE from PE:OptionalHeader.SizeOfCode\r
507                                 if CODE_SIZE = 0\r
508                                         load CODE_BASE from PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
509                                         store CODE_BASE at PE:OptionalHeader.BaseOfCode\r
510                                 end if\r
511                                 CODE_SIZE = CODE_SIZE + RAW_DATA_SIZE\r
512                                 store CODE_SIZE at PE:OptionalHeader.SizeOfCode\r
513                         end if\r
514                         if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_INITIALIZED_DATA & RAW_DATA_SIZE > 0\r
515                                 load DATA_SIZE from PE:OptionalHeader.SizeOfInitializedData\r
516                                 if DATA_SIZE = 0 & MAGIC <> 0x20B\r
517                                         load DATA_BASE from PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
518                                         store DATA_BASE at PE:OptionalHeader.BaseOfData\r
519                                 end if\r
520                                 DATA_SIZE = DATA_SIZE + RAW_DATA_SIZE\r
521                                 store DATA_SIZE at PE:OptionalHeader.SizeOfInitializedData\r
522                         end if\r
523                         if SECTION_CHARACTERISTICS and IMAGE_SCN_CNT_UNINITIALIZED_DATA\r
524                                 load BSS_SIZE from PE:OptionalHeader.SizeOfUninitializedData\r
525                                 BSS_SIZE = BSS_SIZE + SECTION_SIZE\r
526                                 store BSS_SIZE at PE:OptionalHeader.SizeOfUninitializedData\r
527                         end if\r
528                 end if\r
530                 if DEFINED_SECTION | SECTION_SIZE > 0\r
531                         SECTION_INDEX = SECTION_INDEX + 1\r
532                 end if\r
534         end namespace\r
535 end macro\r
537 macro section? declaration*\r
538         namespace PE\r
540                 section\r
542                 DEFINED_SECTION = 1\r
544                 store SECTION_BASE-IMAGE_BASE at PE:SectionTable.VirtualAddress+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
545                 store FILE_OFFSET at PE:SectionTable.PointerToRawData+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
547                 SECTION_DIRECTORIES = 0\r
549                 match name attributes, declaration\r
551                         store name:qword at PE:SectionTable.Name+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
553                         SECTION_CHARACTERISTICS = 0\r
555                         local seq\r
556                         define seq attributes:\r
557                         while 1\r
558                                 match :, seq\r
559                                         break\r
560                                 else match =readable? tail, seq\r
561                                         redefine seq tail\r
562                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_READ\r
563                                 else match =writeable? tail, seq\r
564                                         redefine seq tail\r
565                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_WRITE\r
566                                 else match =writable? tail, seq\r
567                                         redefine seq tail\r
568                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_WRITE\r
569                                 else match =executable? tail, seq\r
570                                         redefine seq tail\r
571                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_EXECUTE\r
572                                 else match =discardable? tail, seq\r
573                                         redefine seq tail\r
574                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_DISCARDABLE\r
575                                 else match =shareable? tail, seq\r
576                                         redefine seq tail\r
577                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_MEM_SHARED\r
578                                 else match =import? tail, seq\r
579                                         redefine seq tail\r
580                                         SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1\r
581                                         data import\r
582                                 else match =export? tail, seq\r
583                                         redefine seq tail\r
584                                         SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1\r
585                                         data export\r
586                                 else match =resource? =from? path tail, seq\r
587                                         redefine seq tail\r
588                                         SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1\r
589                                         data resource from path\r
590                                 else match =resource? tail, seq\r
591                                         redefine seq tail\r
592                                         SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1\r
593                                         data resource\r
594                                 else match =fixups? tail, seq\r
595                                         redefine seq tail\r
596                                         SECTION_DIRECTORIES = SECTION_DIRECTORIES + 1\r
597                                         data fixups\r
598                                 else match =code? tail, seq\r
599                                         redefine seq tail\r
600                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_CODE\r
601                                 else match =data? tail, seq\r
602                                         redefine seq tail\r
603                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_INITIALIZED_DATA\r
604                                 else match =udata? tail, seq\r
605                                         redefine seq tail\r
606                                         SECTION_CHARACTERISTICS = SECTION_CHARACTERISTICS or IMAGE_SCN_CNT_UNINITIALIZED_DATA\r
607                                 else match attribute tail, seq\r
608                                         err 'unknown attribute "',`attribute,'"'\r
609                                         redefine seq :\r
610                                 end match\r
611                         end while\r
613                         store SECTION_CHARACTERISTICS at PE:SectionTable.Characteristics+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
614                 else\r
616                         store declaration:qword at PE:SectionTable.Name+SECTION_INDEX*SectionTable.ENTRY_LENGTH\r
618                 end match\r
620         end namespace\r
621 end macro\r
623 macro data? type*\r
624         namespace PE\r
625                 local number,content\r
626                 define content\r
627                 match =export?, type\r
628                         number = 0\r
629                 else match =import?, type\r
630                         number = 1\r
631                 else match =resource? =from? path, type\r
632                         number = 2\r
633                         define content resource_from path\r
634                 else match =resource?, type\r
635                         number = 2\r
636                 else match =fixups?, type\r
637                         number = 5\r
638                         define content fixups\r
639                 else\r
640                         number = type\r
641                 end match\r
642                 define DATA_DIRECTORY number\r
643                 load DATA_BASE:dword from PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH\r
644                 if DATA_BASE = 0\r
645                         store $-IMAGE_BASE:dword at PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH\r
646                         match instruction, content\r
647                                 instruction\r
648                         end match\r
649                 else\r
650                         err 'data already defined'\r
651                 end if\r
652         end namespace\r
653 end macro\r
655 macro end?.data?\r
656         namespace PE\r
657                 load DATA_BASE:dword from PE:RvaAndSizes.Rva+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH\r
658                 store $-IMAGE_BASE-DATA_BASE:dword at PE:RvaAndSizes.Size+DATA_DIRECTORY*RvaAndSizes.ENTRY_LENGTH\r
659                 restore DATA_DIRECTORY\r
660         end namespace\r
661 end macro\r
663 macro PE.resource_directory?\r
664         namespace PE\r
665                 Resource: rb RESOURCE_HEADERS_LENGTH\r
666                 Resource.counter = 0\r
667                 define RESOURCE_DIRECTORIES_LIST Resource_root\r
668                 Resource_root.counter = 0\r
669         end namespace\r
670 end macro\r
672 macro PE.resource_data? type*,id*,lang*,codepage:0\r
673         namespace PE\r
674                 local _type,_id,_lang\r
675                 _type = type\r
676                 _id = id\r
677                 _lang = lang\r
678                 if ~ type eqtype 0\r
679                         _type = _type shl 32\r
680                 end if\r
681                 if ~ id eqtype 0\r
682                         _id = id shl 32\r
683                 end if\r
684                 if ~ lang eqtype 0\r
685                         _lang = lang shl 32\r
686                 end if\r
687                 repeat 1, %type:_type, %id:_id, %lang:_lang\r
688                         if ~ defined Resource_#%type#_#%id.counter\r
689                                 if ~ defined Resource_#%type.counter\r
690                                         repeat 1, i:Resource_root.counter\r
691                                                 Resource_root.entry#i = type\r
692                                                 Resource_root.offset#i =  (Resource_#%type - Resource) or 80000000h\r
693                                         end repeat\r
694                                         Resource_root.counter = Resource_root.counter + 1\r
695                                         match list, RESOURCE_DIRECTORIES_LIST\r
696                                                 define RESOURCE_DIRECTORIES_LIST list,Resource_#%type\r
697                                         end match\r
698                                         Resource_#%type.counter = 0\r
699                                 end if\r
700                                 repeat 1, i:Resource_#%type.counter\r
701                                         Resource_#%type.entry#i = id\r
702                                         Resource_#%type.offset#i =  (Resource_#%type#_#%id - Resource) or 80000000h\r
703                                 end repeat\r
704                                 Resource_#%type.counter = Resource_#%type.counter + 1\r
706                                 match list, RESOURCE_DIRECTORIES_LIST\r
707                                         define RESOURCE_DIRECTORIES_LIST list,Resource_#%type#_#%id\r
708                                 end match\r
709                                 Resource_#%type#_#%id.counter = 0\r
710                         end if\r
711                         repeat 1, i:Resource_#%type#_#%id.counter\r
712                                 Resource_#%type#_#%id.entry#i = lang\r
713                                 Resource_#%type#_#%id.offset#i = Resource_#%type#_#%id#_#%lang - Resource\r
714                         end repeat\r
715                         Resource_#%type#_#%id.counter = Resource_#%type#_#%id.counter + 1\r
716                         repeat 1, i:Resource.counter\r
717                                 Resource_#%type#_#%id#_#%lang := Resource.entry#i\r
718                                 Resource.cp#i := codepage\r
719                                 Resource.data#i:\r
720                         end repeat\r
721                 end repeat\r
722         end namespace\r
723 end macro\r
725 macro PE.end_resource_data?\r
726         namespace PE\r
727                 repeat 1, i:Resource.counter\r
728                         Resource.size#i := $ - Resource.data#i\r
729                 end repeat\r
730                 Resource.counter = Resource.counter + 1\r
731                 align 4\r
732         end namespace\r
733 end macro\r
735 macro PE.end_resource_directory?\r
736        namespace PE\r
737                 RESOURCE_HEADERS_POINTER = 0\r
739                 match list, RESOURCE_DIRECTORIES_LIST\r
740                         iterate dir, list\r
741                                 dir := Resource + RESOURCE_HEADERS_POINTER\r
742                                 RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16 + dir.counter * 8\r
743                                 local x,y,z,a,b\r
744                                 x = dir.counter shr 1\r
745                                 while x > 0\r
746                                         y = x\r
747                                         while y < dir.counter\r
748                                                 z = y\r
749                                                 while z-x >= 0\r
750                                                         repeat 1, i:z, j:z-x\r
751                                                                 if dir.entry#i eqtype 0\r
752                                                                         if ~ dir.entry#j eqtype 0 | dir.entry#i >= dir.entry#j\r
753                                                                                 z = 0\r
754                                                                         end if\r
755                                                                 else if ~ dir.entry#j eqtype 0\r
756                                                                         a = dir.entry#i bswap lengthof dir.entry#i\r
757                                                                         b = dir.entry#j bswap lengthof dir.entry#j\r
758                                                                         if ( lengthof a >= lengthof b & a shr ((lengthof a - lengthof b)*8) >= b ) | ( lengthof a < lengthof b & a > b shr ((lengthof b - lengthof a)*8) )\r
759                                                                                 z = 0\r
760                                                                         end if\r
761                                                                 end if\r
762                                                                 if z > 0\r
763                                                                         a = dir.entry#i\r
764                                                                         b = dir.offset#i\r
765                                                                         dir.entry#i = dir.entry#j\r
766                                                                         dir.offset#i = dir.offset#j\r
767                                                                         dir.entry#j = a\r
768                                                                         dir.offset#j = b\r
769                                                                         z = z - x\r
770                                                                 end if\r
771                                                         end repeat\r
772                                                 end while\r
773                                                 y = y + 1\r
774                                         end while\r
775                                         x = x shr 1\r
776                                 end while\r
777                         end iterate\r
778                         iterate dir, list\r
779                                 store __TIME__ : 4 at dir + 4\r
780                                 dir.names_counter = 0\r
781                                 repeat dir.counter, i:0\r
782                                         if dir.entry#i eqtype 0\r
783                                                 store dir.entry#i : 4 at dir + 16 + i * 8\r
784                                         else\r
785                                                 dir.names_counter = dir.names_counter + 1\r
786                                                 repeat 1, %id:dir.entry#i\r
787                                                         if ~ defined Resource_string#%id\r
788                                                                 restore Resource_string#%id\r
789                                                                 Resource_string#%id = Resource + RESOURCE_HEADERS_POINTER\r
790                                                                 if lengthof dir.entry#i and 1\r
791                                                                         err 'a word-aligned string is expected as a name'\r
792                                                                 end if\r
793                                                                 RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + lengthof dir.entry#i + 2\r
794                                                                 store (lengthof dir.entry#i)/2 : 2 at Resource_string#%id\r
795                                                                 store dir.entry#i : lengthof dir.entry#i at Resource_string#%id + 2\r
796                                                         end if\r
797                                                         store (Resource_string#%id - Resource) or 80000000h : 4 at dir + 16 + i * 8\r
798                                                 end repeat\r
799                                         end if\r
800                                         store dir.offset#i : 4 at dir + 16 + i * 8 + 4\r
801                                 end repeat\r
802                                 store dir.names_counter : 2 at dir + 12\r
803                                 store dir.counter - dir.names_counter : 2 at dir + 14\r
804                         end iterate\r
805                 end match\r
807                 if RESOURCE_HEADERS_POINTER and 11b\r
808                         RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 4 - RESOURCE_HEADERS_POINTER and 11b\r
809                 end if\r
811                 repeat Resource.counter, i:0\r
812                         Resource.entry#i := Resource + RESOURCE_HEADERS_POINTER\r
813                         RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16\r
814                         store RVA(Resource.data#i) : 4 at Resource.entry#i\r
815                         store Resource.size#i : 4 at Resource.entry#i + 4\r
816                         store Resource.cp#i : 4 at Resource.entry#i + 8\r
817                 end repeat\r
819                 RESOURCE_HEADERS_LENGTH = RESOURCE_HEADERS_POINTER\r
820         end namespace\r
821 end macro\r
823 macro PE.resource_from path*\r
825         local res_file,res_size,res_header_size,res_data_size,res_data\r
826         local offset,char,type,id,lang\r
828         virtual at 0\r
829                 res_file:: file path\r
830                 res_size := $\r
831         end virtual\r
833         PE.resource_directory\r
835                 offset = 0\r
836                 while offset < res_size\r
837                         load res_header_size : 4 from res_file : offset + 4\r
838                         load res_data_size : 4 from res_file : offset + 0\r
840                         if res_data_size > 0\r
842                                 offset =: offset + 8\r
843                                 load char : 2 from res_file : offset\r
844                                 if char = 0FFFFh\r
845                                         load char : 2 from res_file : offset + 2\r
846                                         type = +char\r
847                                         offset = offset + 4\r
848                                 else\r
849                                         while 1\r
850                                                 if char = 0\r
851                                                         load type : (%-1)*2 from res_file : offset\r
852                                                         offset = offset + (% + % and 1)*2\r
853                                                         break\r
854                                                 end if\r
855                                                 load char : 2 from res_file : offset + %*2\r
856                                         end while\r
857                                 end if\r
858                                 load char : 2 from res_file : offset\r
859                                 if char = 0FFFFh\r
860                                         load char : 2 from res_file : offset + 2\r
861                                         id = +char\r
862                                         offset = offset + 4\r
863                                 else\r
864                                         while 1\r
865                                                 if char = 0\r
866                                                         load id : (%-1)*2 from res_file : offset\r
867                                                         offset = offset + (% + % and 1)*2\r
868                                                         break\r
869                                                 end if\r
870                                                 load char : 2 from res_file : offset + %*2\r
871                                         end while\r
872                                 end if\r
873                                 load char : 2 from res_file : offset + 6\r
874                                 lang = +char\r
876                                 restore offset\r
878                                 PE.resource_data type,id,lang\r
879                                         load res_data : res_data_size from res_file : offset + res_header_size\r
880                                         db res_data\r
881                                 PE.end_resource_data\r
883                         end if\r
885                         offset = offset + res_header_size + res_data_size\r
886                         if offset and 11b\r
887                                 offset = offset + 4 - offset and 11b\r
888                         end if\r
889                 end while\r
891         PE.end_resource_directory\r
893 end macro\r
895 macro PE.fixups\r
896         namespace PE\r
897                 Fixups:\r
898                 calminstruction BuildFixups\r
899                         local   PAGE_RVA, BLOCK_HEADER, BLOCK_SIZE\r
900                         local   INDEX, ADDRESS, TYPE, FIXUP\r
901                         compute PAGE_RVA, -1\r
902                         compute BLOCK_HEADER, 0\r
903                         compute BLOCK_SIZE, 0\r
904                         compute INDEX,0\r
905                     process:\r
906                         check   INDEX = NUMBER_OF_RELOCATIONS\r
907                         jyes    close_block\r
908                         asm     load ADDRESS:4 from relocated_addresses:INDEX shl 2\r
909                         check   PAGE_RVA >= 0 & ADDRESS and not 0FFFh = PAGE_RVA\r
910                         jyes    append_to_block\r
911                     close_block:\r
912                         check   BLOCK_HEADER\r
913                         jno     start_new_block\r
914                         check   BLOCK_SIZE and 11b\r
915                         jno     finish_block\r
916                         asm     dw 0\r
917                         compute BLOCK_SIZE, BLOCK_SIZE + 2\r
918                     finish_block:\r
919                         asm     store BLOCK_SIZE:4 at BLOCK_HEADER+4\r
920                     start_new_block:\r
921                         check   INDEX = NUMBER_OF_RELOCATIONS\r
922                         jyes    done\r
923                         compute PAGE_RVA, ADDRESS and not 0FFFh\r
924                         compute BLOCK_HEADER, $\r
925                         asm     dd PAGE_RVA, 0\r
926                         compute BLOCK_SIZE, 8\r
927                     append_to_block:\r
928                         asm     load TYPE:2 from relocation_types:INDEX shl 1\r
929                         compute FIXUP, (ADDRESS and 0FFFh) or (TYPE shl 12)\r
930                         asm     dw FIXUP\r
931                         compute BLOCK_SIZE, BLOCK_SIZE + 2\r
932                         compute INDEX, INDEX + 1\r
933                         jump    process\r
934                     done:\r
935                 end calminstruction\r
936                 BuildFixups\r
937         end namespace\r
938 end macro\r
940 if defined PE.Fixups\r
942         calminstruction dword? value\r
943                 compute value, value\r
944                 check   value relativeto 0 | ~ value relativeto PE.RELOCATION\r
945                 jyes    plain\r
946                 local   offset\r
947                 compute offset, $%\r
948                 asm     emit 4: value - PE.RELOCATION\r
949                 check   $% > offset\r
950                 jno     done\r
951                 asm     store $-4-PE.IMAGE_BASE:4 at PE.relocated_addresses:PE.RELOCATION_INDEX shl 2\r
952                 asm     store IMAGE_REL_BASED_HIGHLOW:2 at PE.relocation_types:PE.RELOCATION_INDEX shl 1\r
953                 compute PE.RELOCATION_INDEX, PE.RELOCATION_INDEX + 1\r
954             done:\r
955                 exit\r
956             plain:\r
957                 asm     emit 4: value\r
958         end calminstruction\r
960         calminstruction qword? value\r
961                 compute value, value\r
962                 check   value relativeto 0 | ~ value relativeto PE.RELOCATION\r
963                 jyes    plain\r
964                 local   offset\r
965                 compute offset, $%\r
966                 asm     emit 8: value - PE.RELOCATION\r
967                 check   $% > offset\r
968                 jno     done\r
969                 asm     store $-8-PE.IMAGE_BASE:4 at PE.relocated_addresses:PE.RELOCATION_INDEX shl 2\r
970                 asm     store IMAGE_REL_BASED_DIR64:2 at PE.relocation_types:PE.RELOCATION_INDEX shl 1\r
971                 compute PE.RELOCATION_INDEX, PE.RELOCATION_INDEX + 1\r
972             done:\r
973                 exit\r
974             plain:\r
975                 asm     emit 8: value\r
976         end calminstruction\r
978         iterate <dd,dword>, dd,dword, dq,qword\r
980                 calminstruction dd? definitions&\r
981                         local   value, n\r
982                     start:\r
983                         match   value=,definitions, definitions, ()\r
984                         jyes    recognize\r
985                         match   value, definitions\r
986                         arrange definitions,\r
987                     recognize:\r
988                         match   n =dup? value, value, ()\r
989                         jyes    duplicate\r
990                         match   ?, value\r
991                         jyes    reserve\r
992                         arrange value, =dword value\r
993                         assemble value\r
994                     next:\r
995                         match   , definitions\r
996                         jno     start\r
997                         take    , definitions\r
998                         take    definitions, definitions\r
999                         jyes    next\r
1000                         exit\r
1001                     reserve:\r
1002                         arrange value, =dd ?\r
1003                         assemble value\r
1004                         jump    next\r
1005                     duplicate:\r
1006                         match   (value), value\r
1007                     stack:\r
1008                         check   n\r
1009                         jno     next\r
1010                         take    definitions, value\r
1011                         arrange value, definitions\r
1012                         compute n, n - 1\r
1013                         jump    stack\r
1014                 end calminstruction\r
1016                 calminstruction (label) dd? definitions&\r
1017                         local   cmd\r
1018                         arrange cmd, =label label : =dword\r
1019                         assemble cmd\r
1020                         arrange cmd, =dd definitions\r
1021                         assemble cmd\r
1022                 end calminstruction\r
1024         end iterate\r
1026 end if\r
1028 postpone\r
1029         purge section?\r
1030         section\r
1031         namespace PE\r
1032                 SIZE_OF_IMAGE := SECTION_BASE - IMAGE_BASE\r
1033                 NUMBER_OF_SECTIONS := SECTION_INDEX\r
1034                 NUMBER_OF_RELOCATIONS := RELOCATION_INDEX\r
1035         end namespace\r
1036 end postpone\r
1038 postpone ?\r
1039         namespace PE\r
1040                 CHECKSUM = 0\r
1042                 calminstruction CheckSum\r
1043                         local   AREA, DATA_START, DATA_END, POS, H\r
1044                     get_block:\r
1045                         match   AREA=,DATA_START=,DATA_END=,CheckSumBlocks, CheckSumBlocks\r
1046                         jyes    block_ready\r
1047                         match   AREA=,DATA_START=,DATA_END, CheckSumBlocks\r
1048                         jyes    last_block\r
1049                         exit\r
1050                     last_block:\r
1051                         arrange CheckSumBlocks,\r
1052                     block_ready:\r
1053                         compute POS, DATA_START\r
1054                     process_block:\r
1055                         check   POS + 2 <= DATA_END\r
1056                         jno     finish_block\r
1057                         asm     load H:2 from AREA:POS\r
1058                         compute CHECKSUM, CHECKSUM + H\r
1059                         compute POS, POS + 2\r
1060                         jump    process_block\r
1061                     finish_block:\r
1062                         check   POS + 1 = DATA_END\r
1063                         jno     reduce_checksum\r
1064                         asm     load H:1 from AREA:POS\r
1065                         compute CHECKSUM, CHECKSUM + H\r
1066                     reduce_checksum:\r
1067                         check   CHECKSUM shr 16\r
1068                         jno     get_block\r
1069                         compute CHECKSUM, CHECKSUM shr 16 + CHECKSUM and 0FFFFh\r
1070                         jump    reduce_checksum\r
1071                     done:\r
1072                 end calminstruction\r
1074                 CheckSum\r
1075                 CHECKSUM = CHECKSUM + $%\r
1076                 store CHECKSUM at PE:OptionalHeader.CheckSum\r
1077         end namespace\r
1078 end postpone\r