EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

ea.htm
Tuning
EaTune
Class
EA
Object
Ea
Macro
EaStackCheck
Procedures
EaAssemble
EaBufferAlign
EaBufferRelease
EaBufferReserve
EaBufferSort
EaCreate
EaDestroy
EaDisplayPgm
EaFs2Id
EaId2Fs
EaIniAssemble
EaIniGlobal
EaMain
EaMallocError
EaStreamAlign
@RTprocedures

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.
↑ EaTune
Global parameters for fine tuning of €ASM performance.
%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
Structure EA describes the main EuroAssembler object Ea which represents the compiler itself.
Member Ea.TimeStart keeps the real system time when euroasm.exe launched. It is used to compute the duration of runtime, which will be reported with I0980. See also Ea.Eaopt.TimeStamp.
Member Ea.BufferStack is a pointer to STACK which stacks QWORDS which contain
  1. pointer to preallocated BUFFER in low DWORD, and
  2. arbitrary nonzero identifier in high DWORD, or NULL when the buffer is released and free.

Member 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 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 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 FILE euroasm.ini.
.SrcFile       DS FILE   ; Currently processed source file specified on cmdline.
   ENDSTRUC EA
↑ EaEnc
Encoding of EA status flags.
   
eaAtLeast1File   EQU 1 ; euroasm.exe was launched with one or more input source file.
eaWildcarded     EQU 2 ; Input source file was specified with wildcard(s) ?, *. 
eaIniSectEUROASM EQU 4 ; [EUROASM] section of euroasm.ini is currently processed.
eaIniSectPROGRAM EQU 8 ; [PROGRAM] section of euroasm.ini is currently processed.
↑ EaStackCheck
Macro EaStackCheck is used to protect the program from stack overflow. It should be used in recursively invoked procedures.
Input
- Current value of ESP is compared with global member Ea.StackBottom.
Output
Arithmetic flags are destroyed.
Error
F9210 Memory reserved for machine stack is too small for this program.
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.
↑ Ea
As there is only one instance of the main €ASM object Ea, it is defined statically in [.bss] segment.
The main EuroAssembler object model
EaMain:: ; Executable entry. EaCreate ; Ea constructor. SysEachFile EaAssemble SourceFileFromCmdLine EaDestroy ; Ea destructor. SysExitProcess ; Terminate euroasm.exe.
[.bss]
Ea::  DS EA
[.data]
EaVersion:: DB "%^DATE" ; Date "YYYYMMDD" when was €ASM built.
EaIniFileDefault: ; Factory default options from ../objlib/euroasm.ini will be built-in to euroasm.exe.
  INCLUDEBIN "../objlib/euroasm.ini"
