EuroAssembler Index Manual Download Source Macros

Sitemap Links Forum Tests Projects


Object MAC represents one macroinstruction.
Mac objects (macro definitions) are kept on PASS.MacList.
MacList is empty in the beginning of each pass.
Macros defined in program pass are merged with parent program's macros when the last pass terminates. Scope of macros and %variables begins with their definition and ends at the end of source.

When a macro is invoked (expanded), its arguments are stored to context, and assembly is redirected to the macro prototype (%MACRO statement of invoked macro). Assembly returns below the macro invocation when the coresponding %ENDMACRO has been assembled.

Macro expansion object model
SampleMacro %MACRO Ord1,Ord2,Ord3,Key1=Key1Val,Key2=Key2Val ; Macro prototype statement. ; Body of SampleMacro goes here. %ENDMACRO SampleMacro Macro definition above is parsed and ignored in ctxDefinition, reference to prototype is saved to PASS.Maclist. SampleLabel: SampleMacro Ord1Val,Ord2Val,,,Ord5Val,Key2=NewKey2Val,Key3=NewKey3Val Macro invocation above is parsed, assembly context is redirected to the line where was the SampleMacro defined. Prototype in ctxExpansion is parsed to Stm by StmParse: Stm.OrdBuffer: Ord1,Ord2,Ord3 Stm.KeyBuffer: Key1=Key1Val,Key2=Key2Val Parsed macro invocation is stored to the context object by MacExpand >MacCtxUpdate: Ctx.ObjBuffer: SampleLabel,SampleMacro Ctx.OrdBuffer: Ord1Val,Ord2Val,,,Ord5Val Ctx.KeyBuffer: Key2=NewKey2Val,Key3=NewKey3Val ; Warn undeclared keyword Key3= MacPrototype merges operands of invokation with operands of prototype: Ctx.FrmBuffer: Ord1=Ord1Val,Ord2=Ord2Val,Ord3=,=,=Ord5Val,Key1=Val1,Key2=NewKey2Val Values of automatic macro variables will be %set on demand in VarExpand as if the following statements were virtually performed: %: %SET SampleLabel ; Label actually used at invocation. %* %SET Ord1Val,Ord2Val,,,Ord5Val ; Ordinals actually used at invocation. %# %SETA 5 ; Five ordinals actually used at invocation, though two of them are empty. %=* %SET Key2=NewKey2Val,Key3=NewKey3Val %=# %SETA 2 ; Two keywords are actually used at invocation, though Key3= is undeclared and ignored. %0 %SET SampleMacro ; 0th operand is the macro name. %1 %SET Ord1Val ; The value used on macro invocation as 1st operand. %3 %SET ; Empty, as no 3rd operand was used on macro invocation. %5 %SET Ord5Val ; 5th operand used on macro invocation (though it was not explicitly declared in protoype). %Key1 %SET Key1Val ; As Key1 wasn't mentioned in macro invocation, default from prototype is used. %Key2 %SET NewKey2Val ; Default from prototype is rewritten with new value specified in macro invocation. %Key3 %SET ; Empty because this keyword was not declared in prototype. When %ENDMACRO is encountered in ctxExpansion, assembly returns back just below the macro invokation statement and ctxMACRO+ctxExpansion is discarded.
 INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
  mac HEAD ; Start of module interface.
Object of this class represents a defined macro.
.NamePtr  D D ; Pointer to macro name.
.NameSize D D ; Size of macro name.
.LinePtr  D D ; Pointer to the first physical line of %MACRO statement (definition of the macro) or 0 when the macro was dropped.
.Status   D D ; Macro properties.
↑ MacEnc
Encoding of flags used in MAC.Status.
macLabeled  = 0x00000001 ; Formal label %: occured at least once in some statement of macro definition.
  ENDHEAD mac ; End of module interface.
