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. INCLUDEHEAD \ ; Include headers of another modules used in this module. 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, \ syswin.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