

'
'  ########    #########
'  ##     ##   ##
'  ##     ##   ##
'  ##     ##   ##
'  ########    ########
'  ##          ##
'  ##          ##
'  ##          ##
'  ##          #########
'

string dos_header="

`MZ`  90 00     ' 0000
03 00 00 00     ' 0004
04 00 00 00     ' 0008
FF FF 00 00     ' 000c
B8 00 00 00     ' 0010
00 00 00 00     ' 0014   
40 00 00 00     ' 0018 e_lfanew
$20             ' 001c '32 nulls
hle8            ' 003c 'e8 (cofo) was hl80
                '
0E 1F BA 0E     ' 0040
00 B4 09 CD     ' 0044
21 B8 01 4C     ' 0048
CD 21           ' 004c

`This program cannot be run in DOS mode.` 0d 0a 00

/e8 'e8 : adds 0x68 to all offsets (cofo) (was 80)

!end!
"

 
string pe_header="

'----------------------------
'IMAGE FILE HEADER (24 bytes)
'============================

`PE` 00 00     ' 0000  Signature: 00004550 'PE
hw014c         ' 0004  Machine:
               '       IMAGE_FILE_MACHINE_I386  014c
               '       IMAGE_FILE_MACHINE_AMD64 8664
hwSECT         ' 0006  no of sections:
hlDATETIME     ' 0008  DateTimeStamp: eg 489E0DEE
               '       Date & Time: 09/August/2008  22:36:46
hl0            ' 000C  Pointer to symbol table:
hl0            ' 0010  Number of symbols:
hw00e0         ' 0014  Size of Optional header: hw00e0 32bit hw00f0 64bit
hwLIBX         ' 0016  Characteristics: was 30e
               '       IMAGE_FILE_LINE_NUMS_STRIPPED
               '       IMAGE_FILE_LOCAL_SYMS_STRIPPED
               '       not IMAGE_FILE_32BIT_MACHINE
               '       IMAGE_FILE_DEBUG_STRIPPED
               '       IMAGE_FILE_DLL 0x2000
               '       'DLL=2102 EXE=0102


'WITH NOTES FOR PE32 / PE32+

'---------------------------------------
'`OPTIONAL` FILE HEADER (96 / 112 bytes)
'=======================================

'
'0X10B for PE32 / 0X20B for PE32+
'
hw0*0b 'MAGIC   ' 0018  magic: h010b for PE32, hw020b for PE32+
02              ' 001A  major linker version: 08 was 02 08
38              ' 001B  minor linker version: 00 was 38 00
hl0             ' 001C  Size of Code: to fill in
hl0             ' 0020  Size of Initialised Data: to fill in
hlUNINITIA      ' 0024  Size of Uninitialised Data: to fill in
                '
ga _main_       ' 0028  Address of Entry Point:
ga _code_       ' 002C  Base of Code:
'
'
'OMIT IN PE32+
^ga _data_ ' 0030  Base of Data:
'
'
'DWORD IN PE32, QWORD IN PE32+
'
hgIMAGEBAS ' 0034  0030  Image Base: 10000000 for dll 00400000 for EXE
'
'
hl1000     ' 0038  Section Alignment:
hl200      ' 003C  File Alignment Alignment:
hw4        ' 0040  Major Operating System Version: was 4
hw0        ' 0042  Minor Operating System Version: was 0
hw1        ' 0044  Major Image Version: was 1
hw0        ' 0046  Minor Image Version: was 0
hw4        ' 0048  Major Subsystem Version: WAS 5 4
hw0        ' 004A  Minor Subsystem Version: WAS 2 0
hl0        ' 004C  Reserved: (wIN32)
hl5000     ' 0050  Size of Image to fill in
hl400      ' 0054  Size of headers to fill in
hl0        ' 0058  Checksum 'unused
hw*        ' 005C  Subsystem:
           '       #define IMAGE_SUBSYSTEM_UNKNOWN 0
           '       #define IMAGE_SUBSYSTEM_NATIVE 1
           '       #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
           '       #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
