EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

src.htm
Class
SRC
Procedures
SrcAssemble
SrcCreate
SrcDestroy
SrcFetchLine
SrcPosition


Src represents one source file which is assembled by €ASM.
As there can be only one source being assembled at the moment, the object Src is defined statically in [.data] segment.

Src has its own memory pool.

The input source file name and its suboperation are provided by Ea.SrcFile and Ea.SubPtr.

SrcAssemble is invoked by EaAssemble with the source file name specified in Ea.SrcFile . Path of source filename is also used to locate the local option file euroasm.ini and to locate the listing file, which will have the same filename as source but appended with extension .lst.


src PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
 EUROASM LISTINCLUDE=OFF
 INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
src HEAD ; Start of module interface.
SRC STRUC          ; +00h.
.FsSrcNamePtr  D D ; Pointer to a string with default (envelope) program name derived from source filename.
.FsSrcNameSize D D ; Default program name size.
.Errorlevel    D D ; Highest errorlevel reached in this source.
.Inclusions    D D ; Number of succesfull INCLUDE* statements in this source.
                   ; +10h.
.Pool          D D ; Src's memory pool.
.CtxStack      D D ; ^STACK of context.
.EaoptStack    D D ; ^STACK of EAOPT maintained with EUROASM PUSH/POP.
.HeadStack     D D ; ^STACK of CHUNK_HEAD for nested HEAD/ENDHEAD blocks.
                   ; +20h.
.VarList       D D ; ^LIST of %variables.
.ChunkList     D D ; ^LIST of source chunks.
.FileList      D D ; ^LIST of FILEs included in this source.
.PfList        D D ; ^LIST of QWORDS (Ptr,Size) of output file names (used for detection of W3990).
                   ; +30h.
.CurrentStm    D D ; ^STM currently executed. Used in MsgProc.
.Lst           DS LST    ; Listing object.
.Eaopt         DS EAOPT  ; Current €ASM options in charge.
.Pgmopt        DS PGMOPT ; Current program options used as default.
.IniFile       DS FILE   ; Local option file.
.LstFile       DS FILE   ; Listing file.
ENDSTRUC SRC
  ENDHEAD src ; End of module interface.
[.bss]
Src:: DS SRC ; The source object.
[.text]
↑ SrcCreate
This constructor initializes memory structures of the source.
SrcCreate will also process local configuration file euroasm.ini, if found.
Input
Initialized Ea object containing source file name and its suboperations.
Output
CF=0, SRC object ready to assemble.
Error
CF=1 Errors are reported with macro Msg.
Called from
EaAssemble.
Invokes
ChunkSuboperate EaBufferRelease EaBufferReserve EaFs2Id EaIniAssemble LstCreate
Invoked by
EaAssemble
SrcCreate Procedure
Chunk     LocalVar Size=SIZE#CHUNK
FileName$ LocalVar Size=MAX_PATH_SIZE ; Room for local euroasm.ini filename.
     ; Initialize memory pool.
     Clear Src
     PoolCreate Size=%EaPoolSize, ErrorHandler=EaMallocError::
     JC .99:
     MOV [Src.Pool],EAX
     MOV EDX,EAX 
     ; Derive default program name Src.FsSrcName from source filename.
     LEA ESI,[Ea.SrcFile.Name::]
     MOV ECX,[Ea.SrcFile.ExtOffs::]
     ADD ESI,[Ea.SrcFile.NameOffs::]
     SUB ECX,[Ea.SrcFile.NameOffs::]
     ; ESI,ECX is now source file name without path and extension.
     Invoke EaBufferReserve::,SrcCreate
     Invoke EaFs2Id::,ESI,ECX,EAX ; Create an identifier from file name.
     BufferRetrieve EAX
     Invoke EaBufferRelease::,EAX
     PoolStore EDX,ESI,ECX ; Permanently store derived name ESI,ECX.
     MOV [Src.FsSrcNamePtr],EAX ; Will be used as default (envelope) program name.
     MOV [Src.FsSrcNameSize],ECX
    ; Create memory structures of the source on source pool EDX.
     StackCreate EDX,SIZE#CTX,Depth=32
     MOV [Src.CtxStack],EAX
     StackCreate EDX,SIZE#EAOPT,Depth=4
     MOV [Src.EaoptStack],EAX
     StackCreate EDX,SIZE#CHUNK_HEAD,Depth=4
     MOV [Src.HeadStack],EAX
     ListCreate EDX,SIZE#VAR
     MOV [Src.VarList],EAX
     ListCreate EDX,8
     MOV [Src.PfList],EAX ; Output file names are kept here.
     ListCreate EDX,SIZE#CHUNK
     MOV [Src.ChunkList],EAX
     ListCreate EDX,SIZE#FILE
     MOV [Src.FileList],EAX ; Included files are kept in Src.FileList. 
     Invoke LstCreate:: ; Initialize Src.Lst object.
