EuroAssembler Index Manual Download Source Macros

Sitemap Links Forum Tests Projects


This file can be included to 16bit programs written in EuroAssembler. The library contains OS-independent macroinstructions which extend generic pseudoinstruction PROC, ENDPROC, CALL.

Macroinstructions Procedure and EndProcedure hide the prologue and epilogue of standard call calling convention , where the arguments are pushed backwards and they are removed by the called procedure.

Macroinstructions in this library comunicate with one another at assembly time using the preprocessing %variables %LocalFrameSize and %NrOfArg_ProcedureName.

doscall HEAD
↑ %StdCall16

Implementation of 16bit standard call convention in €ASM uses formal %names for accessing Procedure parameters, local stack-memory variables and all eight general-purpose registers saved on stack.

Following example shows the stack frame created by invoking Procedure with the name Function which has three parameters and uses two local stack variables with sizes 2 and 4. Prologue of Function Procedure Par1, Par2, Par3 will assign "global" %variables %NrOfArg_Function %SETA 3 and %LocalFrameSize %SETA 2+4 , they will be used by epilogue in EndProcedure Function during Invoke Function, Param1, Param2, Param3.

SP after the step. Prologue in 8 steps Stack frame Epilogue in 3 steps 0.>┌──────────┐<12.continue below Invoke 1.PUSH Par3 │%Par3 │ 1.>├──────────┤ 2.PUSH Par2 │%Par2 │ 2.>├──────────┤ 3.PUSH Par1 │%Par1 │ 3.>├──────────┤ 4.CALL Function │return VA │ 12.RET 3*2 4.>├──────────┤<11. 5.PUSHAW │%ReturnAX │ ├──────────┤ │%ReturnCX │ ├──────────┤ │%ReturnDX │ ├──────────┤ │%ReturnBX │ ├──────────┤ │%ReturnSP │ ├──────────┤ │%ReturnBP │ ├──────────┤ │%ReturnSI │ ├──────────┤ 6.MOV BP,SP │%ReturnDI │ 11.POPAW 5.6.>├──────────┤<10. 7.SUB SP,SIZE#LocalVar1 │%LocalVar1│ 7.>├──────────┤ │ │ │ │ 8.SUB SP,SIZE#LocalVar2 │%LocalVar2│ 10.MOV SP,BP 8.>└──────────┘<9. 9.Function body
; Formal %names assignment:
%Par4     %SET BP+24
%Par3     %SET BP+22
%Par2     %SET BP+20
%Par1     %SET BP+18
%ReturnAX %SET BP+14
%ReturnCX %SET BP+12
%ReturnDX %SET BP+10
%ReturnBX %SET BP+08
%ReturnSP %SET BP+06
%ReturnBP %SET BP+04
%ReturnSI %SET BP+02
%ReturnDI %SET BP+00
↑ Procedure Operand1, Operand2,,,
This macro declares 16bit StdCall-procedure prolog which, unlike ordinary pseudoinstruction PROC, accepts ordinal operands.
Macro operands will be assigned to preprocessing %variables using the operand formal name prefixed with a percent sign.
Label of Procedure statement is mandatory, it gives the procedure a name. Number of operands is not limited.
Macroinstruction will define global symbol, assign formal operands to %variables and emit machine instructions PUSHAW and MOV BP,SP as the procedure prolog.
Move Procedure Source,Destination,Size MOV SI,[%Source] MOV DI,[%Destination] MOV CX,[%Size] REP MOVSB EndProcedure Move
Macro Procedure in the previous example will assign
%NrOfArg_Move %SET 3 ; This %variable propagates to the corresponding macro EndProcedure Move. %LocalFrameSize %SETA 0 ; This %variable propagates to macro LocalVar, if used in Move Procedure. %Source %SET BP+18 ; These are formal %variables of all operands. %Destination %SET BP+20 %Size %SET BP+22
Procedure %MACRO Operands ; Prologue of standard calling convention procedure.
 LblCheck %IF "%:" == ""
           %ERROR ID=5921, 'Macro "Procedure" requires a label.'
           %EXITMACRO Procedure
          %ENDIF LblCheck
          %%NrOfArg_%: %SETX %#
          %LocalFrameSize %SETA 0
          ArgNr %FOR 1..%#, STEP=+1
           %%%*{%ArgNr} %SETX BP+(16+%ArgNr<<1)                                                                        ; >>
          %ENDFOR ArgNr
      %::: PROC %=*, NESTINGCHECK=OFF ; Open the namespace.
           MOV BP,SP
        %ENDMACRO Procedure