↑ MacExpand Stm
MaxExpand is statement handler for macroinstructions. Name of the macro is in Stm.OperationPtr/Size.
Stm.OperationData contains pointer to MAC object and MAC.LinePtr points to the corresponding %MACRO statement with macro definition.
MacExpand creates context ctxMACRO+ctxExpansion.
Stm is pointer to the parsed STM statement.
Context stack modified, prototype prepared.
CF=1 Errors are reported with macro Msg.
CtxCreate MacCtxUpdate StmCheckFields
Invoked by
Tested by
MacExpand Procedure Stm
     MOV EBX,[%Stm]
     Invoke StmCheckFields::,EBX,"*0**"
     StackPush [Src.CtxStack::],0
     LEA ECX,[EBX+STM.OperationPtr]
     Msg cc=C,'9312',ECX ; Allocation error expanding macro !1S.
     MOV ECX,ctxMACRO+ctxExpansion+ctxExpandable+ctxFormal+ctxPrototype
     ; Examine listing status.
     JNSt [Ea.Eaopt.Status::],eaoptLIST,.50:
     JNSt [Ea.Eaopt.Status::],eaoptLISTMACRO,.50:
     ; Indicate that macroexpansion should be +listed
     ; even when the macro is defined in included file and LISTINCLUDE=OFF:
     SetSt ECX,ctxMacExpList
 .50:Invoke CtxCreate::,EAX,ECX,EBX
     Invoke MacCtxUpdate,EAX,EBX ; Copy macro operands to context buffers.
     MOV ECX,[EBX+STM.OperationData] ; Pointer to MAC object with macro declaration.
     MOV EAX,[ECX+MAC.LinePtr]
     MOV [EBX+STM.LineNext],EAX ; Continue assembly with macro prototype statement.
     MOVD [EBX+STM.ChunkNext],0
 .90:EndProcedure MacExpand
↑ MacCtxUpdate CtxPtr, StmPtr
Procedure MacCtxUpdate will copy macroinstruction operands from parsed statement (where they have limited lifetime) to buffers from CTX object in order to persistently store operand names and values until the macro is completely expanded and %MACRO..%ENDMACRO block abandoned.
CtxPtr Pointer to CTX already created with CtxCreate.
StmPtr Pointer to the parsed statement with macroinstruction.
Context is updated, CTX.OrdBuffer and CTX.KeyBuffer filled, CTX.ValBuffer is used as persistent storage. CTX.FrmBuffer is reserved but empty.
CF=1 Errors are reported with macro Msg.
See also
Invoked by
Tested by
MacCtxUpdate Procedure CtxPtr, StmPtr
McuPassPool LocalVar ; Current program pass pool.
     MOV EBX,[%StmPtr]
     MOV EDX,[%CtxPtr]
     MOV EAX,[EBX+STM.Program]
     MOV ECX,[EAX+PGM.PassPtr]
     JNZ .05:
.F9312:LEA ECX,[EBX+STM.OperationPtr]
     Msg '9312',ECX ; Allocation error expanding macro !1S.
     JMP .90:
.05: MOV EAX,[ECX+PASS.Pool]
     MsgUnexpected cc=Z
     MOV [%McuPassPool],EAX
     MOV EAX,[EBX+STM.LineEnd] ; LinePtr to the statement which follows macro invocation.
     MOV EDI,[EBX+STM.ChunkPtr]
     MOV [EDX+CTX.LineNext],EAX ; Where to continue when the expansion is over.
     MOV [EDX+CTX.ChunkNext],EDI
     MOV [EDX+CTX.Shift],ECX
     ; Update context with MacPtr from statement and copy flag MAC.Status:macLabeled to CTX.Status:ctxMacLabeled
     ; in order to to indicate whether %: should be expanded implicitly.
     MOV ESI,[EBX+STM.OperationData] ; In case of macroinstruction it is ^MAC.
     MOV [EDX+CTX.MacPtr],ESI
     JNSt [ESI+MAC.Status],macLabeled,.10:
     SetSt [EDX+CTX.Status],ctxMacLabeled