; Three chunks will initialize assembly:
; 1. "FsSrcName: PROGRAM" stored on Src.Pool (chunkEnvelope).
; 2.  contents of base source file mapped in memory (chunkSource).
; 3. "ENDPROGRAM FsSrcName:" stored in Src.Pool (chunkEnvelope).
     ; First create chunk Nr.1:
     LEA EBX,[%Chunk]
     LEA EAX,[Ea.SrcFile::]
     MOV [EBX+CHUNK.FilePtr],EAX ; The main source.
     ; Create chunk contents on Src.Pool.
     MOV ECX,[Src.FsSrcNameSize]
     LEA EDX,[ECX+11]
     PoolNew [Src.Pool],EDX, Align=BYTE
     MOV EDI,EAX ; Room for envelope PROGRAM statement.
     MOV [EBX+CHUNK.Bottom],EAX
     MOV ESI,[Src.FsSrcNamePtr]
     REP MOVSB
     MOV AX,": "
     STOSW
     MOV ESI,[Dict_PseudoPROGRAM::+DICT.Ptr] ; The text "PROGRAM".
     MOV ECX,[Dict_PseudoPROGRAM::+DICT.Size]
     REP MOVSB
     MOV AX,0x0A0D ; CR+LF.
     STOSW
     MOV [EBX+CHUNK.Top],EDI
     MOVD [EBX+CHUNK.Status],chunkEnvelope
     ListStore [Src.ChunkList],EBX
     ; Create chunk Nr.2:
     LEA EBX,[%Chunk]
     MOV EAX,[EBX+CHUNK.FilePtr]
     LEA EDX,[EAX+FILE.Name]
     SysOpenFileMap EAX,EDX
     Msg cc=C,'8030',EDX ; Error reading source !1$.
     JC .99:
     ; The main source file contents is now mapped in memory ESI,EAX.
     MOV [EBX+CHUNK.Bottom],ESI
     ADD EAX,ESI
     MOV [EBX+CHUNK.Top],EAX
     MOVD [EBX+CHUNK.Status],chunkSource
     ; Source file might have been specified with suboperation, e.g. "source.asm"{1..%&-80}[10..99]
     MOV ECX,[Ea:: + EA.SubSize]
     JECXZ .30: ; If no suboperation requested.
     MOV EAX,[Ea:: + EA.SubPtr]
     ADD ECX,EAX ; EAX..ECX now specifies string e.g. {1..%&-80}[10..99]
.20: Invoke ChunkSuboperate::,EBX,EAX,ECX,1
     JC .99:
     JZ .20: ; If chunk was suboperated, more chained suboperations may follow.