hw0        ' 005E  DLL Characteristics: 140: nxAware, can be relocated at load time (was 0)
'
'THESE ARE DWORD IN PE32 AND QUAD IN PE32+
'
hg00100000 ' 0060  0060  Size of Stack Reserve:
hg00100000 ' 0064  0068  Size of Stack Commit:
hg00100000 ' 0068  0070  Size of Heap Reserve:
hg00001000 ' 006C  0078  Size of Heap Commit:

hl0        ' 0070  0080  Loader Flags:
hl10       ' 0074  0084  Number of RVA and sizes
  

'
'RVA 96 / 112    (0078 PE32 OR 0088 FOR PE32+)
'
  
'
'Optional Header Data Directories
'================================
' 
'
'giving offset and length: (2 DWORDS)
'
'    DESCRIPTION                 FILE ADDR:
'    MODE                        32    64
'==========================================
' 01 export table                0078  0088
' 02 import tables               0080  0090
' 03 resource table              0088  0098
' 04 exception table             0090  00A0
' 05 certificate table           0098  00A8
' 06 base relocation table       00A0  00B0
' 07 debug                       00A8  00B8
' 08 architecture                00B0  00C0
' 09 global ptr                  00B8  00C8
' 10 thread local storage        00C0  00D0
' 11 load configuration          00C8  00D8
' 12 bound import                00D0  00E0
' 13 import address table        00D8  00E8
' 14 delay import descriptor     00E0  00F0
' 15 CLR common language runtime 00E8  00F8
' 16 reserved                    00F0  0100
'
' RVA 00F8/0108 (16 entries * 8 bytes)
'
' Table Entries                  00F8  0108 ...
'==============================================
' each header table 40 bytes.. 
'  
' CODE HEADER:
'---------------
' 00 NAME                        00F8  0108
' 08 VIRTUAL SIZE                0100  0110
' 12 VIRTUAL ADDRESS             0104  0114
' 16 SIZE OF RAW DATA            0108  0118
' 20 POINTER TO RAW DATA         010C  011C
' 24 ( POINTER TO RELOCATIONS )  0110  0120
' 28 ( POINTER TO LINE NUMBERS ) 0114  0124
' 32 ( NUMBER OF RELOCATIONS )   0118  0128
' 34 ( NUMBER OF LINE NUMBERS )  011C  012C
' 36 CHARACTERISTICS             0120  0130
' 40 


'SECTION HEADER FLAGS
'====================
' HL0001 reserved
' HL0002 reserved
' HL0008 IMAGE_SCN_TYPE_NO_PAD obsolete
' HL0010 reserved
' HL0020 IMAGE_SCN_CNT_COD contains executable code
' HL0040 IMAGE_SCN_CNT_INITIALIZED_DATA
' HL0080 IMAGE_SCN_CNT_UNINITIALIZED_ DATA
' HL0100 IMAGE_SCN_LNK_OTHER reserved
' HL0200 IMAGE_SCN_LNK_INFO contains comments (obj files only)
' HL0400 reserved
' HL0800 IMAGE_SCN_LNK_REMOVE not part of image (obj files only)
' HL1000 IMAGE_SCN_LNK_COMDAT
' HL8000 IMAGE_SCN_GPRE contains date reference by global ptr

' HL10000000 IMAGE_SCN_MEM_SHARED can be shared
' HL20000000 IMAGE_SCN_MEM_EXECUTE can be executed as code
' HL40000000 IMAGE_SCN_MEM_READ can be read
' HL80000000 IMAGE_SCN_MEM_WRITE can be written to



!end!
"

string pe_imports="

.imports
ga name_list1 hl0 hl0
ga module_name1
ga address_list1
'ga name_list2 hl0 hl0
'ga module_name2
'ga address_list2
ga name_list3 hl0 hl0
ga module_name3
ga address_list3

hl0 hl0 hl0 hl0 hl0 ' termination

.module_name1 `KERNEL32.DLL` 00
'.module_name2 `OLEAUT32.DLL` 00
.module_name3 `USER32.DLL` 00


'IN PE32+ MODE THESE TABLES HAVE 64BIT ADDRESSES INSTEAD OF 32BIT ADDRESSES
'null termination