.10: BufferRetrieve [EBX+STM.OrdBuffer] ; Copy ordinal operands from invocation to context.OrdBuffer.
     ; ESI,ECX is QWORDs (Ptr,Size) for each ordinal used in macro invocation. ECX is 0,8,16,24,...
     ; However their lifetime is limited to StmFlush.
     BufferStore [EDX+CTX.OrdBuffer],ESI,ECX
     JC .F9312:
     BufferRetrieve [EDX+CTX.OrdBuffer]
     ; Ordinal lifetime will be prolonged to the end of macroexpansion.
     JECXZ .30: ; All ordinals copied. 
.20: PoolStore [%McuPassPool],[ESI+0],[ESI+4] ; Make the ordinal value persistent till end of pass.
     JC .F9312:
     MOV [ESI+0],EAX
     ADD ESI,8
     SUB ECX,8
     JA .20: ; Next ordinal.
.30: BufferRetrieve [EBX+STM.KeyBuffer] ; Copy keyword operands from invocation to context.KeyBuffer.
     BufferStore [EDX+CTX.KeyBuffer],ESI,ECX
     JC .F9312:
     BufferRetrieve [EDX+CTX.KeyBuffer]
     ; ESI,ECX is four DWORDs (NamePtr,NameSize,ValPtr,ValSize) for each keyword used in macro invocation.
     ; Keywords will be made persistent to the end of expansion.
     JECXZ .50: ; All keywords copied.  ECX was 0,16,32,... 
.40: PoolStore [%McuPassPool],[ESI+0],[ESI+4] ; Make the keyword name persistent.
     JC .F9312:
     MOV [ESI+0],EAX
     PoolStore [%McuPassPool],[ESI+8],[ESI+12] ; Make the keyword value persistent.
     JC .F9312:
     MOV [ESI+8],EAX
     ADD ESI,16
     SUB ECX,16
     JG .40: ; Next keyword. 
.50: BufferNew [EDX+CTX.ObjBuffer],SIZE# CTX_MAC
     JC .F9312:
     MOV EDI,EAX ; ^CTX_MAC in CTX.ObjBuffer.
     MOV ESI,[EBX+STM.LabelPtr]
     MOV ECX,[EBX+STM.LabelSize]
     PoolStore [%McuPassPool],ESI,ECX
     JC .F9312:
 ; Copy misc info from invocation to context.ObjBuffer in the format CTX_MAC.
     MOV [EDI+CTX_MAC.LabelPtr],EAX   ; Label of macro invokation.
     MOV [EDI+CTX_MAC.LabelSize],ECX
     MOV ESI,[EBX+STM.OperationPtr]
     MOV ECX,[EBX+STM.OperationSize]
     PoolStore [%McuPassPool],ESI,ECX ; Make macroname persistent (it may be used to expand %0).
     JC .F9312:
     MOV [EDI+CTX_MAC.MacroNamePtr],EAX
     MOV [EDI+CTX_MAC.MacroNameSize],ECX
     MOV EAX,[EBX+STM.OperationData]
     MOV [EDI+CTX_MAC.ProtoLinePtr],EAX ; LinePtr to %MACRO prototype in source.
     MOV EAX,[EBX+STM.Status]
     MOV [EDI+CTX_MAC.InvokStmStatus],EAX ; STM.Status of macro invocation.