.30: ListStore [Src.ChunkList],EBX
     ; Now create chunk Nr.3:
     MOV ECX,[Src.FsSrcNameSize]
     LEA EDX,[ECX+13]
     PoolNew [Src.Pool],EDX, Align=BYTE
     MOV EDI,EAX
     MOV [EBX+CHUNK.Bottom],EAX
     MOV ESI,[Dict_PseudoENDPROGRAM::+DICT.Ptr] ; The text "ENDPROGRAM".
     MOV ECX,[Dict_PseudoENDPROGRAM::+DICT.Size] ; 9.
     REP MOVSB
     MOV AL,' '
     STOSB
     MOV ESI,[Src.FsSrcNamePtr]
     MOV ECX,[Src.FsSrcNameSize]
     REP MOVSB
     MOV AL,':'
     STOSB
     MOV AX,0x0A0D ; CR+LF.
     STOSW
     MOV [EBX+CHUNK.Top],EDI
     MOVD [EBX+CHUNK.Status],chunkEnvelope
     ListStore [Src.ChunkList],EBX
     ; Current options are inherited from parent object (Ea).
     CopyTo Src.Eaopt,  Ea.EaoptIni::
     CopyTo Src.Pgmopt, Ea.Pgmopt::
     ; Then the options will be updated from local euroasm.ini file, if found.
     MOV ESI,Ea.SrcFile.Name::
     MOV ECX,[Ea.SrcFile.NameOffs::]
     LEA EDI,[%FileName$]
     PUSH EDI
      REP MOVSB  ; Concantenate source path and "euroasm.ini".
      MOV ESI,=B"euroasm.ini"
      MOV ECX,12
      REP MOVSB
     POP EDI
     MOV EDX,Src.IniFile
     SysOpenFileMap EDX,EDI
     Msg cc=C,'0160',EDI ; Local option file "!1$" was not found.
     JC .60:
     SetSt [EDX+FILE.Status],fileFound
     Msg '0170',EDI ; Assembling local option file "!1S".
     ADD EAX,ESI
     Invoke EaIniAssemble:: ,ESI,EAX, Src.Eaopt, Src.Pgmopt
     SysCloseFile EDX
.60: CopyTo Ea.Eaopt::,Src.Eaopt,Size=SIZE#EAOPT
     Msg '0180',Ea.SrcFile.Name::, Ea.SubPtr:: ; Assembling source file "!1$"!2S.
.99: EndProcedure SrcCreate
↑ SrcDestroy
Assembly of a source file terminates.
Input
-
Output
-
Error
 
Called from
EaAssemble.
Invokes
LstGetFileName
Invoked by
EaAssemble
SrcDestroy Procedure
LstSize    LocalVar
     Invoke LstGetFileName::
     LEA EBX,[Src.LstFile]
     SysAssignFile EBX,ESI,ECX
     FileMkDir EBX
     JNC .30:
.LstError:
     LEA EAX,[EBX+FILE.Name]
     Msg '7982',EAX ; Error writing to listing file "!1$".
     JMP .40:
.WriteStreamBlock PROC ; Callback from StreamDump macro.
         ADD [%LstSize],ECX
         FileWrite Src.LstFile,ESI,ECX
         RET
     ENDP .WriteStreamBlock
.30: FileCreate EBX ; Write listing to ListFile.
     JC .LstError:
     MOVD [%LstSize],0 ; File size counter.
     LEA EDX,[Src.Lst]
     StreamDump [EDX+LST.Stream], .WriteStreamBlock
     JC .LstError:
     LEA EAX,[EBX+FILE.Name]
     Msg  '0860',EAX,[%LstSize] ; Listing file "!1$" created, size=!2D.
.40: FileClose EBX ; Close the listing file.
.50: CopyTo Ea.Eaopt::, Src.Eaopt, Size=SIZE#EAOPT ; Ea.Eaopt is updated from Src.Eaopt.
     ListGetLast [Src.FileList]
     JZ .80:
.70: SysCloseFile EAX  ; Close all included files.
     ListGetPrev EAX
     JNZ .70:
     SysCloseFile Ea::+EA.SrcFile ; Close the base source file.