.name_list1
  gg _LoadLibrary
  gg _GetProcAddress
  gg _FreeLibrary
  gg _GetModuleHandle
  gg _GetCommandLine
  gg _GetExitCodeProcess
  gg _ExitProcess
  gg _CreateFile
  gg _ReadFile
  gg _CloseHandle
  hg0

'.name_list2
'  gg _SysAllocStringByteLen
'  gg _SysFreeString
'  hg0

.name_list3
  gg _MessageBoxA
  gg _MessageBoxW
  hg0


'-------------------------------
/+8 .import_address_table
'===============================

.address_list1
  gg _LoadLibrary
  gg _GetProcAddress
  gg _FreeLibrary
  gg _GetModuleHandle
  gg _GetCommandLine
  gg _GetExitCodeProcess
  gg _ExitProcess
  gg _CreateFile
  gg _ReadFile
  gg _CloseHandle
  hg0

'.address_list2
'  gg _SysAllocStringByteLen
'  gg _SysFreeString
'  hg0

.address_list3
  gg _MessageBoxA
  gg _MessageBoxW
  hg0



/+4 ._LoadLibrary        hw0 `LoadLibraryA` 00          '00  00
/+4 ._GetProcAddress     hw0 `GetProcAddress` 00        '04  08
/+4 ._FreeLibrary        hw0 `FreeLibrary` 00           '08  16
/+4 ._GetModuleHandle    hw0 `GetModuleHandleA` 00      '12  24
/+4 ._GetCommandLine     hw0  `GetCommandLineA` 00      '16  32
/+4 ._GetExitCodeProcess hw0 `GetExitCodeProcess` 00    '20  40
/+4 ._ExitProcess        hw0 `ExitProcess` 00           '24  48
/+4 ._CreateFile         hw0 `CreateFileA` 00           '28  56
/+4 ._ReadFile           hw0 `ReadFile` 00              '32  64
/+4 ._CloseHandle        hw0 `CloseHandle` 00           '36  72
                                                        '40  80 gap
/+4 ._MessageBoxA        hw0 `MessageBoxA` 00           '44  88
/+4 ._MessageBoxW        hw0 `MessageBoxW` 00           '48  96

p6
/+1000
!end!
"


'==========================
'PORTABLE EXECUTABLE FORMAT
'==========================


function exportdata(int*eord) as string
=======================================
  '
  int e,i,j,k,ki,kj,ei
  int pf,po,pn,ps
  string wf,wo,wn,ws,w1,w2
  '
  'ordinal counter eord
  '
  'create ordinal index
  '--------------------
  '
  e=eord-1 : ei=e-1
  for i=0 to e
    expi(i)=i
  next
  '
  'simple sort into ascending order
  '--------------------------------
  '
  for i=0 to ei
    for j=i+1 to e
      ki=expi(i)
      kj=expi(j)
      if expal(ki)>expal(kj) 'SWAP INDEX
       k=expi(i)
       expi(i)=expi(j)
       expi(j)=k
      endif
    next
  next
  '
  'build export data blocks
  '------------------------
  '
  'OXYGEN SCRIPT TO INSERT AFTER MAIN CODE
  '
  pf=0 : po=0 : pn=0 : ps=0
  for i=0 to e
    ki=expi(i)
    w2=str(i)
    w1="ga "+expwn(ki)+cr 'FUNCTION ADDRESSES TABLE `EAT`
    appe(wf,pf,w1)
    w1="nw "+w2+cr        'ORDINALS TABLE           `EOT`
    appe(wo,po,w1)
    w1="ga #en#"+w2+cr    'NAMES TABLE              `ENT`
    appe(wn,pn,w1)
    w1="/+4 .#en#"+w2+" "+chr(96)+expal(ki)+chr(96)+ " 00"+cr 'NAMES
    appe(ws,ps,w1)
  next
  '
  'combine to make export data
  '---------------------------
  '
  return "/+4 .export_funcs"+cr+left(wf,pf)+
         "/+4 .export_ordls"+cr+left(wo,po)+
         "/+4 .export_names"+cr+left(wn,pn)+
         left(ws,ps)
  '
