This source file ea.htm
contains 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, object Ea
is defined statically.
ea PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32 INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
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. EUROASM DEBUG=NO
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 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.
euroasm.exe.
[.bss] Ea:: DS EA [.data] EaVersion:: DB "%^DATE" ; Date "YYYYMMDD" when was €ASM 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 no more arguments. MOV EBX,ESI ; Pointer to 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. ; EBX,EDX is option key name, e.g."NOWARN". ESI,ECX is valid option value, e.g. "2100". Invoke DictLookup::, DictEaoptMisc::,EBX,EDX 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 no more arguments. MOV EBX,ESI ; Pointer to 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 valid cmdline option. Invoke DictLookup::, DictEaoptStatus::,EBX,EDX JNC .40: ; Skip valid cmdline option. Invoke DictLookup::, DictEaoptFea::,EBX,EDX JNC .40: ; Skip 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 ; 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 assembled. SysGetUTC SUB EAX,[Ea.TimeStart] JNZ .50: INC EAX ; Total assembly took 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. ; This prevents SysEachFile from further wildcard expansions. EndProcedure EaAssemble
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: ; ESI is at Qword which describes the buffer. CMP [ESI+4],ECX JNZ .10: ; The buffer is occupied. Try 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 ; Buffer contains DWORD pointers. ECX is now 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 theese registers preserved. MOV EBX,[ESI] ; Pointer to object 1. MOV EDX,[EDI] ; Pointer to object 2. TEST EBX JZ .C9: TEST EDX JZ .C9: MOV ECX,[EBX+4] ; Name 1 size. CMP ECX,[EDX+4] ; Name 2 size. JBE .C2: MOV ECX,[EDX+4] .C2: CLC ; ECX is now the shorter one of both names. JECXZ .C9: ; No swap if name is empty. MOV EBX,[EBX] ; Name 1 ptr. MOV EDX,[EDX] ; Name 2 ptr. 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. 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. .C4: LOOP .C3: ; If not decided yet, go check the next characters. ; The shorter part of the name matches exactly. MOV EBX,[ESI] ; Pointer to object 1. MOV EDX,[EDI] ; Pointer to 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. ; 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: .C5: MOV EAX,[ESI] ; Object names are not in ascending order, swap them. XCHG EAX,[EDI] MOV [ESI],EAX STC ; Signalize to 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 MOV EBX,[%Stream] StreamGetSize EBX MOV ECX,EAX 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: 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: TEST AH,expDigit JZ .30: MOV AL,"`" ; Prefix 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 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 ; 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::] MOV [Src.CurrentStm::],ESI .10: MOV EDI,[%IniPtr] LEA ESI,[%EaIniStm] MOV [ESI+STM.LinePtr],EDI ; Provide 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 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: ; The line at ESI can be a comment, [EUROASM], [PROGRAM], or Identifier=value. .20: CMP ESI,EDI 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. ; String EDX..EBX is section name (PROGRAM or EUROASM). SUB EBX,EDX 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::] EndProcedure EaIniAssemble
euroasm.iniand create this file if it didn't exist.
EaIniGlobal Procedure GlobalIniName LocalVar Size=256 ; MAX_PATH_SIZE ; Room for global euroasm.ini filename. ; Find global option file name. LEA EBX,[%GlobalIniName] 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: ; Global euroasm.ini not found, lets try to create it. SysCreateFile Ea.IniFile,EBX JC .20: MOV ESI,EaIniFileDefault MOV ECX,EaIniFileDefaultEnd MOV EBX,Ea.IniFile SUB ECX,ESI SysWriteFile EBX,ESI,ECX 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"%^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. SssRange LocalVar Size=28 ; 0000..FFFF(0123) ; 0....5...10...15 Msg '1000' ; Separator. MOV EBX,[%Pgm] ; 1920 PGM^!1H:St=!2H,program !3S ******** EaDisplayPgm at "!4$"{!5D} 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 Msg '1921',EBX,[EBX+PGM.Status],EBX ; Display the module program EBX. CALL .PgmDisplay: ListGetNext EBX JNZ .10: .PgmDisplay PROC1 ; Display program EBX. ListGetFirst [EBX+PGM.SymList] JZ .20: ; Display the symbol EAX. .10:MOV ESI,[EAX+SYM.Section] MOV ECX,[EAX+SYM.Status] MOV DL,'X' JSt ECX,symExport,.15: MOV DL,'P' JSt ECX,symPublic,.15: MOV DL,'I' JSt ECX,symImport,.15: MOV DL,'E' JSt ECX,symExtern,.15: MOV DL,'G' JSt ECX,symGlobal+symGlobalRef,.15: MOV DL,'S' .15:Msg '1922',EDX,EAX,[EAX+SYM.Status],ESI,ESI,[EAX+SYM.OffsetLow],EAX,[EAX+SYM.NameIndex] ; SYM^!2H:Sc''!1Z'',St!3H,Se!4H,[!5S]:!6H,!7S,Ni!8D,',0 ListGetNext EAX JNZ .10: ; The next symbol. .20:LEA EDI,[%SssRange] MOVW [EDI+4],'..' MOVB [EDI+10],'(' MOVD [EDI+15],') ' ListGetFirst [EBX+PGM.SssList] JZ .80: .30:PUSH EAX,EDI ; Display the SSS object EAX. MOV ESI,EAX MOV EAX,[ESI+SSS.BottomLow] LEA EDI,[%SssRange+0] AND EAX,0x0000_FFFF StoH EDI,Size=4 MOV EAX,[ESI+SSS.TopLow] LEA EDI,[%SssRange+6] AND EAX,0x0000_FFFF StoH EDI,Size=4 PUSH ESI BufferRetrieve [ESI+SSS.EmitBuffer] POP ESI MOV AX,CX LEA EDI,[%SssRange+11] StoH EDI,Size=4 POP EDI,EAX MOV ECX,[EAX+SSS.Status] MOV DL,'I' JSt ECX,sssImport,.35: MOV DL,'E' JSt ECX,sssExtern,.35: MOV DL,'G' JSt ECX,sssGroup,.35: MOV DL,'S' JSt ECX,sssSegment,.35: MOV DL,'?' .35:BufferRetrieve [EAX+SSS.EmitBuffer] ; SSS^!2H:''!1Z'',St!3W,!4$Sg!5H Gr!6H Sm!7H,[!8S],Ni!9D',0 Msg '1923',EDX,EAX,[EAX+SSS.Status],EDI, \ [EAX+SSS.SegmPtr],[EAX+SSS.GroupPtr],[EAX+SSS.SymPtr],EAX,[EAX+SSS.NameIndex] PUSHAD BufferRetrieve [EAX+SSS.RelocBuffer] JECXZ .50: MOV EDX,SIZE#RELOC .40: MOV EAX,[ESI+RELOC.Status] ; Display the relocation ESI. SHR EAX,8 MOV AL,[ESI+RELOC.Status] ; AH now contains relocWidthMask+relocExtAttr ; RELOC^!1H:St!2H,Org!3H:!4H,Fr!5H,Tg!6H:!7H' Msg '1925',ESI,[ESI+RELOC.Status],[ESI+RELOC.Section], \ [ESI+RELOC.OrgLow],[ESI+RELOC.Frame],[ESI+RELOC.Target],[ESI+RELOC.DispLow] ADD ESI,EDX SUB ECX,EDX JA .40: ; The next RELOC. .50:POPAD ListGetNext EAX JNZ .30: ; The next SSS object. .80: RET ENDPROC1 .PgmDisplay: .90:EndProcedure EaDisplayPgm 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 Debug
Semiinline macros hired in EuroAssembler are for the first time dummy-expanded
here in 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 BufferStore 0,0,0 BufferStoreByte 0,0 BufferStoreWord 0,0 BufferStoreDword 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 DecodeUTF8 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