.90:EndProcedure MacCtxUpdate
↑ MacPrototype CtxPtr, StmPtr
MacPrototype will merge operands of macroinstruction invocation with operands of %MACRO prototype and prepare formal %variables in CTX.FrmBuffer.
CtxPtr Ptr to CTX which was pushed on invocation of the macro with its actual operands in ObjBuffer,OrdBuffer,KeyBuffer.
StmPtr Ptr to parsed STM with prototype %MACRO statement which yields the default keyword values and formal names of all operands in its .OrdBuffer and .KeyBuffer.
FrmBuffer in CTX object will be updated with actual operands. They will be used later to dynamically construct special macro %variables (%*,%#,%1 etc).
Errors are reported with macro Msg.
See also
Invoked by
Tested by
MacPrototype Procedure CtxPtr, StmPtr
MpPassPool LocalVar
FrmVar     LocalVar Size=16 ; VarNamePtr,VarNameSize,VarValuePtr,VarValueSize
FrmMax     LocalVar ; Greater of ordinals length in STM.OrdBuffer and CTX.OrdBuffer. 0,8,16,,,
FrmNdx     LocalVar ; 0,8,16,...FrmMax-8
     MOV EBX,[%StmPtr] ; Statement with %MACRO (prototype).
     MOV EDX,[%CtxPtr] ; Context with invocation operands.
     MOV EAX,[EBX+STM.Program]
     MOV ECX,[EAX+PGM.PassPtr]
     JZ .F9312:
     MOV EAX,[ECX+PASS.Pool]
     JZ .F9312:
     MOV [%MpPassPool],EAX
     ; Merge ordinal operands.
     BufferRetrieve [EBX+STM.OrdBuffer]
     MOV [%FrmMax],ECX
     BufferRetrieve [EDX+CTX.OrdBuffer]
     CMP ECX,[%FrmMax]
     JBE .10:
     MOV [%FrmMax],ECX
     MOV [%FrmNdx],ECX ; Start with the 1st ordinal.
 .20:LEA EDI,[%FrmVar] ; Loop .20: .. .50: ordinal operands.
     MOV ECX,4
     REP STOSD ; Clear FrmVar.
     MOV EDI,[%FrmNdx]
     CMP EDI,[%FrmMax]
     JNB .50:
     BufferRetrieve [EBX+STM.OrdBuffer]
     JNB .30:
     ; Make ordinal name persistent to the end of macro expansion.
     MOV ECX,[EDI+ESI+4]
     MOV ESI,[EDI+ESI+0]
     PoolStore [%MpPassPool],ESI,ECX
     JC .F9312:
     MOV [%FrmVar+0],EAX ; Persistent ordinal name ptr.
     MOV [%FrmVar+4],ECX ; Ordinal name size (may be 0 when the ordinal is unnamed).
 .30:BufferRetrieve [EDX+CTX.OrdBuffer]
     JNB .40:
     MOV ECX,[EDI+ESI+4] ; Ordinal value size.
     MOV ESI,[EDI+ESI+0] ; ValuePtr. It's already been made persistent in MacCtxUpdate.
     MOV [%FrmVar+8],ESI 
     MOV [%FrmVar+12],ECX
 .40:LEA ESI,[%FrmVar]
     BufferStore [EDX+CTX.FrmBuffer],ESI,16
     JC .F9312:
     ADDD [%FrmNdx],8
     JMP .20:
 .50:; Merge keyword operands. First store keywords from prototype with their default values.
     BufferRetrieve [EBX+STM.KeyBuffer]
     JECXZ .60:
 .52:PUSH ECX ; Loop .52: .. .60: keyword operands.
      MOV EDI,[ESI+0] ; NamePtr. 
      MOV ECX,[ESI+4] ; NameSize.
      PoolStore [%MpPassPool],EDI,ECX
      JC .F9312:
      MOV [%FrmVar+0],EAX ; Persistent ordinal name ptr.
      MOV [%FrmVar+4],ECX ; Ordinal name size.
      MOV EDI,[ESI+8] ; ValuePtr. 
      MOV ECX,[ESI+12] ; ValueSize.
      PoolStore [%MpPassPool],EDI,ECX
      MOV [%FrmVar+8],EAX ; Persistent default value ptr.
      MOV [%FrmVar+12],ECX ; Persistent default value size.
      LEA EDI,[%FrmVar]
      BufferStore [EDX+CTX.FrmBuffer],EDI,16 ; Save keyword with default value.
     POP ECX
     JNC .55:
.F9312:Msg '9312',EBX ; Allocation error expanding macro !1S.
     JMP .90:
 .55:ADD ESI,16
     SUB ECX,16
     JG .52:
 .60: ; Each keyword in macro invocation should be found in CTX.FrmBuffer, otherwise W2610,
      ; and its value will update the stored key.
     BufferRetrieve [EDX+CTX.KeyBuffer]
     JECXZ .90:
       MOV EDI,[ESI+0] ; Name ptr.
       MOV EAX,[ESI+4] ; Name size.
       ; Search for keyword EDI,EAX in CTX.FrmBuffer.
       BufferRetrieve [EDX+CTX.FrmBuffer]
       JECXZ .W2610: ; If keyword not found.
 .70:  Compare [ESI+0],[ESI+4],EDI,EAX
       JE .75: ; If keyword found.
       ADD ESI,16
       SUB ECX,16
       JG .70:
.W2610:MOV EAX,[ESP] ; ^QWORD keyword from CTX.KeyBuffer.
       Msg '2610',EAX,[EBX+STM.LinePtr]; Parameter "!1S=" was not specified in macro prototype at !2@. Ignored.       
       JMPS .80:
 .75:  ; Matching keyword in CTX.FrmBuffer is addressed with ESI,
       ; its default value will be overwritten with value from CTX.KeyBuffer.
       MOV EDI,[ESP] ; ^QWORD keyword from CTX.KeyBuffer.         
       MOV EAX,[EDI+8] ; Persistent new key value ptr.
       MOV ECX,[EDI+12] ; New key value size.
       MOV [ESI+8],EAX
       MOV [ESI+12],ECX
     ADD ESI,16
     SUB ECX,16
     JG .62:
.90:EndProcedure MacPrototype
↑ MacFind NamePtr, NameSize
MacFind searches for macro with given name on Pass.MacList belonging to all PROGRAMs on context stack, beginning with the last program. The search is case sensitive.
If the macro name is found on MacList but its MAC.LinePtr is NULL, which happens in %DROPMACRO, searching stops and does not continue with parent PROGRAMs.
NamePtr Pointer to macro name.
NameSize Size of macro name.
CF=0 EAX= pointer to MAC structure which contains macro name and LinePtr to the %MACRO definition statement.
CF=1 EAX=0 Macro was not found.
CF=1 EAX= ^MAC with this name, which was dropped.
Invoked by
PseudopcDROPMACRO PseudopcMACRO StmParse
Tested by
t8210 t8232
MacFind Procedure NamePtr, NameSize
       SUB EDI,EDI
       MOV [%ReturnEAX],EDI
 .10:  Invoke CtxPeek::,ctxPROGRAM,EDI
       JC .90:
       MOV EDI,EAX
       MOV EBX,[EAX+CTX.ObjPtr]
       TEST EBX
       JZ .10:
       MOV ECX,[EBX+PGM.PassPtr]
       JECXZ .10:
       MOV EDX,[ECX+PASS.MacList]
       ListGetLast EDX
 .50:  JZ .10:
       Compare [%NamePtr],[%NameSize],[EAX+MAC.NamePtr],[EAX+MAC.NameSize]
       JE .70:
       ListGetPrev EAX
       JMP .50:
 .70: MOV ECX,[EAX+MAC.LinePtr]
      JECXZ .90: ; Zero LinePtr signalizes that the macro was dropped.
      MOV [%ReturnEAX],EAX
 .90:EndProcedure MacFind
↑ MacListMerge ParentPass, ChildPass
MacListMerge copies macro names defined during ChildProgram.Pass to ParentProgram.Pass.MacList.
Names must be reallocated on ParentProgram.Pass.Pool because the ChildPass is about to end.
ParentPass Pointer to PASS to whose .MacList the macros will be copied to.
ChildPass Pointer to PASS whose .MacList contains source macro names defined in this pass, including dropped macros.
Macro names are copied.
not detected.
See also
Invoked by
MacListMerge Procedure ParentPass, ChildPass
     MOV EBX,[%ParentPass]
     MOV EDX,[%ChildPass]
     ListGetFirst [EDX+PASS.MacList]
     JZ .90:
 .10 MOV ESI,EAX ; Ptr to MAC.
     PoolStore [EBX+PASS.Pool],[ESI+MAC.NamePtr],[ESI+MAC.NameSize]
     MOV [ESI+MAC.NamePtr],EAX ; Reallocated ptr to name.
     ListStore [EBX+PASS.MacList],ESI
     ListGetNext ESI
     JNZ .10:
 .90:EndProcedure MacListMerge

▲Back to the top▲