end function


function cvlm(string*s,int i) as int
====================================
  int a at strptr(s)+i
  return a
end function


procedure ptch(string*s,int i,v)
================================
  int a at strptr(s)+i
  a=v
end procedure


function sect(string*s, int i,le) as string
===========================================
  return mid(s,i+1,le)
end function
 

function sizebss() as int
==========================
  int b
  b=(aoff+0xfff)and 0x7ffff000 'round up to nearest 4k
  return b
end function


function DateTimeEncode() as string
===================================
  int tss=CalcUnixTimeStamp(null,0)
  return hex(tss,8) 'beware 2037 !
end function


procedure setimagestat(int ii,offs,*pt,*lr,*lf)
==============================================
  pt=cvlm(dbuf,offs+12) 'get virtual offset
  lr=posbin[ii]
  if lr
    lr=lr-pt 'get length of data
  endif
  lf=(lr+0x1ff) and 0xfffffe00 'round up length to nearest 0x200 bytes
  ptch dbuf,offs+08,lr  ' size of image data
  ptch dbuf,offs+16,lf  ' size of file data (raw data length)
end procedure


int lpef

function MakePEfile(string*fi) as int
=====================================
  '
  'CONVERTS MEMORY IMAGE INTO PE FILE (EXE OR DLL)
  '
  int a,b,i,p,q
  int sho,ocs,ods,oes,ois,obs,pemo
  int prc,prd,pre,pri,ptc,ptd,pte,pti,ptq,ptb
  int lrc,lrd,lre,lri,lfc,lfd,lfe,lfi,lfr,cofo
  string w1,ssh,ssc,ssd,ssi,sse,dll

  if ert
    exit function
  endif

  'including dos header 128 + pe header 24 + optional header 96 + section directory 128 ==> 0x178 + stringbase 1 ==> 0x179 (256+120+1)


  'MAP OUT ENTRY OFFSETS
  '=====================



  'TABLE ENTRIES ARE 40 BYTES EACH
  '===============================

  'cvl(mid(dbuf,0x3d,4))
  cofo=cvlm(dbuf,0x3c) 'Coff header offset is size of DOS header (0xe8)

  'CHECK MAGIC NUMBER FOR PE32=010b OR PE32+ (64BIT)=020b
  '
  if asc(dbuf,cofo+0x1a)=2
    pemo=16 'EXTRA 16 BYTES FOR PE32+ HEADER (64 BIT
  endif
  if pemo
    mid(dbuf,cofo+0x17)=chr(0x22) 'CAN HANDLE LARGE ADDRESSES
  endif
  '
  sho=cofo+0xf8+pemo  'SECTION HEADERS OFFSET
  '
  'OFFSETS OF TABLE ENTRIES
  '========================
  '
  'must be kept in sync with table in o2fini
  ' 
  expf=0 'exports flag
  a=sho  'section header offset
  do
    w1=mid(dbuf,a+1,8)
    if asc(w1)<>46
      exit do
    elseif idword(w1,".text")
      ocs=a 'code header offset
    elseif idword(w1,".data")
      ods=a 'initialised data header offset
    elseif idword(w1,".bss")
      obs=a 'uninitialised data header offset
    elseif idword(w1,".edata")
      oes=a : expf=1 'export header offset
    elseif idword(w1,".idata")
      ois=a 'import header offset
    endif
    a+=40 'step next table entry
  loop


  'MAPPING OF EACH SECTION HEADER
  '==============================
  '
  ' 0  NAME
  ' 8  VIRTUAL SIZE
  ' 12 VIRTUAL ADDRESS
  ' 16 SIZE OF RAW DATA
  ' 20 POINTER TO RAW DATA
  ' 24 ( POINTER TO RELOCATIONS )
  ' 28 ( POINTER TO LINE NUMBERS )
  ' 32 ( NUMBER OF RELOCATIONS )
  ' 34 ( NUMBER OF LINE NUMBERS )
  ' 36 CHARACTERISTICS
  ' 40

  '
   
  'GET DATA OFFSETS AND RAW DATA LENGTHS
  '=====================================

  'returning offset, length, and file section length
  '
  setimagestat(2,ocs,ptc,lrc,lfc) 'code
  setimagestat(3,ods,ptd,lrd,lfd) 'data
  if expf
    setimagestat(5,oes,pte,lre,lfe) 'exports
  endif
  setimagestat(6,ois,pti,lri,lfi) 'imports

  ptb=cvlm(dbuf,obs+12)


  
  'CALC FILE DATA OFFSETS 'aka: raw data
  '======================
  
  a=0x400           'PE FILE HEADER LENGTH IN FILE
  prc=a : a+=lfc    'CODE SECTION
  prd=a : a+=lfd    'DATA SECTION
  if expf
    pre=a : a+=lfe  'EXPORT SECTION
  endif
  pri=a : a+=lfi    'IMPORT SECTION

  'BUILD RAW DATA FOR FILE FROM MEMORY IMAGE
  '=========================================
  '
  ssh=left(dbuf,0x400)     'HEADER   SECTION 
  ssc=sect(dbuf,ptc,lfc)   'CODE     SECTION
  ssd=sect(dbuf,ptd,lfd)   'DATA     SECTION
  if expf
    sse=sect(dbuf,pte,lfe) 'EXPORT   SECTION
  endif
  ssi=sect(dbuf,pti,lfi)   'IMPORT   SECTION

  dll=ssh+ssc+ssd+sse+ssi


  'PATCH IN LENGTHS
  '----------------

  ptch dll,cofo+0x50,len(dbuf) 'INCLUDING BSS SPACE

  'giving section lengths in file lf? or in memory ls?

  ptch dll,cofo+0x1c,lfc             ' size of code section
  ptch dll,cofo+0x20,lfd+lfe+lfi     ' size of initialised data section


  'PATCH DATA INTO THE SECTION HEADERS
  '-----------------------------------
  '
  'here the length of physical data (in memory image) = length of raw data
  '
  ptch dll,ocs+20,prc  ' offset of file data for code
  ptch dll,ods+20,prd  ' offset of file data for code
  ptch dll,ois+20,pri  ' offset of file data for imports

  if expf
  '
  ptch dll,oes+20,pre  ' offset of file data for exports
  ptch dll,pre+4,q     ' timedate stamp for exports
  ptch dll,cofo+pemo+0x7c,lfe
  '
  endif

  '
  'CALCULATE AND SET CHECKSUM
  '==========================
  '
  int *ck 'checksum
  sys ps=strptr(dll)
  dword b at ps+60 'PE header offset
  @ck=ps+b+0x58 'checksum location
  ck=0 'clear checksum
  '
  uint ls  'byte length of data
  ls=len(dll)
  lpef=ls
                   'word *pd 'input
  xor eax,eax      'uint ca 'checksum accumulator
  xor edx,edx      'uint uw 'upper word      '
  mov rsi,ps       '@pd=ps
  mov ecx,ls       'int j 'iterator      
  (                'for j=1 to ls step 2 'each word
    mov dx,[rsi]   '
    add eax,edx    '  ca+=pd
    mov edx,eax    '  uw=ca>>16
    shr edx,16     '
    and eax,0xffff '  ca and=0xffff
    add eax,edx    '  ca+=uw
    add rsi,2      '  @pd+=2
    sub ecx,2      '
    jg repeat      '
  )                'next
  'final           '
  mov edx,eax      'uw=ca>>16
  shr edx,16       '
  add eax,edx      'ca=uw+ca
  and eax,0xffff   'ca and= 0xffff
  add eax,ls       'ca+=ls 'add in byte length of data
  addr rsi,ck      'ck=ca 'set checksum
  mov [rsi],eax    '
  '
  '
  'CREATE AND STORE THE FILE
  '=========================
  '
  SetLastError 0
  putfile(fi,dll)
  'https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--0-499-
  b=GetLastError
  if b=183
    b=0 'file already exists
  endif
  if b
    ert=b
    ers="Unable to File Binary "+fi+" "+str(b) : ert=43
  endif
  return b