.80: MOV EDX,[Src.Pool]
     MOV [Src.CtxStack],0
     PoolDestroy EDX
     Msg cc=C,'2575','Src',EDX ; Deallocation of virtual memory !1C.Pool !2Hh failed.
.90: Clear Src
    EndProcedure SrcDestroy
↑ SrcFetchLine LinePtr, ChunkPtr
SrcFetchLine will find the memory-mapped physical line which starts at LinePtr and strip off its machine comment, if any. Searching for the chunk, where the required line belongs, starts with the specified chunk, or with the first chunk if ChunkPtr=NULL.
If the chunk specified with LinePtr, ChunkPtr is chunkBin or chunkError, the returned data ESI..EAX is not source line but binary data or Msg parameter. The caller should test chunk status first.
Input
LinePtr is pointer inside the text of source file mapped in memory, usually the start of a physical line.
LinePtr may be 0, and the 1st physical line of the specified chunk is returned in this case.
ChunkPtr it pointer to CHUNK where the search for line should start. ChunkPtr may be 0 which means the first chunk on Src.ChunkList.
Output on standard line
CF=ZF=0
ESI= Pointer to the beginning of line (if no machine comment), or behind the machine comment (behind | which terminates it).
EAX= Pointer to the end of the returned physical line, usually right behind its LF.
LF may be omitted when the last line in source file is not terminated with LineFeed.
EDX= Pointer to the chunk the line lies in.
Fetched line between ESI..EAX may be empty or white-space only.
Output on markup line
CF=0, ZF=1 when the line is markup comment (starting with <) or when the whole line is machine comment (starting with |)
The caller should invoke SrcFetchLine again with LinePtr=EAX, ChunkPtr=EDX.
EAX=ESI= pointer to the end of the returned physical line, usually right behind LF.
EDX= Pointer to the chunk the line lies in.
Output on end of the last chunk
CF=1, ZF=1 when there is no more source text.
EAX, ESI, EDX unspecified.
Invoked by
StmParse
SrcFetchLine Procedure LinePtr, ChunkPtr
     MOV EAX,[%ChunkPtr]
     MOV EDI,[%LinePtr]
     TEST EAX
     JNZ .10:
     ListGetFirst [Src + SRC.ChunkList]
.10: JZ .EndSource: ; No more chunks.
     TEST EDI
     JNZ .20:
     MOV EDI,[EAX+CHUNK.Bottom]
.20: CMP EDI,[EAX+CHUNK.Bottom]
     JB .30:
     CMP EDI,[EAX+CHUNK.Top]
     JB .60:
     JE .40:
.30: ListGetNext EAX
     JMP .10
.40: ; TxtPtr was at the top of current chunk, lets start at the bottom of the next one.
.50: ListGetNext EAX
     JZ .EndSource:
     MOV EDI,[EAX+CHUNK.Bottom]
.60: ; EAX=actual chunk; EDI=start of physical line
     MOV [%ReturnEDX],EAX
     MOV ECX,[EAX+CHUNK.Top]
     MOV ESI,EDI
     SUB ECX,EDI
     JZ .50:
     JNSt [EAX+CHUNK.Status],chunkBin|chunkError,.65:
     ; Chunk EAX does not contain source lines but binary data or Msg parameter.
     MOV ECX,[EAX+CHUNK.Top]
     MOV [%ReturnESI],EDI
     MOV [%ReturnEAX],ECX
     JMP .NormalOutput:
.65: MOV AL,10
     REPNE SCASB ; Find the end of physical line.
     MOV [%ReturnESI],ESI
     MOV [%ReturnEAX],EDI
     ; Pysical line ESI..EDI is specified. Now strip off comments.
     MOV ECX,EDI
     MOV EDI,ESI
     SUB ECX,ESI