EaIniFileDefaultEnd:
↑ EaMain
This is the main procedure of EuroAssembler and its entry point.
Invokes
DictLookup EaBufferRelease EaBufferReserve EaCreate EaDestroy EaIniAssemble EaIniGlobal ExpParseKeyName ExpParseKeyValue
Invoked from
OS program loader.
[.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 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
      Msg '0010',EAX ; EuroAssembler version !1S 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 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 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 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 StackOrg
Constructor which initializes the Ea object.
Input
StackOrg is value of ESP at program entry.
Output
Object Ea is initialized.
Invoked by
EaMain
Invokes
EaIniAssemble
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-in  euroasm.exe body.
    Invoke EaIniAssemble,EaIniFileDefault,EaIniFileDefaultEnd, Ea.Eaopt, Ea.Pgmopt
   EndProcedure EaCreate
↑ EaDestroy
Destructor of Ea object.
Input
-
Output
I0980, I0990
Error
W2575
Invoked by
EaMain
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
↑ EaAssemble
This procedure assembles lines from 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.
EaAssemble is callback procedure invoked in EaMain from the macro SysEachFile.
Object model
See Ea object model and Stm object model.
Input
EDI= pointer to WIN32_FIND_DATAW structure with file attributes.
Ea.SrcFile is assigned with the source file name, wildcards resolved.
Ea.SubPtr, Ea.SubSize specifies suboperation(s) with source file as given on cmd line, when only a part of it should be assembled, for instance {1..%&-40}. Ea.SubSize=0 when no suboperation was specified.
Output
CF=0 if the source file was assembled.
Error
CF=1 if fatal error occured (errorlevel 9) and €ASM needs to abort.
Invokes
SrcAssemble SrcCreate SrcDestroy
Tested by
t1210
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
Memory allocation exception handler. It is called from PoolCreate when allocation request failed (fatal error).
See also
PoolCreate
EaMallocError:: PROC
     Msg '9110' ; Cannot allocate virtual memory.
     RET
     ENDP EaMallocError
↑ EaBufferReserve RequestingObject
EaBufferReserve returns empty buffer from the stack of universal buffers.
It will search Ea.BufferStack for unoccupied buffer and, if none found, create a new one and add it on the stack. The optimal initial Ea.BufferStack size depends on the nesting depth used in assembled program (macro in macro, nested suboperation etc) and it is increased on demand.
Objects kept on Ea.BufferStack are QWORDS where the first DWORD is pointer to a BUFFER, and the second DWORD is nonzero identifier of occupation (zero value indicates that the buffer is released).
Input
RequestingObject is address of the object which is going to use this buffer. It is used for debugging purpose only (to find out which Procedure requested the buffer).
Output
CF=0, EAX= pointer to an empty buffer.
Error
CF=1, EAX=0 fatal error F9312.
See also
EaBufferRelease.
Invoked by
ChunkInclude ChunkSuboperate CtxCreate CtxDiscard CtxFind EaMain ExpEval ExpEvalData ExpEvalIdentifier ExpParseDatatype ExpStoreInstr IiAssembleMultiop IiFlush LstGetFileName MemberAdd MemberUpdate PfDrectveCreate PfSuboperate PfcoffCompile PfcoffLoadPgm PflibcofCompile PflibomfCompile PfmzCompile PfomfLoadDataBlock PfomfLoadModule PfomfStoreData PfomfStoreModule PfpeBaserelocFixup PfpeCompile PfpeExportCreate PfpeImportCreate PfrsrcLoadIconFile PfrsrcLoadPgm PgmConcatenateImage PgmDetectImportModule PgmListGlobals PgmListLiterals PgmListMap PgmOrderSegmDo PgmSelectModules PgmoptSetDefaults PseudoData PseudoPROC1 PseudoSEGMENT PseudoSTRUC PseudopcDISPLAY PseudopcERROR PseudopcSET PseudopcSET2 PseudopcSETA PseudopcSETB PseudopcSETC PseudopcSETE PseudopcSETL PseudopcSETS PseudopcSETX RelocUniq SrcCreate SssCreate SssGuessPurpose StmCreate StmExpandField StmListing SymCreate SymCreateLiteral VarExpand VarExpandField VarSuboperate
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 BufferPtr
EaBufferRelease will mark the specified buffer as free. It does not pop the buffer from Ea.BufferStack. Released buffer may be reused later by EaBufferReserve.
Input
BufferPtr pointer to the buffer, as returned from EaBufferReserve. It may be 0, nothing happens in this case.
Output
CF=0 Buffer was released and cleared.
Error
CF=1 The specified buffer was not found on Ea.BufferStack.
See also
EaBufferReserve.
Invoked by
ChunkInclude ChunkSuboperate CtxDestroy CtxDiscard CtxFind EaMain ExpEval ExpEvalData ExpEvalIdentifier ExpParseDatatype ExpStoreInstr IiAssembleMultiop IiFlush LstGetFileName MemberAdd MemberUpdate PfDrectveCreate PfSuboperate PfcoffCompile PfcoffLoadPgm PflibcofCompile PflibomfCompile PfmzCompile PfomfLoadDataBlock PfomfLoadModule PfomfStoreData PfomfStoreModule PfpeBaserelocFixup PfpeCompile PfpeExportCreate PfpeImportCreate PfrsrcLoadIconFile PfrsrcLoadPgm PgmConcatenateImage PgmDetectImportModule PgmListGlobals PgmListLiterals PgmListMap PgmOrderSegmDo PgmSelectModules PgmoptSetDefaults PseudoData PseudoPROC1 PseudoSEGMENT PseudoSTRUC PseudopcDISPLAY PseudopcERROR PseudopcSET PseudopcSET2 PseudopcSETA PseudopcSETB PseudopcSETC PseudopcSETE PseudopcSETL PseudopcSETS PseudopcSETX RelocUniq SrcCreate SssCreate SssGuessPurpose StmDestroy StmExpandField StmListing SymCreate SymCreateLiteral VarExpand VarExpandField VarSuboperate
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 PtrBuffer
EaBufferSort alphabetically sorts the objects whose pointers are provided in the buffer. Object may be SYM, VAR, MAC or any other type which begins with .NamePtr and .NameSize.
Input
PtrBuffer Pointer to a BUFFER filled with Dword pointers to unsorted-yet objects.
Output
Objects in PtrBuffer are sorted by name.
Error
-
See also
ShellSort.
Invoked by
PfpeExportCreate PgmListGlobals PgmOrderSegmDo PseudopcDISPLAY
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 Buffer, Alignment
EaBufferAlign keeps storing NULL bytes to Buffer until its contents size is aligned.
Input
Buffer is a pointer to BUFFER to align.
Alignment is required alignment. 0..1=no alignment, 2=WORD, 4=DWORD etc.
Forced to 0 when the Aligment is not a power of two.
Output
EAX= number of NULL bytes stored to Buffer.
Error
-
Invokes
ExpAlign
Invoked by
PfmzCompile PfpeBaserelocFixup PfpeCompile PfpeImportCreate PfrsrcLoadIconFile PfrsrcLoadPgm
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 Stream, Alignment
EaStreamAlign keeps storing NULL bytes to Stream until its contents size is aligned.
Input
Stream is a pointer to STREAM to align.
Alignment is required alignment. 0..1=no alignment, 2=WORD, 4=DWORD etc.
Forced to 0 when the Aligment is not a power of two.
Output
EAX= number of NULL bytes stored to Stream.
Error
-
Invokes
ExpAlign
Invoked by
PflibomfCompile
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 IdNamePtr, IdNameSize, OutBuffer
EaId2Fs converts an €ASM identifier to a string which can be used as filename.
Question mark ? is replaced with underscore _.
Input
IdNamePtr Pointer to identifier.
IdNameSize Number of characters in the identifier.
OutBuffer ^BUFFER allocated by caller, where the filename will be written to.
Output
Result is written to OutBuffer.
Error
-
See also
EaFs2Id.
Invoked by
PgmoptSetDefaults
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 FsNamePtr, FsNameSize, OutBuffer
EaFs2Id converts a name with filesystem-permitted characters to a valid €ASM identifier.
Nonalphanumeric characters are replaced with underscore _ and if the filename does not start with a letter, grave ` is prefixed to the name.
Input
FsNamePtr Pointer to file name.
FsNameSize Number of characters in the name.
OutBuffer ^BUFFER allocated by caller, where the identifier will be written to.
Output
Result is written to OutBuffer.
Error
-
See also
EaId2Fs.
Invoked by
PfcoffLoadPgm SrcCreate
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
↑ EaIniAssemble IniPtr, IniEnd, Eaopt, Pgmopt
EaIniAssemble will assemble contents of euroasm.ini file to EAOPT and PGMOPT structures.
Input
IniPtr Pointer to the start of text of unassembled contents of euroasm.ini mapped in memory.
IniEnd Pointer to the end of text.
Eaopt Pointer to the target EAOPT object.
Pgmopt Pointer to the target PGMOPT object.
Output
EAOPT and PGMOPT are modified with assembled options.
Error
Warnings W3701,W3705,W3720,W3730 are reported with macro Msg.
Invokes
DictLookup EaoptAssemble ExpParseKeyName ExpParseKeyValue PgmoptAssemble StmCreate StmDestroy
Invoked by
EaCreate EaIniGlobal EaMain SrcCreate
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 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::]
    EndProcedure EaIniAssemble
↑ EaIniGlobal
EaIniGlobal will update Ea.Eaopt from global euroasm.ini and create this file if it didn't exist.
Input
-
Output
CF=0 Ea.Eaopt updated, copied to Ea.EaoptIni. Global file created.
Error
CF=1 Errors are reported with macro Msg.
Invokes
EaIniAssemble
Invoked by
EaMain
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.
EaDisplayPgm Pgm, SourceName$Ptr, SourceLineNr
Diagnostic runtime procedure for debugging of EuroAssembler itself. It will be assembled only when EUROASM DEBUG=ENABLED.
Input
Pgm is pointer to the displayed program.
SourceName$Ptr is pointer to ASCIIZ filename of source where was the procedure EaDisplayPgm invoked. Use literal =B"%^SourceName" at invocation.
SourceLineNr is physical line number of source where was the procedure EaDisplayPgm invoked. Use %^SourceLine" at invocation.
Example
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
↑ @RTprocedures

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.

See also
%@RTprocedureList.
   ; 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

▲Back to the top▲