end function



function MakeSections() as string
=================================
'
int    a,b,c,d,k
string w1,w2,w3,w4,wm,wd
string prol,epils,asms,hdrs,ddat,udat,imps,exps,ress


'       ################
'      #     #          #
'     #       #          #
'    #         #          #
'    #         #          #
'    #      #  #  #    #  #  #
'    #       #####      #####
'    #        ###        ###
'    #         #          #
'    #         #          #
'    #########            #
'    #                    #
'    #                    #
'     #                  #
'      #################
'            #
'           ###
'            # 
'
'  ########################

'  END OF PREPROCESSOR LOOP

'  ########################



'

'=====
finap:
'=====
'   
'   =========================
'   |  |      |   |   || | | |
'   |  | O2   |   |   || | | |
'   |H | O2H  |   |   || | |F|----------> ASSEMBLER
'   |  |      |   |   || | | |
'   |  |      |   |   || | | |
'   =========================
'

'
'  SAVE REGISTERS
'  BOOTSTRAP
'  ALLOCATE STATIC MEMORY
'  FREE LIBRARIES
'  FREE MEMORY
'  RESTORE REGISTERS
'
if ert=0
  if brc>0
    ers=str(brc)+" excess left brackets in source ((..) " : ert=10
  endif
endif
'
'
'
'BSS DATASPACE ALLOCATION
'
'
'PROGRAM ENTRY FOR PRIMARY COMPILED CODE:
'CREATE BSS STATIC SPACE FOR GLOBALS ETC
'
aoff+=15 : aoff and= 0xfffffff0  'ROUND UP TO NEAREST 16
'
ddat="._data_"+cr+left(dats,dati)+"
00
p3
/+1000"+cr
udat=".bssdata"+cr+"$"+hex(sizebss())+cr
string cpuws=str(cpuw)
'
if independent
  goto njit
