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.
ea PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
INCLUDEHEAD euroasm.htm, \ Interface (structures, symbols and macros) of other modules used in this source.
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
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 may be allocated on demand later.
%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 containEa.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 of euroasm.exe
reserved 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 when euroasm.exe
launched, as seconds since midnight Jan 1st 1970 UTC.
.SrcTime D D ; Last write time of currently processed source file.
.MemPeakSrc D D ; Memory allocated by Src.Pool.
.StmCount D D ; Total number of statements parsed.
;+40h
.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 FILE euroasm.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.
euroasm.exe.
[.bss] Ea:: DS EA ; Instance of the main EuroAssembler object. [.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 virtual euroasm.ini
contents 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 option NOWARN=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
MOV ECX,Ea.EuroasmOS
Msg '0010',EAX,ECX ; EuroAssembler version !1S !2$ started.
POP EAX,EAX
Msg '0020',EBX ; Current directory is "!1$".
Invoke EaIniGlobal ; Compile global euroasm.ini
to 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 it may have wildcards.
; String may look like file.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 wildcards 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
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.
MOV EDI,%EaPoolSize
PoolCreate Size=EDI, 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-in euroasm.exe
body.
Invoke EaIniAssemble,EaIniFileDefault,EaIniFileDefaultEnd, Ea.Eaopt, Ea.Pgmopt
EndProcedure EaCreate
EaDestroy Procedure
MOV ECX,[Ea.StmCount]
TEST ECX
JZ .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 ; EBX is the duration of assembly.
MOV EDX,[Ea.Pool]
PoolDestroy EDX
Msg cc=C,'2575','Ea',EDX ; Deallocation of virtual memory !1C.Pool !2Hh failed.
ADD EAX,[Ea.MemPeakSrc]
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.
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 of input source file was specified.
EaAssemble Procedure
LEA ESI,[EBX+FILE.Name]
SysGetFileTime ESI
MOV [Ea.SrcTime],EAX
SetSt [Ea.Status],eaAtLeast1File
Invoke SrcCreate::
Invoke SrcAssemble::
Invoke SrcDestroy::
CMP EAX,[Ea.MemPeakSrc::]
JNA .80:
MOV [Ea.MemPeakSrc::],EAX
.80: 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.
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 pointer to 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:
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 in euroasm.ini
may 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.
euroasm.inihas a fixed name
%AppData%\eurotool\euroasm.ini in MS Windows, or
/etc/eurotool/euroasm.ini in Linux.
EaIniGlobal Procedure
Invoke EaBufferReserve::,%^PROC
MOV EBX,EAX ; Temporary buffer for the name of configuration file.
%IF "%eaos" === "win"
SysGetEnvironment =B"AppData",7,EBX
BufferStore EBX,=B"\eurotool\euroasm.ini",22
%ELSE
BufferStore EBX,=B"/etc/eurotool/euroasm.ini",26
%ENDIF
BufferRetrieve EBX
Invoke EaBufferRelease::,EBX
MOV EBX,ESI
SysMkDir Ea.IniFile
SysOpenFileMap Ea.IniFile,EBX ; Open the file with name in EBX.
JC .50:
Msg '0070',EBX ; Assembling global option file "!1$".
ADD EAX,ESI
Invoke EaIniAssemble,ESI,EAX, Ea.Eaopt, Ea.Pgmopt
SysCloseFile Ea.IniFile
JMP .70:
.50:SysCreateFile Ea.IniFile,EBX ; Global euroasm.ini was not found, lets try to create it.
JC .60:
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.
.60:Msg cc=C, '0060',EBX ; Global option file "!1$" could not be created.
SysCloseFile Ea.IniFile
.70:CopyTo Ea.EaoptIni,Ea.Eaopt,Size=SIZE#EAOPT
EndProcedure EaIniGlobal
; The following are 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
DebugInternal %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
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
%ENDIF DebugInternal
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. BufferCreate 0,0,0 BufferNew 0,0 BufferResize 0,0,0 BufferStore 0,0,0 BufferStoreByte 0,0 BufferStoreDword 0,0 BufferStorePascalString 0,0 BufferStoreQword 0,0 BufferStoreWord 0,0 Clear 0 Compare 0,0,0 CopyTo 0,0 FileAssign 0,0 FileClose 0 FileCreate 0 FileEach 0,0 FileMapOpen 0 FileMkDir 0 FileNameParse 0 FileWrite 0 GetArg 0 GetLength$ 0 IiAbort 0 IiAbortIfNotST0 IiAllowLocking Operand1 IiDataSize Operand1 IiDispatchFormat IiDispatchLocation 0 IiDispSize Operand1 IiEmitImm Operand1,BYTE IiEmitImm2 Operand1 IiEmitOpcode IiImmSize Operand1 IiStringDestination Operand1 IiStringSource Operand1 ListCreate 0,0 ListInsert 0,0,0 ListNew 0 ListRemove 0,0 ListStore 0,0 LodD PoolCreate Size=%EaPoolSize PoolDestroy 0 PoolNew 0,0 ShellSort 0,0,0,0 StackCreate 0,0 StackPush 0,0 StoD StoH Align=left StoQD Align=left StreamCreate 0 StreamDump 0,0 StreamStore 0, SysGetFileSize 0 SysGetFileTime 0 SysGetEnvironment 0,0,0
ENDPROGRAM ea