This source file ea.htm
contains an object Ea which represents the executable file
euroasm.exe
. It provides initialization of €ASM and assembles all source files
specified at cmdline.
As there is only one instance of EA, the object Ea
is defined statically.
EUROASM NOWARN=2101 ea 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. dict.htm, \ eaopt.htm, \ exp.htm, \ ii.htm, \ msg.htm, \ pfcoff.htm, \ pfmz.htm, \ pfpe.htm, \ pgm.htm, \ pgmopt.htm, \ reloc.htm, \ sss.htm, \ stm.htm, \ sym.htm, \ syswin.htm, \ ;;
ea HEAD ; Start of module interface.
%EaStackSize %SETA 1M ; €ASM machine stack ES:ESP reserved size. ; Fatal error is thrown on overflow. %EaPoolSize %SETA 64K ; Initial POOL block brutto size. ; More blocks will be allocated on demand with OS' granularity. %EaBufferSize %SETA 4K ; Initial BUFFER brutto size. ; It can be increased (doubled) on demand when underestimated. %EaStackDepth %SETA 16 ; Initial number of stackable objects on STACK. ; It can be increased (doubled) on demand when underestimated.
Ea.TimeStart
keeps the real system time when euroasm.exelaunched. It is used to compute the duration of runtime, which will be reported with I0980. See also
Ea.Eaopt.TimeStamp
.
Ea.BufferStack
is a pointer to
STACK which stacks QWORDS which contain
Ea.StackBottom
is computed from Ea.StackOrg
decreased by the reserved stack size minus some safety reserve.
It is used for protection from stack overflow.EA STRUC .Version D 8*B ; EuroAssembler version "YYYYMMDD". .EuroasmOS D 4*B ; Zero-padded shortcut of EuroAssembler platform (oper.system), e.g. "Win",0. .Errorlevel D D ; Highest errorlevel reached so far in any source. ;+10h .StackOrg D D ; €ASM machine stack pointer (ESP) at program entry. .StackBottom D D ; Bottom ofeuroasm.exereserved machine stack. .Pool D D ; Pointer to Ea memory POOL. .BufferStack D D ; Pointer to STACK of Qwords described above. ;+20h .Status D D ; Binary flags in EaEnc encoding. .ArgNr D D ; Ordinal number of currently processed cmdline argument. .SubPtr D D ; Pointer to suboperation string applied to source file. .SubSize D D ; Size of suboperation string including brackets. ;+30h .TimeStart D D ; Real time wheneuroasm.exelaunched, as seconds since midnight Jan 1st 1970 UTC. .SrcTime D D ; Last write time of currently processed source file in FAT DosDateTime format (OMF). .MemAllocated D D ; Currently allocated amount of virtual memory. .MemPeak D D ; Peak amount of virtual memory ever allocated. ;+40h .StmCount D D ; Total number of statements parsed. .CodePage D D ; Codepage currently loaded and cached in Ea.CodeTable. .CodeTable DU 128*U ; Dynamically updated translate table from ANSI[128..255] to WIDE characters. .EaoptIni DS EAOPT ; Global default EUROASM options valid at start of each source. .Eaopt DS EAOPT ; Currently valid EUROASM options in charge. Dynamically updated. .Pgmopt DS PGMOPT ; Global default PROGRAM options valid at the start of each source. .IniFile DS FILE ; Global configuration FILEeuroasm.ini. .SrcFile DS FILE ; Currently processed source file specified on cmdline. ENDSTRUC EA
eaAtLeast1File EQU 1 ;euroasm.exewas launched with one or more input source file. eaWildcarded EQU 2 ; Input source file was specified with wildcard(s) ?, *. eaIniSectEUROASM EQU 4 ; [EUROASM] section ofeuroasm.iniis currently processed. eaIniSectPROGRAM EQU 8 ; [PROGRAM] section ofeuroasm.iniis currently processed.
Ea.StackBottom
.EaStackCheck %MACRO CMP ESP,[Ea.StackBottom::] Msg cc=B,'9210' ; Memory reserved for machine stack is too small for this source file. %ENDMACRO EaStackCheck
ENDHEAD ea ; End of module interface.
[.bss] Ea:: DS EA ; Instance of the main EuroAssembler object.
euroasm.exe.
[.data] EaVersion:: DB "%^DATE" ; Date "YYYYMMDD" when €ASM was built. EaIniFileDefault: ; Factory default options from../objlib/euroasm.iniwill be built-in toeuroasm.exe. INCLUDEBIN "../objlib/euroasm.ini" EaIniFileDefaultEnd:
[.text] EaMain:: PROC ; Entry point of EuroAssembler. Here the execution begins and ends. MOV EAX,ESP Invoke EaCreate,EAX ; Command-line arguments are source file names mixed with EUROASM options, ; separated with unquoted space or comma and they are processed in two passes: ; Cmdline pass 1 will ignore filenames and store each option as is to a temporary buffer. Invoke EaBufferReserve,EaMain MOV EBP,EAX BufferStore EBP, =B "[EUROASM]",9 ; Initialize contents with division name. BufferStoreByte EBP,10 ; Terminate with line-feed. .10:INCD [Ea.ArgNr] ; Get the next argument (a filename or keyword option). SysGetArg [Ea.ArgNr] ; Set ESI,ECX to a cmdline argument. JC .30: ; If there are no more arguments. MOV EBX,ESI ; Pointer to a potential keyword. LEA EDI,[ESI+ECX] ; End of potential EUROASM keyword including its value. Invoke ExpParseKeyName::,ESI,EDI JC .10: ; If the argument was not a keyword=, then it must be a filename. Ignore in pass 1. LEA EDX,[EAX-1] SUB EDX,EBX ; EBX,EDX is now KeyName. Invoke ExpParseKeyValue::,EAX,EDI JC .10: ; Ignore. Invalid options will be processed in cmdline pass 2 and treated as a filename. Invoke DictLookup::, DictEaoptMisc::,EBX,EDX ; EBX,EDX is option key name, e.g."NOWARN". ESI,ECX is valid option value, e.g. "2100". JNC .20: Invoke DictLookup::, DictEaoptStatus::,EBX,EDX JNC .20: Invoke DictLookup::, DictEaoptFea::,EBX,EDX JC .10: ; Ignore. Unknown options will be processed in cmdline pass 2 and treated as a filename. .20:SysGetArg [Ea.ArgNr] ; Reload the whole valid argument again. BufferStore EBP,ESI,ECX ; Accumulate unassembled cmdline options in temporary buffer EBP. BufferStoreByte EBP,10 ; Terminate with line-feed. JMP .10: ; The next cmdline argument. .30:BufferRetrieve EBP ; Reload plaintext cmdline EUROASM options from the temporary buffer EBP. ADD ECX,ESI ; Text at ESI..ECX is virtualeuroasm.inicontents composed from [EUROASM] division and cmdline options. Invoke EaIniAssemble,ESI,ECX,Ea.Eaopt,Ea.Pgmopt ; Compile the contents to Ea.Eaopt object. ; Now it's time to report first informative messages. They are suppressible only by cmdline optionNOWARN=0010..0020
. MOV EBX,Ea.SrcFile.Name ; As SrcFile was not used yet, its room will be temporarily misused as the current directory name temporary storage. SysGetCurrentDirectory EBX PUSHD 8,Ea.Version MOV EAX,ESP Msg '0010',EAX ; EuroAssembler version !1S started. POP EAX,EAX Msg '0020',EBX ; Current directory is "!1$". Invoke EaIniGlobal ; Compile globaleuroasm.inito Ea object. BufferRetrieve EBP ADD ECX,ESI Invoke EaIniAssemble,ESI,ECX,Ea.Eaopt,Ea.Pgmopt ; Reapply cmdline options again. Invoke EaBufferRelease,EBP ; Temporary buffer for cmdline options is no longer necessary. CopyTo Ea.EaoptIni, Ea.Eaopt ; Snapshot the starting options for each source. ; Cmdline pass 2 will read&assemble filename(s) and skip command-line options. MOVD [Ea.ArgNr],0 ; Start with the first argument again. .40:INCD [Ea.ArgNr] SysGetArg [Ea.ArgNr] JC .80: ; If there are no more arguments. MOV EBX,ESI ; Pointer to a potential keyword. LEA EDI,[ESI+ECX] ; End of potential EUROASM keyword including its value. Invoke ExpParseKeyName::,ESI,EDI JC .50: ; If the argument was not a keyword=, go and treat the argument ESI,ECX as a filename to assemble. LEA EDX,[EAX-1] SUB EDX,EBX ; EBX,EDX is now KeyName. Check if it is valid. PUSH ECX,ESI Invoke ExpParseKeyValue::,EAX,EDI POP ESI,ECX JC .50: ; If the option value was invalid, go and treat the argument ESI,ECX as a filename to assemble. ; EBX,EDX is key name. Invoke DictLookup::, DictEaoptMisc::,EBX,EDX JNC .40: ; Skip a valid cmdline option. Invoke DictLookup::, DictEaoptStatus::,EBX,EDX JNC .40: ; Skip a valid cmdline option. Invoke DictLookup::, DictEaoptFea::,EBX,EDX JNC .40: ; Skip a valid cmdline option. .50:; ESI,ECX will be treated as a filename to assemble. It may be suboperated and have wildcards. ; String may look likefile.asm
or"file*.asm"
or"file.asm"{1..40}
. ; Filename wildcards without quotes will be solved by SysEachFile, ; suboperation string will be parsed to Ea.SubPtr,Ea.SubSize. LEA EDX,[ESI+ECX] LODSB MOV [Ea.SubPtr],EDX ; Initialize Ea.Sub to an empty string. MOV [Ea.SubSize],0 MOV EDI,ESI DEC ESI CMP AL,'"' JNE .60: ; If filename is not in quotes, it cannot have suboperations. INC ESI ; Source file is specified in quotes. REPNE SCASB ; Find the closing quote. MOV [Ea.SubPtr],EDI SUB EDX,EDI ; Suboperation size. LEA ECX,[EDI-1] MOV [Ea.SubSize],EDX SUB ECX,ESI ; ESI,ECX is netto filename. It may contain wildcard characters ? *. SetSt [Ea.Status],eaWildcarded RstSt [Ea.Status],eaAtLeast1File MOV EDX,ECX MOV EDI,ESI MOV AL,"?" REPNE SCASB MOV ECX,EDX JE .70: MOV EDI,ESI MOV AL,"*" REPNE SCASB MOV ECX,EDX JE .70: RstSt [Ea.Status],eaWildcarded .60:MOV EDX,ECX .70:SysAssignFile Ea.SrcFile,ESI,EDX ; Resolve wildcard using SysEachFile, and invoke callback procedure EaAssemble ; on each resolved source file. Succesfull callback will set flag eaAtLeast1File. SysEachFile Ea.SrcFile,EaAssemble JSt [Ea.Status],eaWildcarded | eaAtLeast1File,.40: ; Fetch and assemble the next source. ; Filename read from cmdline was not found, perhaps no file matched the mask. PUSH EDX,ESI ; ESI,EDX is nonwildcarded filename from cmdline. MOV EAX,ESP Msg '8010',EAX ; No such file "!1S". POP ESI,EDX JMP .40: ; Fetch the next argument from cmdline. .80: ; All cmdline arguments were processed. CMP [Ea.ArgNr],1 Msg cc=NA,'8000' ; No input file specified. .90:Invoke EaDestroy MOV ESP,[Ea.StackOrg] SysExitProcess [Ea.Errorlevel] ; Shutdown EuroAssembler. ENDP EaMain::
EaCreate Procedure StackOrg Clear Ea MOV ESI,EaVersion MOV EDI,Ea.Version MOVSD ; Copy the version string "YYYYMMDD" defined statically when €ASM was build. MOVSD ; Set €ASM system %variables values into Ea object. SysGetEuroasmOS MOV [Ea.EuroasmOS],EAX SysGetUTC ; Get real system time as the number of seconds since 1.1.1970 to EAX. MOV [Ea.TimeStart],EAX MOV [Ea.Eaopt.TimeStamp],EAX ; Initialize nominal system time, too. ; Manage machine stack SS:ESP. MOV EBX,[%StackOrg] MOV [Ea.StackOrg],EBX ; EBX=Top of stack. SysGetStackSize ; EAX=size of this running €ASM reserved machine stack (SS:ESP). Msg cc=C,'9210' SUB EBX,EAX ; EBX=bottom of stack. ADD EBX,4K ; A safety reserve. MOV [Ea.StackBottom],EBX ; When ESP gets below this value, F9210 is reported. ; Pool of heap memory for €ASM own memory management. PoolCreate Size=%EaPoolSize, ErrorHandler=EaMallocError MOV [Ea.Pool],EAX ; Stack of universal reserveable buffers. StackCreate EAX,8,Depth=%EaStackDepth ; BufferStack items have two DWORDs each. MOV [Ea.BufferStack],EAX ; Initialize EUROASM options with factory defaults built-ineuroasm.exebody. Invoke EaIniAssemble,EaIniFileDefault,EaIniFileDefaultEnd, Ea.Eaopt, Ea.Pgmopt EndProcedure EaCreate
EaDestroy Procedure MOV ECX,[Ea.StmCount] JECXZ .90: ; If no statement was assembled. SysGetUTC SUB EAX,[Ea.TimeStart] JNZ .50: INC EAX ; Round up the total assembly duration to at least 1 second. .50:MOV EBX,EAX MOV EAX,[Ea.MemPeak] SHR EAX,10 Msg '0980',EAX,[Ea.StmCount],EBX ; Peak memory allocation !1D KB. !2D statements assembled in !3D s. .90:Msg '0990',[Ea.Errorlevel] ; EuroAssembler terminated with errorlevel !1D. MOV EDX,[Ea.Pool] PoolDestroy EDX Msg cc=C,'2575','Ea',EDX ; Deallocation of virtual memory !1C.Pool !2Hh failed. EndProcedure EaDestroy
Ea.SrcFile
. The source filename might have been specified with wildcards.
Usually the whole file is assembled but possible suboperation of source
can be specified with Ea.SubPtr,Ea.SubSize
.
{1..%&-40}
.
Ea.SubSize=0 when no suboperation was specified.EaAssemble Procedure LEA EAX,[EDI+WIN32_FIND_DATAW.LastWriteTime] SysFileTimeToDosDateTime EAX ; Source filetime is needed in OMF output format dependency record. MOV [Ea.SrcTime],EAX SetSt [Ea.Status],eaAtLeast1File Invoke SrcCreate:: Invoke SrcAssemble:: Invoke SrcDestroy:: CMP [Ea.Errorlevel],9 CMC ; Return CF on fatal Euroasm error, such as bad memory allocation or stack overflow. EndProcedure EaAssemble ; This prevents SysEachFile from further wildcard expansions.
EaMallocError:: PROC Msg '9110' ; Cannot allocate virtual memory. RET ENDP EaMallocError
EaBufferReserve Procedure RequestingObject BufRec LocalVar Size=8 MOV EBX,[Ea.BufferStack] MOV ESI,[EBX+STACK.Ptr] SUB ECX,ECX .10: SUB ESI,[EBX+STACK.Size] CMP ESI,[EBX+STACK.Bottom] JNB .50: ; No released buffer found on stack. BufferCreate [EBX+STACK.Pool],Size=%EaBufferSize JC .F9313: LEA EDI,[%BufRec] MOV [EDI],EAX MOV [EDI+4],ECX StackPush EBX,EDI JNC .30: .F9313:SUB EAX,EAX Msg '9313',[%RequestingObject] ; Alloc.error reserving buffer for !1H. STC JMP .90: .30: MOV ESI,EAX .50: CMP [ESI+4],ECX ; ESI is at Qword which describes the buffer. JNZ .10: ; The buffer is occupied. Try the lower one. LODSD MOV ECX,[%RequestingObject] TEST ECX JNZ .80: DEC ECX ; If RequestingObject was not specified, use -1 (any nonzero is OK). .80: MOV [ESI],ECX PUSHD [EAX+BUFFER.Bottom] POPD [EAX+BUFFER.Ptr] ; BufferClear. .90: MOV [%ReturnEAX],EAX EndProcedure EaBufferReserve
EaBufferRelease Procedure BufferPtr MOV ECX,[%BufferPtr] MOV EBX,[Ea.BufferStack] JECXZ .90: MOV ESI,[EBX+STACK.Ptr] .10: SUB ESI,[EBX+STACK.Size] CMP ESI,[EBX+STACK.Bottom] JB .90: CMP [ESI],ECX JNE .10: MOVD [ESI+4],0 .90:EndProcedure EaBufferRelease
EaBufferSort Procedure PtrBuffer BufferRetrieve [%PtrBuffer] SAR ECX,2 ; PtrBuffer contains DWORD pointers. ECX is now the number of sorted objects. JZ .90: ShellSort ESI,ECX,4,.CmpObjNames .CmpObjNames PROC1 ; Callback subprocedure to compare-by-name two objects, ; whose pointers are pointed to with ESI and EDI. PUSH EBX,ECX ; ShellSort needs those registers preserved. MOV EBX,[ESI] ; Pointer to the object 1. MOV EDX,[EDI] ; Pointer to the object 2. TEST EBX JZ .C9: TEST EDX JZ .C9: MOV ECX,[EBX+4] ; Size of the .Name 1. CMP ECX,[EDX+4] ; Size of the .Name 2. JBE .C2: MOV ECX,[EDX+4] .C2: CLC ; ECX is now the shorter size of both names. JECXZ .C9: ; No swap if the names are empty. MOV EBX,[EBX] ; Pointer to the .Name 1. MOV EDX,[EDX] ; Pointer to the .Name 2. TEST EBX JZ .C9: TEST EDX JZ .C9: .C3: MOV AL,[EBX] ; Load a character from .Name 1. MOV AH,[EDX] ; Load a character from .Name 2. INC EBX ; Prepare pointer to the next character. INC EDX ; Prepare pointer to the next character. PUSH EAX ; First compare case-insensitively. OR AX,0x2020 ; Simplified conversion to lowercase. CMP AH,AL ; Compare case-insensitive first (C-I). POP EAX ; Restore case. JB .C5: ; If the C-I order requires swapping. JA .C9: ; If the C-I order is compliant, return with CF=0. CMP AH,AL ; Otherwise compare case-sensitively (C-S). JB .C5: ; If the C-S order requires swapping. JA .C9: ; If the C-S order is compliant, return with CF=0. .C4: LOOP .C3: ; If not decided yet, go check the next characters. ; The shorter part of the name matched exactly. MOV EBX,[ESI] ; Pointer to the object 1. MOV EDX,[EDI] ; Pointer to the object 2. MOV ECX,[EBX+4] ; Name 1 size. CMP [EDX+4],ECX ; Compare with Name 2 size. JB .C5: ; If the order requires swapping. JA .C9: ; If the order is compliant, return with CF=0. ; Both objects have identical names. This happens only when sorting global symbols. Compare by scope. MOV EAX,[EBX+SYM.Status] MOV ECX,[EDX+SYM.Status] AND EAX,symScopeMask AND ECX,symScopeMask CMP ECX,EAX JAE .C9: ; If the order is compliant, return with CF=0. .C5: MOV EAX,[ESI] ; Object names are not in ascending order, swap them. XCHG EAX,[EDI] MOV [ESI],EAX STC ; Signalize to the caller that objects were swapped. .C9:POP ECX,EBX RET ENDP1 .CmpObjNames .90:EndProcedure EaBufferSort
EaBufferAlign Procedure Buffer, Alignment MOV EBX,[%Buffer] BufferRetrieve EBX Invoke ExpAlign::,ECX,[%Alignment],0 MOV [%ReturnEAX],ECX ; Number of stored NULL bytes. XOR EDX,EDX CMP ECX,EDX JZ .90: SHR ECX,1 JNC .20: BufferStoreByte EBX,EDX .20: SHR ECX,1 JNC .40: BufferStoreWord EBX,EDX .40: JECXZ .90: .50: BufferStoreDword EBX,EDX LOOP .50: .90:EndProcedure EaBufferAlign
EaStreamAlign Procedure Stream, Alignment, Stuff MOV EBX,[%Stream] StreamGetSize EBX Invoke ExpAlign::,EAX,[%Alignment],0 ; Returns ECX=stuff size. MOV [%ReturnEAX],ECX ; Number of stored stuff bytes. JECXZ .90: ; Done when %Stream is already aligned. MOV EDX,[%Stuff] SHR ECX,1 JNC .20: StreamStoreByte EBX,DL .20: SHR ECX,1 JNC .40: StreamStoreWord EBX,DX .40: JECXZ .90: .50: StreamStoreDword EBX,EDX LOOP .50: .90:EndProcedure EaStreamAlign
EaId2Fs Procedure IdNamePtr, IdNameSize, OutBuffer MOV ECX,[%IdNameSize] MOV ESI,[%IdNamePtr] JECXZ .90: .10:LODSB CMP AL,'?' JNE .20: MOV AL,"_" ; Replace question mark with underscore. .20:BufferStoreByte [%OutBuffer],EAX LOOP .10: .90:EndProcedure EaId2Fs
EaFs2Id Procedure FsNamePtr, FsNameSize, OutBuffer MOV ECX,[%FsNameSize] MOV ESI,[%FsNamePtr] MOV EDI,[%OutBuffer] JECXZ .90: LEA EDX,[ESI+ECX] ExpClassify [ESI] TEST AH,expLetter|expFullstop JNZ .30: ; Go and store a valid character from AL. TEST AH,expDigit ; Test if the filename begins with a digit '0'..'9'. JZ .30: MOV AL,"`" ; Prefix the digit with leading letter (grave). .20:BufferStoreByte EDI,EAX .30:CMP ESI,EDX JNB .90: LODSB ExpClassify AL TEST AH,expLetter|expDigit|expFullstop JNZ .40: MOV AL,"_" ; Replace unacceptable character with underscore. .40:BufferStoreByte EDI,EAX JMP .30: .90:EndProcedure EaFs2Id
euroasm.inifile to EAOPT and PGMOPT structures.
euroasm.inimapped in memory.
EaIniAssemble Procedure IniPtr, IniEnd, Eaopt, Pgmopt ErrPar LocalVar Size=8 ; Parameter for error message. EaIniStm LocalVar Size=SIZE#STM ; Temporary fake statement to provide position of error in ini file. EaStackCheck RstSt [Ea.Status],eaIniSectEUROASM | eaIniSectPROGRAM LEA ESI,[%EaIniStm] Invoke StmCreate::,ESI PUSHD [Src.CurrentStm::] ; Save the current statement in source and MOV [Src.CurrentStm::],ESI ; replace it with a temporary one. .10: MOV EDI,[%IniPtr] LEA ESI,[%EaIniStm] MOV [ESI+STM.LinePtr],EDI ; Provide the line position for error message. MOV ECX,[%IniEnd] MOV ESI,EDI MOV AL,10 SUB ECX,EDI JNA .90: REPNE SCASB MOV [%IniPtr],EDI ; ESI..EDI is the current line. %IniPtr specifies the start of the next line. LEA EDX,[%ErrPar] MOV EAX,EDI SUB EAX,ESI StripSpaces ESI,EAX MOV [EDX+0],ESI ; Prepare error message parameter. MOV [EDX+4],EAX TEST EAX JZ .10: .20: CMP ESI,EDI ; The line at ESI can be a comment, [EUROASM], [PROGRAM], or Identifier=value. JNB .10: ; Skipt empty line. LODSB CMP AL,'[' JNE .50: RstSt [Ea.Status],eaIniSectEUROASM + eaIniSectPROGRAM MOV EDX,ESI ; Start of section name. .30: CMP ESI,EDI JBE .40: .W3701:LEA ECX,[%ErrPar] Msg '3701',ECX ; Unknown section "!1S" in "euroasm.ini" file. JMP .10: .40: LODSB CMP AL,']' JNE .30: LEA EBX,[ESI-1] ; End of section name. SUB EBX,EDX ; String EDX..EBX is section name (PROGRAM or EUROASM). StripSpaces EDX,EBX LEA ECX,[%ErrPar] MOV [ECX+0],EDX MOV [ECX+4],EBX Invoke DictLookup::, DictIniSect::, EDX,EBX JC .W3701: SetSt [Ea.Status],EAX ; EAX is eaIniSectEUROASM or eaIniSectPROGRAM. JMP .10: .50: CMP AL,';' JE .10: CMP AL,'#' ; Comment line ineuroasm.inimay begin with ; or #. JE .10: LEA EDX,[ESI-1] ; EDX points to "ident= value". Invoke ExpParseKeyName::,EDX,EDI ; Returns EAX behind the equal sign. JNC .60: .W3705:LEA ECX,[%ErrPar] Msg '3705',ECX ; Unexpected text "!1S" in "euroasm.ini" file. JMP .10: .60: Invoke ExpParseKeyValue::,EAX,EDI ; Returns ESI,ECX value string. JC .W3705: DEC EAX SUB EAX,EDX ; EDX,EAX is now key name. ESI,ECX is key value. JSt [Ea.Status],eaIniSectEUROASM, .70: JSt [Ea.Status],eaIniSectPROGRAM, .80: LEA ECX,[%ErrPar] Msg '3710',ECX ; Option "!1S" is in undefined section of "euroasm.ini" file. JMP .10: .70: Invoke EaoptAssemble::,[%Eaopt],EDX,EAX,ESI,ECX JMP .10: ; The next line. .80: Invoke DictLookup::, DictPgmopt::, EDX,EAX LEA EDX,[%ErrPar] Msg cc=C,'3730',EDX ; "!1S" is unknown option in [PROGRAM] section. JC .10: Invoke PgmoptAssemble::, [%Pgmopt],EAX,ESI,ECX, JMP .10: .90: LEA ESI,[%EaIniStm] Invoke StmDestroy::,ESI POPD [Src.CurrentStm::] ; Restore the current statement in source. EndProcedure EaIniAssemble
euroasm.iniand create this file if it didn't exist.
EaIniGlobal Procedure GlobalIniName LocalVar Size=256 ; Reserve MAX_PATH_SIZE room for global euroasm.ini filename. LEA EBX,[%GlobalIniName] ; Find the global option file name. SysGetExe EBX ; Fill %GlobalIniName with full path to euroasm.exe. FileNameParse EBX LEA EDX,[MAX_PATH_SIZE-12+EBX] CMP EAX,EDX Msg cc=A,'8020',EBX ; Filename too long. JA .30: MOV EDI,EAX ; Position of file name withing the full path. MOV ESI,=B"euroasm.ini" MOV ECX,12 REP MOVSB SysOpenFileMap Ea.IniFile,EBX JC .10: Msg '0070',EBX ; Assembling global option file "!1$". ADD EAX,ESI Invoke EaIniAssemble,ESI,EAX, Ea.Eaopt, Ea.Pgmopt SysCloseFile Ea.IniFile JMPS .30: .10:SysCreateFile Ea.IniFile,EBX ; Global euroasm.ini was not found, lets try to create it. JC .20: MOV ESI,EaIniFileDefault ; Factory-default. MOV ECX,EaIniFileDefaultEnd MOV EBX,Ea.IniFile SUB ECX,ESI SysWriteFile EBX,ESI,ECX ; Returns CF if the creation of global "euroasm.ini" failed. LEA EBX,[EBX+FILE.Name] Msg cc=NC,'0050',EBX ; Global option file "!1$" was created. .20:Msg cc=C, '0060',EBX ; Global option file "!1$" could not be created. SysCloseFile Ea.IniFile .30:CopyTo Ea.EaoptIni,Ea.Eaopt,Size=SIZE#EAOPT EndProcedure EaIniGlobal
; Ad hoc debug subprograms. Not to be released.
EUROASM DEBUG=ENABLED
.=B"%^Proc"
at invocation.
=B"%^SourceName"
at invocation.
%^SourceLine"
at invocation. Invoke EaDisplayPosition::, =B"%^Proc", =B"%^SourceName", %^SourceLine
EaDisplayPosition Procedure ProcName$Ptr,SourceName$Ptr,SourceLineNr Msg '1900',[%ProcName$Ptr],[%SourceName$Ptr],[%SourceLineNr] ; Position "!1$" at "!2$"{!3D} EndProcedure EaDisplayPosition
EUROASM DEBUG=ENABLED
.=B"%^SourceName"
at invocation.
%^SourceLine"
at invocation. Invoke EaDisplayPgm::, EBX, =B"%^SourceName", %^SourceLine
Debug %IF %^DEBUG ; Internal EuroAssembler debugging. EaDisplayPgm Procedure Pgm ,SourceName$Ptr,SourceLineNr ; Display program objects PGM,SYM,SSS,RELOC. RelocTop LocalVar ; End of RELOC array in current segment. SssRange LocalVar Size=44 ; Va000000..FFFFFF(0123),Fa000000,Rva000000 ; 0....5...10...15...20...25...30...35...40.. Msg '1000' ; Separator. MOV EBX,[%Pgm] ; 1920 PGM^!1H:St=!2H, base program ******** !3S ******** EaDisplayPgm at "!4$"{!5D}',0 Msg '1920',EBX,[EBX+PGM.Status],EBX,[%SourceName$Ptr],[%SourceLineNr] ; Display the base program EBX. CALL .PgmDisplay: ListGetFirst [EBX+PGM.ModulePgmList] JZ .90: .10:MOV EBX,EAX ; 1921 PGM^!1H:St=!2H,module **** !3S ****',0 Msg '1921',EBX,[EBX+PGM.Status],EBX ; Display the module program EBX. CALL .PgmDisplay: ListGetNext EBX JNZ .10: .90:EndProcedure EaDisplayPgm EaDisplayPgm.PgmDisplay PROC ; Display program EBX. ListGetFirst [EBX+PGM.SymList] JZ .30: .20:MOV ESI,[EAX+SYM.Section] ; Display the symbol EAX. MOV ECX,[EAX+SYM.Status] MOV DL,'X' JSt ECX,symExport,.25: MOV DL,'P' JSt ECX,symPublic,.25: MOV DL,'I' JSt ECX,symImport,.25: MOV DL,'E' JSt ECX,symExtern,.25: MOV DL,'G' JSt ECX,symGlobal | symGlobalRef,.25: MOV DL,'S' .25:; LEA ECX,[EAX+SYM.DllNamePtr] MOV CL,[EAX+SYM.NameDynIndex] MOV CH,[EAX+SYM.NameIndex] ; 1922 SYM^!1H:Sc''!2Z'',St!3H,Se!4H,Sy!5H,Di!6W,!7S,[!8S]:!9H Msg '1922',EAX,EDX,[EAX+SYM.Status],ESI,[EAX+SYM.SymbPtr],ECX,EAX,ESI,[EAX+SYM.OffsetLow] ListGetNext EAX JNZ .20: ; The next symbol. .30:LEA EDI,[%SssRange] ; Preformat %SssRange. MOVW [EDI+00],'Va' MOVW [EDI+08],'..' MOVB [EDI+16],'(' MOVD [EDI+21],'),Fa' MOVD [EDI+31],',Sva' MOVB [EDI+41],0 ListGetFirst [EBX+PGM.SssList] JZ .80: .40:PUSH EAX ; Display the SSS object EAX. MOV ESI,EAX ; Prepare D1923 Bottom..Top(size),Fa in %SssRange. MOV EAX,[ESI+SSS.BottomLow] LEA EDI,[%SssRange+02] StoH EDI,Size=6 MOV EAX,[ESI+SSS.TopLow] LEA EDI,[%SssRange+10] StoH EDI,Size=6 MOV EAX,[ESI+SSS.TopLow] MOV EDX,[ESI+SSS.TopHigh] SUB EAX,[ESI+SSS.BottomLow] SBB EDX,[ESI+SSS.BottomHigh] LEA EDI,[%SssRange+17] StoH EDI,Size=4 MOV EAX,[ESI+SSS.BottomFA] LEA EDI,[%SssRange+25] StoH EDI,Size=6 LEA EDI,[%SssRange+35] MOV EAX,[ESI+SSS.SVA] StoH EDI,Size=6 POP EAX .45:LEA EDI,[%SssRange] ; '1923 SSS^!1H:St!2H,!3$,Sy!4H,Ni!5D,Si!6D,Sg!7H,Gr!8H',[!9S] Msg '1923',EAX,[EAX+SSS.Status],EDI,[EAX+SSS.SymPtr],[EAX+SSS.NameIndex],\ [EAX+SSS.SegmIndex],[EAX+SSS.SegmPtr],[EAX+SSS.GroupPtr],EAX BufferRetrieve [EAX+SSS.RelocBuffer] ; Display RELOC objects of the segment EAX. LEA EDX,[ESI+ECX] MOV [%RelocTop],EDX .50:CMP ESI,[%RelocTop] JNB .75: MOV EDX,ESI BufferRetrieve [EAX+SSS.EmitBuffer] ; ESI,ECX=emitted contents. XCHG EDX,ESI ; Restore ESI=^RELOC, EDX=^1st emitted byte. ADD EDX,[ESI+RELOC.OrgLow] MOV EDI,[EDX] ; EDI=relocated storage unit in emitted data (WORD|DWORD). MOV ECX,[ESI+RELOC.Status] type %FOR Para,AbsVA,AbsRVA,Rel,Far,Sym,Dyn,PLT,GOT,GOToff,GOTrel LEA EDX,[=B"%type"] JSt ECX,reloc%type,.60: %ENDFOR type LEA EDX,[=B"None"] .60:JNSt ECX,relocWidth16,.65: ; RELOC^!1H:St!2H,Org!3H:!4H,Ad=!5H,Ob=!6W,Sym:!7H,!8S:!9$ Msg '1924',ESI,[ESI+RELOC.Status],[ESI+RELOC.Section],[ESI+RELOC.OrgLow], \ 16bit [ESI+RELOC.AddendLow],EDI,[ESI+RELOC.Symbol],[ESI+RELOC.Symbol],EDX JMP .70: .65: ; RELOC^!1H:St!2H,Org!3H:!4H,Ad=!5H,Ob=!6H,Sym:!7H,!8S:!9$ Msg '1925',ESI,[ESI+RELOC.Status],[ESI+RELOC.Section],[ESI+RELOC.OrgLow], \ 32bit [ESI+RELOC.AddendLow],EDI,[ESI+RELOC.Symbol],[ESI+RELOC.Symbol],EDX .70:ADD ESI,SIZE# RELOC JMP .50: ; The next RELOC. .75:ListGetNext EAX JNZ .40: ; The next SSS object. .80:RET ENDPROC EaDisplayPgm.PgmDisplay: EaPoolDisplay Procedure aPool,LinePtr ; Display pool blocks. MOV EAX,[%LinePtr] ; 1912 Allocated memory pool at source line {!1D}: Msg '1912',EAX MOV EBX,[%aPool] SUB ECX,ECX MOV ESI,[EBX+POOL.Last] .10:TEST ESI JZ .20: ADD ECX,[ESI] MOV ESI,[ESI+4] JMP .10: .20: ; 1913 Pool=!1H, Gran=!2K, Total=!3H=!3K, Size=!4H=!4K Msg '1913',EBX,[EBX+POOL.Gran],ECX,[EBX-8] MOV EAX,[EBX-8] LEA EAX,[EBX+EAX-8] ; 1914 Pool.Prev=!1H, Last=!2H, Ptr=!3H, Top=!4H. Msg '1914',[EBX-4],[EBX+POOL.Last],[EBX+POOL.Ptr],EAX MOV EAX,[EBX+POOL.Last] .50:TEST EAX JZ .90: MOV ESI,[EAX] ; Size. LEA EDI,[EAX+4] ; Prev. LEA EDX,[EAX+4+ECX] ; 1915 Poolblock=!1H, Prev=!2H, bottom=!3H, top=!4H. Msg '1915',EAX,ESI,EDI,EDX MOV EAX,ESI JMP .50: .90: EndProcedure EaPoolDisplay INCLUDE1 debug.htm DebugOutput:: PROC1 StdOutput ESI,Size=ECX RET ENDP1 DebugOutput:: %ENDIF Debug
Semiinline macros hired in EuroAssembler are for the first time dummy-expanded
here in the module ea.htm
. Their @RTprocedures are declared as PUBLIC
in this module and they are declared as EXTERN in all other modules.
This prevents the runtime code from being repeatedly emitted in each separately assembled module, which would unnecessarily blow up the final PE size.
; Dummy expansion of semiinline macros creates their runtime procedures here. PoolCreate PoolNew 0,0 PoolDestroy 0 BufferCreate 0,0,0 BufferNew 0,0 BufferResize 0,0,0 BufferStore 0,0,0 BufferStoreByte 0,0 BufferStoreWord 0,0 BufferStoreDword 0,0 BufferStoreQword 0,0 BufferStorePascalString 0,0 GetLength$ 0 IiAbort 0 IiAbortIfNotST0 IiAllowLocking Operand1 IiDispatchFormat IiDispatchLocation 0 IiDispSize Operand1 IiEmitImm Operand1,BYTE IiEmitImm2 Operand1 IiEmitOpcode IiImmSize Operand1 IiDataSize Operand1 IiStringDestination Operand1 IiStringSource Operand1 ListCreate 0,0 ListNew 0 ListStore 0,0 ListInsert 0,0,0 ListRemove 0,0 StackCreate 0,0 StackPush 0,0 StreamCreate 0 StreamStore 0, StreamDump 0,0 Clear 0 Compare 0,0,0 CopyTo 0,0 LodD StoD StoQD Align=left StoH Align=left ShellSort 0,0,0,0 FileAssign 0,0 FileEach 0,0 FileMapOpen 0 FileMkDir 0 FileNameParse 0 FileCreate 0 FileWrite 0 FileClose 0 SysGetFileSize 0 SysGetFileTime 0
ENDPROGRAM ea