endif
'
'RBX contains base address of runtime procedure table

'MAIN PROLOG
============


=================
if cpuw=4 '32bit
=================

prol="
jmp fwd _initjit

'UTILITIES:
'
'GET ADDRESS OF BSSDATA, STORE IN RBX
'====================================
._mem
call fwd _h_
._h_
pop rbx
sub rbx,_h_
add rbx,bssdata
ret
'
'
'MAIN ENTRY POINT
'================
._initjit
push rbp : mov rbp,rsp
'call CopyLib
'SPACE FOR GLOBAL BUFFER POINTERS
push 0
push 0
push 0
push 0
push 512  : call [rbx+8] : mov [rbx+664],rax 'BUFFER FOR GLOBAL STRINGS 664 
push 4096 : call [rbx+8] : mov [rbx+680],rax 'BUFFER FOR LIB HANDLES 680 

" 'END OF PROLOG
'
'
'VACANT BUFFER POINTERS
'[rbx+648]
'[rbx+656]
    '

'EPILOG
'======    '
epils="
._end_
mov rsp,rbp : pop rbp
ret

._error_
(
  o2 e8 hl0
  pop eax
  add eax,9
  exit
  o2 `MISSING OR UNLOADABLE` 00 00
)
push 0x30
push eax
push ecx
push 0
call [ebx+472]
jmp _end_
"

===========
else '64bit
===========

prol="
jmp fwd _initjit

'UTILITIES:
'
'GET ADDRESS OF BSSDATA, STORE IN RBX
'====================================

  ._mem
  lea rip rbx,bssdata
  ret
'
'
'MAIN ENTRY POINT
'================
._initjit
push rbp : mov rbp,rsp
'SPACE FOR GLOBAL BUFFER POINTERS
push 0
push 0
push 0
push 0
mov rcx,512  : call [rbx+8] : mov [rbx+664],rax 'BUFFER FOR GLOBAL STRINGS 664 
mov rcx,4096 : call [rbx+8] : mov [rbx+680],rax 'BUFFER FOR LIB HANDLES 680 
" 'END OF PROLOG
'
'
'VACANT BUFFER POINTERS
'[rbx+648]
'[rbx+656]
'

'EPILOG
'======    '
epils="
._end_
mov rsp,rbp : pop rbp
ret