.70: LODSB ; Skip leading white spaces on line.
     DEC ECX
     JZ .NormalOutput:
     ExpClassify AL
     TEST AH,expWhiteSpace
     JNZ .70:
     CMP AL,'<'                                                      ;>
     JE .CommentOnly:
     CMP AL,'|'
     JNE .NormalOutput:
     MOV EDI,ESI
     REPNE SCASB
     MOV [%ReturnESI],EDI
     JE .NormalOutput:
.CommentOnly:
     MOV AH,01000000b ; ZF=1, CF=0
     JMPS .90:
.EndSource:
     MOV AH,01000001b ; ZF=CF=1
     JMPS .90:
.NormalOutput:
     MOV AH,00000000b ; ZF=CF=0
.90: SAHF
    EndProcedure SrcFetchLine
↑ SrcAssemble
SrcAssemble reads all lines from source and creates output program files. Assembly starts with the first line of first chunk on Src.ChunkList (which is the envelope PROGRAM statement).
SrcAssemble stops when the last statement of the last chunk has been assembled (envelope ENDPROGRAM statement), or when source-fatal error occured (errorlevel >=8).
Each statement from ordinary source chunk is parsed, executed, listed and flushed.
Source statement processing object model
EaAssemble SrcCreate SrcAssemble StmCreate StmClean StmParse StmExecute StmListing StmFlush StmDestroy SrcDestroy
See also
Ea object model
Input
Source must have been initialized with SrcCreate , context stack empty, chunk list loaded with three chunks: suboperated memory-mapped source file and both envelope chunks.
Output
Source file is assembled.
Invokes
CtxGetEndTypename CtxPeek StmClean StmCreate StmDestroy StmDisplayParsed StmExecute StmFlush StmListing StmParse
Invoked by
EaAssemble
SrcAssemble Procedure
Stm  LocalVar Size=SIZE#STM ; Stm object used for statement parsing.
     LEA EBX,[%Stm]
     Invoke StmCreate::,EBX
     SUB EDX,EDX
     SUB EAX,EAX ; LinePtr=0, start with the 1st line of source, which is envelope "file: PROGRAM". 
.10: ; Here is the main loop which will read and execute all statements in the source.
     Invoke StmClean::,EBX ; Empty statement buffers and erase remains of previous statement.
     MOV [Src.CurrentStm],EBX
     Invoke StmParse::,EBX,EAX,EDX ; Fetch and parse statement adressed with EAX.
     JC .60: ; If no more source lines.
     INCD [Ea.StmCount::] ; Counter of total assembled statements.
     JNSt [Ea.Eaopt.Status::],eaoptDISPLAYSTM,.18:
     Invoke StmDisplayParsed::,EBX
 .18:Invoke StmExecute::,EBX ; Execute the statement: fill statement buffers, modify context stack, create symbols etc.
     SUB ECX,ECX
     SUB EAX,EAX
 .20:Invoke CtxPeek::,ctxPROGRAM,EAX ; Find emitting program context.
     JC .30: ; If envelope ENDPROGRAM was just executed. No more programs on stack.
     MOV ECX,[EAX+CTX.ObjPtr] ; ECX=0 when PROGRAM statement was in NoEmit state.
     JECXZ .20: ; If NoEmit, search the stack deeper.
     JNSt [ECX+PGM.Status],pgmLastPass,.50: ; Skip the listing in nonlast passes.
     JSt [ECX+PGM.Status],pgmLastJustSet,.40:
.30: Invoke StmListing::,EBX ; Create a listing line(s) and write to Lst.Stream.
.40: JECXZ .50:
     RstSt [ECX+PGM.Status],pgmLastJustSet