↑ LocalVar Size=2
declares local memory variable with the given Size allocated on machine stack. Example:
ProcName: Procedure Arg1,Arg2,Arg3 BlockSize LocalVar ; %BlockSize is now assigned with BP-2 Block LocalVar Size=1K ; %Block is now BP-1026. ClearLocalVar ; Fill Block and BlockSize with 0. MOV [%BlockSize],1K, DATA=WORD LEA DI,[%Block] ; DI is now offset of Block in segment SS. ... EndProcedure ProcName
Plain identifier must be defined as a label of LocalVar statement. It does not need to be unique in the program because it does not declare assembly symbol. The name will be prefixed with % and used as preprocessing %variable for addressing parameters withing the procedure body.
Size=2 specifies how many bytes should be reserved for the local variable.
Macro will define a preprocessing %variable with the name which was defined as the label but it is now prefixed with percent sign. Then it will emit machine instruction SUB SP,%Size to reserve room on the machine stack.
Macro LocalVar also maintains the "global" variable %LocalFrameSize which was initialized in macro Procedure.
LocalVar %MACRO Size=2
 LblCheck %IF "%:"==""
            %ERROR ID=5922, 'Macro "LocalVar" requires a label.'
            %EXITMACRO LocalVar
          %ENDIF LblCheck
SizeCheck %IF %#
            %ERROR ID=5923, 'Macro "LocalVar" does not expect ordinal parameters.'
            %EXITMACRO LocalVar
          %ENDIF SizeCheck
       %: %COMMENT         ; This makes the label of macro invocation void
          %ENDCOMMENT %:   ; so it does not declare a symbol.
          %LocalVarSize   %SETA (%Size + 1) & ~1 ; Round up to WORD.
          %LocalFrameSize %SETA %LocalFrameSize + %LocalVarSize
          SUB SP, %LocalVarSize
     %%%: %SETX BP-%LocalFrameSize ; Assign formal %name to the id specified with LocalVar label.
         %ENDMACRO LocalVar
↑ ClearLocalVar
This macro zeroes all variables on stack previously declared with LocalVar. ClearLocalVar should be expanded right after LocalVar declarations, before any stack operations are made.
We could as well decide to initialize each local variable individually, in this case the macro ClearLocalVar will not be used in the Procedure body at all.
Macro does not use explicit parameters. Pointer to the cleared memory is specified with SP, cleared size is specified with "global" variable %LocalFrameSize.
DI= SP + %LocalFrameSize
ClearLocalVar %MACRO
       %IF %LocalFrameSize
         MOV DI,SP
         MOV CX,%LocalFrameSize/2
         PUSH ES,SS
           POP ES
           XOR AX,AX
           REP STOSW
         POP ES
    %ENDMACRO ClearLocalVar
↑ EndProcedure ProcName

Macro EndProcedure terminates context of the previously opened Procedure . This epilogue of StdCall convention will discard local variables defined with LocalVar using machine instruction MOV SP,BP, restore all GP registers using POPAW and then return to the parent code which the Procedure was Invoked from.
Operands pushed on stack in the Invoke statement will be discarded here by this EndProcedure macro, using RET 2 * NrOfArg.
All registers are preserved throughout the procedure invocation unless the procedure changed their stored value on the stack frame (writing to [%ReturnEAX] for instance).
CPU flags are not preserved, EndProcedure returns with the same flag values which were set at the EndProcedure entry.

Programmer should never use explicit machine instruction RET to return from the block defined with Procedure .. EndProcedure . If premature return is required, jump to the label of EndProcedure statement instead.
ProcName This macroinstruction requires exactly one operand which is identical with the label of previous corresponding Procedure statement.
Stack frame is released, current process returns below Invoke statement.
EndProcedure %MACRO ProcName
 OpCheck  %IF "%ProcName" == ""
            %ERROR ID=5924, 'Macro "EndProcedure" requires one operand.'
            %EXITMACRO EndProcedure
          %ENDIF OpCheck
          %ProcNameStrip %SET %ProcName
          %WHILE "%ProcNameStrip[%&]" == ":" ; Get rid of trailing colons.
            %ProcNameStrip %SET %ProcNameStrip[1..%&-1]
 %NrOfArg %SET2 %%NrOfArg_%ProcNameStrip
 NestChck %IF "%NrOfArg" == ""
             %ERROR ID=5925, '"%ProcName Procedure" statement missing.'
             %EXITMACRO EndProcedure
          %ENDIF NestChck
          MOV SP,BP
          RET 2 * %NrOfArg
          ENDP %ProcName, NESTINGCHECK=OFF ; Terminate the namespace.
      %ENDMACRO EndProcedure
↑ Invoke ProcName, Arg1, Arg2, ...
Invoke is a replacement of standard CALL instruction which can pass parameters to the Procedure. Arguments are pushed on stack as WORDs, starting from the last. The procedure is then called and it is responsible for removing pushed arguments from stack.
It is necessary to Invoke a procedure with exactly the same number of arguments which were declared by the Procedure macro.
ProcName The first operand is the name of invoked procedure.
Arg* is a list of Procedure arguments.
The returned registers and flags depend on the invoked Procedure. By default all registers are preserved unless they return some value.
Invoke %MACRO StdProcedure, Arguments
 ArgCheck %IF "%StdProcedure" == ""
            %ERROR ID=5926, 'Macro "Invoke" requires the name of called Procedure.'
            %EXITMACRO Invoke
          %ENDIF ArgCheck
   ArgNr %FOR %#..2, STEP= -1
            PUSHW %*{%ArgNr}
         %ENDFOR ArgNr
         CALL %StdProcedure
       %ENDMACRO Invoke
  ENDHEAD doscall

▲Back to the top▲