._error_
'call [rbx+2048] 'MBOX
(
 o2 e8 hl0
 pop rax
 add rax,11
 exit
 o2 `MISSING OR UNLOADABLE` 00 00
)
mov r9,0x30
mov r8,rax
mov rdx,rcx
mov rcx,0
sub rsp,32
call [ebx+472]
add rsp,32
jmp _end_
"
=================================
endif 'cpuw 4/8 : mode 32/64 bit
=================================

asms=prol+t+epils

roundupc(dati,4)
apdat("")

return "
._code_
._main_
"+asms+"
o2 (
p2
/+1000
"+ddat+"
p3
"+udat+"
)
" 'JIT MODE


=====
njit:
=====

asms=prol+t
'
'
'==========================
'PE HEADERS FOR EXE AND DLL
'==========================
'
hdrs=readin(pe_header)
a=instr(hdrs,"^")
c=instr(hdrs,"*") 'SUBSTITUTION WILL BE FOR MAGIC NUMBER
if pem=64
  b=instr(hdrs,"hw014c")
  mid(hdrs,b)="hw8664" 'AMD64 CPU
  b=instr(hdrs,"hw00e0")
  mid(hdrs,b)="hw00f0" 'EXTRA 16 BYTES IN OPTIONAL HEADER
  w3="2" 'MAGIC NUMBER 020B
  lineblank(hdrs,a) 'OMIT
else
  w3="1" 'MAGIC NUMBER 010B
  mid(hdrs,a)=" "
endif
mid(hdrs,c)=w3          'MAGIC NUMBER
c=instr(c,hdrs,"*")     'LOCATE NEXT PATCH
mid(hdrs,c)=chr(0x32+cnsl) 'SUBSYSTEM 2 OR 3 (3=EXISTING CONSOLE)
'
hdrs=readin(dos_header)+hdrs
imps=readin(pe_imports)
'
'hdrs dos header+coff header+optional header
'imps imports section
'
'bss mapping
'===========
'
' [rdi+600] IMPORT FUNCTIONS ADDRESS LIST (BOOTSTRAP LIBRARY)
' [rdi+608] PROCESS HANDLE
' [rdi+615] OXYGEN LIBRARY HANDLE
'
'
w2="" : w3="" : wm=""
'
'
'EXPORT TABLE
'============
'
'https://msdn.microsoft.com/en-us/library/ms809762.aspx
'
if eord
'
w3=" hl"+hex(eord)
exps="
.exports hl0 hl0 hl0 ga export_name
hl1"+w3+w3+" ga export_funcs ga export_names ga export_ordls hl0
/+4 .export_name `"+pexn+"` 00
"+exportdata(eord)+"
p5
/+1000
"
w3=""
expf=1
'
endif 'eord
'
'
'SECTION DIRECTORY
'=================
'
'Optional Header Data Directory (cofo+0x78 or cofo+0x88 64bit )
'
a=128 '16 entries x 8
'address followed by default length
'
'export section
if expf
  w3="ga exports hl0"
else
  w3="hl0 hl0"
endif
hdrs+=w3+cr
'
'always an import section
hdrs+="ga imports hl200"+cr

'pad out rest of directory with null entries
'a-16
'
'
'SECTION TABLE/HEADERS (40 BYTES EACH)
'=====================================
'
'following section directory of 16 entries = 80h bytes
'BASE ADDRESS RVA 178 or 188 in PE32+
'
'with default values
'
string hd1,hd2,hd3,hd4,hd5
'--------------------------------------------------------------------------------------------'
'     name         virtsz      virtaddr     rdsz   rdpt  characteristics' flags
'============================================================================================'
'   0            8           12           16     20... 36             '
'--------------------------------------------------------------------------------------------'
hd1="`.text`  $3 hl00000000  ga _code_    hl000  $10   hl60000020"+cr ' code exec read
hd2="`.data`  $3 hl40000000  ga _data_    hl200  $10   hlc0000040"+cr ' init read write
hd3="`.bss`   $4 hlUNINITIA  ga bssdata   hl000  $10   hlc0000080"+cr ' uninit read write
if expf
hd4="`.edata` $2 hl02000000  ga exports   hl200  $10   hlc0000040"+cr ' init read write
endif
hd5="`.idata` $2 hl02000000  ga imports   hl200  $10   hlc0000040"+cr ' init read write
'--------------------------------------------------------------------------------------------'
hdrs=hdrs+"$"+hex(a-16)+cr+hd1+hd2+hd3+hd4+hd5
'
'
'PATCH-INS
'
a=instr(hdrs,"hlDATETIME")
mid(hdrs,a)="hl"+DateTimeEncode()

