This source PFDLL generates and imports EuroAssembler output object file in program format DLL (COFF Dynamic Linked Library).
pfdll PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
INCLUDEHEAD euroasm.htm, \ Interface (structures, symbols and macros) of other modules used in this source.
ea.htm,eaopt.htm,exp.htm,msg.htm,pf.htm,pfcoff.htm,pfmz.htm,pfpe.htm,pgm.htm,pgmopt.htm, \
reloc.htm,sss.htm,stm.htm,sym.htm
pfdll HEAD ; Start module interface. ; Program pfdll exports nothing. ENDHEAD pfdll ; End of module interface.
PFCOFF_FILE_HEADER.Characteristics:pfcoffFILE_DLL
set by PfcoffFileHeader.PfdllCompile Procedure OutputStream, Pgm Invoke PfpeCompile::,[%OutputStream],[%Pgm] EndProcedure PfdllCompile
IMPORT ExportedName,LIB=DllName were written in BasePgm.
PfdllLoadPgm Procedure BasePgm, ObjBegin, ObjSize, FileNamePtr
NumberOfSections LocalVar ; As specified in file header.
RVA2Ptr LocalVar ; Difference of mapped address from RVA.
DLLPtr LocalVar ; Ptr to volatile DLL name.
DLLSize LocalVar ; Number of bytes in DLL name.
MOV ESI,[%ObjBegin] ; Pointer to the start of file in mapped memory. FileAddress FA=0.
MOV ECX,[%ObjSize]
LEA EDX,[ESI+ECX] ; ObjEnd in mapped memory. Procedure may read only data below EDX.
ADD ESI,[ESI+PFMZ_DOS_HEADER.e_lfanew] ; Add FA of PE signature.
CMP ESI,EDX
JNB .E8535: ; Report error if file too short.
LODSD
CMP EAX,'PE' ; Check the PE/DLL signature.
JNE .E8535:
MOVZXW ECX,[ESI+PFCOFF_FILE_HEADER.NumberOfSections]
MOVZXW EBX,[ESI+PFCOFF_FILE_HEADER.SizeOfOptionalHeader]
MOVZXW EAX,[ESI+PFCOFF_FILE_HEADER.Characteristics]
MOV [%NumberOfSections],ECX
JECXZ .E8535: ; If no sections in file.
ADD ESI,SIZE# PFCOFF_FILE_HEADER ; Skip the file header.
ADD EBX,ESI
CMP EBX,EDX
JNB .E8535:
MOV EDI,[ESI+PFPE_OPTIONAL_HEADER32.DataDirectory+pfpeDIRECTORY_ENTRY_EXPORT*SIZE#PFPE_DATA_DIRECTORY+PFPE_DATA_DIRECTORY.VirtualAddress]
MOV ECX,[ESI+PFPE_OPTIONAL_HEADER32.DataDirectory+pfpeDIRECTORY_ENTRY_EXPORT*SIZE#PFPE_DATA_DIRECTORY+PFPE_DATA_DIRECTORY.Size]
JNSt EAX,pfcoffFILE_LARGE_ADDRESS_AWARE,.15:
MOV EDI,[ESI+PFPE_OPTIONAL_HEADER64.DataDirectory+pfpeDIRECTORY_ENTRY_EXPORT*SIZE#PFPE_DATA_DIRECTORY+PFPE_DATA_DIRECTORY.VirtualAddress]
MOV ECX,[ESI+PFPE_OPTIONAL_HEADER64.DataDirectory+pfpeDIRECTORY_ENTRY_EXPORT*SIZE#PFPE_DATA_DIRECTORY+PFPE_DATA_DIRECTORY.Size]
.15:MOV ESI,EBX ; ESI now points to the first section header.
JECXZ .E8535:
; Enumerate sections and find FA of ExportTable in the loop .20: .. .30:.
MOV ECX,[%NumberOfSections]
.20:MOV EAX,[ESI+PFCOFF_SECTION_HEADER.VirtualAddress]
CMP EDI,EAX
JB .30:
ADD EAX,[ESI+PFCOFF_SECTION_HEADER.VirtualSize]
CMP EDI,EAX ; Does the export table lay in section with header ESI?
JB .40: ; If section found. Usually it is [.edata] or [.text].
.30:ADD ESI,SIZE#PFCOFF_SECTION_HEADER ; Otherwise try the next section.
LOOP .20:
.E8535:Msg '8535',[%FileNamePtr] ; Format of file "!1$" is not importable.
JMP .90:
.40:MOV EAX,EDI ; EDI is RVA of export table residing in section whose header is mapped with ESI.
SUB EDI,[ESI+PFCOFF_SECTION_HEADER.VirtualAddress] ; EDI is now offset of export directory table.
ADD EDI,[ESI+PFCOFF_SECTION_HEADER.PointerToRawData] ; EDI is now FA of import tables.
ADD EDI,[%ObjBegin] ; EDI is now ptr to import table mapped in memory.
MOV ESI,EDI ; ESI now points to mapped PFPE_EXPORT_DIRECTORY.
SUB EDI,EAX
MOV [%RVA2Ptr],EDI ; Keep the difference of mapped address from its RVA.
; Find and store DLL name.
MOV EDX,[ESI+PFPE_EXPORT_DIRECTORY.Name]
ADD EDX,[%RVA2Ptr]
GetLength$ EDX
MOV [%DLLPtr],EDX
MOV [%DLLSize],ECX
SUB EDX,EDX ; Index of export (0,1,2,3,4...).
MOV ECX,[ESI+PFPE_EXPORT_DIRECTORY.AddressOfNames] ; RVA of Name ptr table (NPT).
ADD ECX,[%RVA2Ptr] ; Pointer to NPT in memory.
MOV EAX,[ESI+PFPE_EXPORT_DIRECTORY.AddressOfOrdinals]
ADD EAX,[%RVA2Ptr] ; Pointer to ONT in memory.
; Create import module of each export.
; EDX=zero-based index, EAX=^ONT, ECX=^NPT, ESI=^PFPE_EXPORT_DIRECTORY.
.50:CMP EDX,[ESI+PFPE_EXPORT_DIRECTORY.NumberOfNames]
JAE .90:
PUSH EAX,ECX
LEA EAX,[EAX+2*EDX] ; EAX is now pointer to word ordinal number.
MOVZXW EDI,[EAX] ; Ordinal number.
ADD EDI,[ESI+PFPE_EXPORT_DIRECTORY.Base]
LEA EAX,[ECX+4*EDX] ; EAX is now pointer to RVA of ASCIIZ symbol name.
MOV EBX,[EAX] ; RVA of ASCIIZ name.
ADD EBX,[%RVA2Ptr] ; Convert RVA to memory pointer.
GetLength$ EBX
Invoke PgmCreateImportModule::,[%BasePgm],[%DLLPtr],[%DLLSize],EDI, \
symImport+'A',EBX,ECX,EBX,ECX
POP ECX,EAX
INC EDX
JMP .50:
.90:EndProcedure PfdllLoadPgm
ENDPROGRAM pfdll