.50: RstSt [Src.Lst.Status],lstVolMask ; Clear used volatile flags of listing.
     Invoke StmFlush::,EBX ; Flush STM.EmitBuffer to the current section's SSS.EmitBuffer.
     CMP [Src.Errorlevel],8
     JAE .80: ; Abort if source fatal error. The source file will be prematurely abandoned.
     MOV EAX,[EBX+STM.LineNext] ; The next statement where to continue.
     MOV EDX,[EBX+STM.ChunkNext]
     TEST EAX
     JNZ .10: ; If STM.LineNext is specified, go to assemble this new statement (macro or repeat block).
     ; Otherwise continue with the next statement in the normal source flow.
     MOV EAX,[EBX+STM.LineEnd] ; End of just executed statement is the beginning of the next one.
     MOV EDX,[EBX+STM.ChunkPtr]
     JMP .10:
.60: ; End of source text.
     StackPop [Src.CtxStack] ; Check if no context was left on stack.
     JC .80: ; If stack empty, OK.
     MOV EDI,EAX ; Some block in source was left open, this is an error.
     Invoke CtxGetEndTypename::,[EDI+CTX.Status] ; EAX=^DQ Ptr,Size
     JNSt [EDI+CTX.Status],ctxREPEAT,.70:
     JSt [EDI+CTX.Status],ctxExited,.70:
     XCHG EAX,EDI ; Operation %REPEAT has block identifier in %1 instead of label field. 
.70: Msg '7110',EAX,EDI ;  Wrong nesting, expected !1S !2S.  ENDblock id
     JMP .60:
.80: Invoke StmDestroy::,EBX
     MOVD [Src.CurrentStm],0
.90: EndProcedure SrcAssemble
↑ SrcPosition LinePtr
SrcPosition returns physical line number and file name of the source file (main source or included file or configuration file) where the LinePtr is mapped.
Input
LinePtr Pointer to line in memory-mapped file.
Output
CF=0
EAX= physical line number (1 or greater).
EDI= pointer to ASCIIZ file name without path.
Error
CF=1 if file not found or its an envelope pseudosource.
EAX= 0
EDI= pointer to NULL byte.
Invoked by
MsgProc VarExpand
          
SrcPosition Procedure LinePtr
     MOV EBX,[%LinePtr]
     MOV EAX,Ea.SrcFile:: 
     CALL .TryFileEAX:
     JNC .Found:
     ListGetFirst [Src.FileList]
     JZ .20:
 .10:CALL .TryFileEAX:
     JNC .Found:
     ListGetNext EAX
     JNZ .10:
 .20:MOV EAX,Ea.IniFile:: ; Try global "euroasm.ini".
     CALL .TryFileEAX:
     JNC .Found:
     MOV EAX,Src.IniFile ; Try local "euroasm.ini".
     CALL .TryFileEAX:
     MOV EDI,=B(0) ; No source file found.
     SUB ESI,ESI
     STC
     JMP .90:
     
.TryFileEAX: PROC ; Check if LinePtr=EBX is in mapped range of file EAX.
 ; Output: CF=1 if not in range. ECX=?
      MOV ECX,[EAX+FILE.BufPtr] ; Bottom of mapped source.
      CMP EBX,ECX
      JB .T9:
      ADD ECX,[EAX+FILE.BufSize] ; Top of mapped source.
      CMP EBX,ECX
      CMC
  .T9:RET      
    ENDP .TryFileEAX:
.Found:
     MOV EDX,EAX ; ^FILE.
     MOV EDI,[EDX+FILE.BufPtr]
     MOV ECX,[EDX+FILE.BufSize]
     SUB ESI,ESI ; Line counter.
     MOV AL,10 ; End of physical line.
 .60:INC ESI     
     JECXZ .80:
     REPNE SCASB ; Find EOL.
     CMP EBX,EDI
     JAE .60:
 .80:LEA EDI,[EDX+FILE.Name]
     ADD EDI,[EDX+FILE.NameOffs] ; Skip file path, if any. CF=0.          
 .90:MOV [%ReturnEDI],EDI
     MOV [%ReturnEAX],ESI
    EndProcedure SrcPosition
   ENDPROGRAM src    

▲Back to the top▲