a=instr(hdrs,"hwSECT")
mid(hdrs,a)="hw000"+chr(52+expf) 'NUMBER OF SECTIONS 4..5

a=instr(hdrs,"hwLIBX")
if pef=1
  mid(hdrs,a)="hw2102"
else
  mid(hdrs,a)="hw0102" 'FOR DLL OR EXE
endif
a=instr(hdrs,"hgIMAGEBAS")
if pef=1
  mid(hdrs,a)="hg10000000"
else
  mid(hdrs,a)="hg00400000" 'FOR DLL OR EXE
endif
wd=hex(sizebss()) 'MIN HEX 1000
wd="hl"+right("0000"+wd,8)
for b=1 to 2
  a=instr(hdrs,"hlUNINITIA")
  mid(hdrs,a)=wd 'UNINITIALISED DATA
next
'
'
'field descriptions
'------------------
' 
' 00  name upto 8 bytes
' 08  virtual size (this is null padded if freater than the raw data size)
' 12  virtual address (offset in memory 4096 byte steps)
' 16  raw data size (rounded to 512 bytes)
' 20  raw data offset in file (512 byte steps)
' 24  pointer to relocations (null)
' 28  pointer to line numbers (null)
' 32  Number of relocations   (0)
' 34  Number of line numbers  (0)
' 36  Characteristics Bits:
'      00 reserved
'      01 reserved
'      02 reserved
'      04 reserved
'      08 obsolete
'      10 reserved
'      20 contains executable code
'      40 contains initialised data
'      80 contains uninitialised data
'     100 reserved     
'     200 reserved contains comments (object files only)
'     400 reserved
'     800 will not become part of image (object files only)
'    1000 contains COMDAT data
'    8000 contains data referenced through global pointer
'   10000 reserved
'   20000 reserved
'   40000 reserved
'   80000 reserved
'  100000 align on 1 byte boundary (object files only)
'  200000 align on 2 byte boundary (object files only)
'  300000 align on 4 byte boundary (object files only)
'  400000 align on 8 byte boundary (object files only)
'  500000 align on 16 byte boundary (object files only)
'  600000 align on 32 byte boundary (object files only)
'  700000 align on 64 byte boundary (object files only)
'  800000 align on 128 byte boundary (object files only)
'  900000 align on 256 byte boundary (object files only)
'  A00000 align on 512 byte boundary (object files only)
'  B00000 align on 1024 byte boundary (object files only)
'  C00000 align on 2048 byte boundary (object files only)
'  D00000 align on 4096 byte boundary (object files only)
'  E00000 align on 8192 byte boundary (object files only)
' 1000000 contains extended relocations
' 2000000 can be discarded
' 4000000 cannot be cached
' 8000000 is not pageable
'10000000 can be shared in memory
'20000000 can be executed as code
'40000000 can be read
'80000000 can be written to
'
'ENTRY POINT
'
'This jump will not appear in the PE file
'
if independent
  hdrs+="/0ff0 c3"+cr+"/+1000" 'NO DIRECT EXEC
else
  hdrs+="/0ff0 e9 gf _o2_ "+cr+"/+1000" 'JUMP TO MAIN CODE
endif
'
replacecolons(wm)
'
'---------------------------
'BRING ALL SECTIONS TOGETHER
'===========================
'
'also adding section for uninitialised data (.bss)
'
return "
o2 (
"+hdrs+"
)
._code_
._main_
"+wm+"
._o2_
"+asms+"
o2 (
p2
/+1000
"+ddat+udat+exps+imps+ress+"
)
"
'END OF PE FILE PREP

end function 'Make Sections
