| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# stdcal32.htm
Enumeration
%StdCall32
Macros
ClearLocalVar
EndProcedure
Invoke
LocalVar
Procedure

This file can be included to 32bit programs written in EuroAssembler. The library contains OS-independent macroinstructions `Procedure, EndProcedure, Invoke` 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.

All GP registers are calee-saved by the Procedure. Result value of the invokation can be returned from procedure by copying the value to stack-variables such as `%ReturnEAX`, which is defined by %StdCall32 as `EBP+28`.

Macroinstructions in this library comunicate at assembly time through the preprocessing %variables `%LvSize_ProcName` (total size of all local stack-variables) and `%ArgC_ProcName` (number of procedure parameters). Individualization of global %variable names allows to nest procedure definitions in one another.

    stdcal32 HEAD

↑ %StdCall32

  Implementation of 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.

  The following example shows stack-frame created by invoking Procedure with the name MyFn which has three parameters and uses two local stack variables named LocV1 and LocV2 with sizes 4 and 8. Prologue of `MyFn Procedure Param1, Param2, Param3` will assign "global" %variables `%ArgC_MyFn %SETA 3` and `%LvSize_MyFn %SETA 4+8` , they can be used in macros LocalVar, ClearLocalVar and by epilogue in `EndProcedure MyFn` during `Invoke MyFn, Param1, Param2, Param3`.

  MyFn Procedure Param1, Param2, Param3 LocV1 LocalVar ; Reserve local stack variable with default size 4. LocV2 LocalVar Size=8 ; Reserve another variable. ; MyFn body can use formal names Param1, Param2, Param3, LocV1, LocV2 ; to access its parameters and local stack variables by prefixing ; the formal name with `%`, for instance MOV EAX,[%Param1] MOV [%LocV1],EAX ; Macro EndProcedure discards local variables, restores all GPR and returns below Invoke, removing the pushed arguments. EndProcedure MyFn
  ESP after the step. │ Prologue in 8 steps │ Stack frame Epilogue in 3 steps │<──4 bytes─> 0.>┌──────────┐<12.continue below Invoke 1.PUSH Param3 │ %Param3 │ 1.>├──────────┤ 2.PUSH Param2 │ %Param2 │ 2.>├──────────┤ 3.PUSH Param1 │ %Param1 │ 3.>├──────────┤ 4.CALL Function │ return │ 12.RET 3*4 4.>├──────────┤<11. 5.PUSHAD │%ReturnEAX│ ├──────────┤ │%ReturnECX│ ├──────────┤ │%ReturnEDX│ ├──────────┤ │%ReturnEBX│ ├──────────┤ │%ReturnESP│ ├──────────┤ │%ReturnEBP│ ├──────────┤ │%ReturnESI│ ├──────────┤ 6.MOV EBP,ESP │%ReturnEDI│ 11.POPAD 5.6.>├──────────┤<10. 7.SUB ESP,4 │ %LocV1 │ 7.>├──────────┤ │ │ │ │ 8.SUB ESP,8 │ %LocV2 │ 10.MOV ESP,EBP 8.>└──────────┘<9. 9.Function body

    ; Formal names assignment:
    %Param8    %SET EBP+64
    %Param7    %SET EBP+60
    %Param6    %SET EBP+56
    %Param5    %SET EBP+52
    %Param4    %SET EBP+48
    %Param3    %SET EBP+44
    %Param2    %SET EBP+40
    %Param1    %SET EBP+36
    %ReturnEAX %SET EBP+28
    %ReturnECX %SET EBP+24
    %ReturnEDX %SET EBP+20
    %ReturnEBX %SET EBP+16
    %ReturnESP %SET EBP+12
    %ReturnEBP %SET EBP+08
    %ReturnESI %SET EBP+04
    %ReturnEDI %SET EBP+00

↑ Procedure Operand1, Operand2,,,
  This macro declares 32bit 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.
Input
  Label of Procedure statement is mandatory, it gives the procedure an invokable name.
  Operand* is argument passed to the procedure. It can be anything pushable as DWORD. Number of operands is not limited.
Output
  Macroinstruction will define global symbol, assign formal operands to %variables and emit machine instructions `PUSHAD` and `MOV EBP,ESP` as the procedure prolog.
Example
  Move Procedure Source,Destination,Size MOV ESI,[%Source] MOV EDI,[%Destination] MOV ECX,[%Size] REP MOVSB EndProcedure Move
  Macro Procedure in the previous example will assign
  %ArgC_Move %SETA 3 ; This %variable propagates to macro EndProcedure and tells how many parameters should be discarded. %LvSize_Move %SETA 0 ; This %variable propagates to macros LocalVar and ClearLocalVar, if they're used in Procedure body. %Source %SET EBP+36 ; These are formal %variables of all operands. %Destination %SET EBP+40 %Size %SET EBP+44

    Procedure %MACRO Operands ; Prologue of standard calling convention procedure.
    LblCheck    %IF "%:" === ""
                  %ERROR ID=5921, 'Macro "Procedure" requires a label.'
                  %EXITMACRO Procedure
                %ENDIF LblCheck
    %%ArgC_%:   %SETX %#
    %%LvSize_%: %SETX 0
    ArgNr       %FOR 1..%#, STEP= +1
    %%%*{%ArgNr}  %SETX EBP+(32+%ArgNr*4)
                %ENDFOR ArgNr
    %:::        PROC %=*, NESTINGCHECK=OFF
                PUSHAD
                MOV EBP,ESP
             %ENDMACRO Procedure

↑ LocalVar Size=4
  reserves and 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 `EBP-4` Block LocalVar Size=1K ; %Block is now `EBP-1028`. ClearLocalVar ; Fill Block and BlockSize with 0. MOV [%BlockSize],1K, DATA=DWORD LEA EDI,[%Block] ... EndProcedure ProcName
Input
  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=4 specifies how many bytes should be reserved for the local variable. It is rounded up to DWORD internally.
Output
  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 ESP,%Size` to reserve room on the machine stack.
  Macro LocalVar also maintains the "global" variable with dynamic name `%LvSize_ProcedureName` which was initialized in macro `Procedure`.

    LocalVar     %MACRO Size=4
    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.
    %ThisLvSize     %SETA (%Size + 3) & ~3            ; Round up the required size to DWORD.
    %GlbLvSize      %SET2 %%LvSize_%^PROC+%ThisLvSize ; Accumulate total size of all LocalVar.
    %%LvSize_%^PROC %SETX %GlbLvSize                  ; Update the "global" variable.
                    SUB ESP, %ThisLvSize              ; Allocate room on stack.
    %%%:            %SETX EBP-(%GlbLvSize)            ; 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.

Input
  Macro does not use explicit parameters. Pointer to the cleared memory is specified with `ESP`, cleared size is specified with "global" variable `%LvSize_CurrentProcName`.
Output
  EAX=ECX=0,
  EDI= ESP + %LvSize_CurrentProcName

    ClearLocalVar %MACRO
    %GlbLvSize %SET2 %%LvSize_%^PROC
               %IF %GlbLvSize
                 MOV EDI,ESP
                 MOV ECX,(%GlbLvSize) / 4
                 XOR EAX,EAX
                 REP STOSD
               %ENDIF
        %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 ESP,EBP`), restore all GP registers (using `POPAD`) and then return to the parent code which the Procedure was Invoked from (using `RET 4*%ArgC_ProcName`).
  Operands pushed on stack in the Invoke statement will be discarded here by this EndProcedure macro.
  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.

Input
  ProcName This macroinstruction requires exactly one operand which is identical with the label of previous corresponding `Procedure` statement.
Output
  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
    %NameStrip %SET %ProcName
               %WHILE "%NameStrip[%&]" === ":"
                 %NameStrip %SET %NameStrip[1..%&-1] ; Get rid of trailing colons.
               %ENDWHILE
    %ArgC      %SET2 %%ArgC_%NameStrip
    NestCheck  %IF "%ArgC" === ""
                 %ERROR ID=5925, '"%ProcName Procedure" statement missing.'
                 %EXITMACRO EndProcedure
               %ENDIF NestCheck
               MOV ESP,EBP
               POPAD
               RET 4 * (%ArgC)
               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 DWORDs, starting from the last. The procedure is then called and it is responsible for removing pushed arguments from stack.
  It's necessary to Invoke a procedure with exactly the same number of arguments which were declared by the Procedure macro.
Input
  ProcName The first operand is the name of invoked procedure.
  Arg* is a list of Procedure arguments.
Output
  The returned registers and flags depend on the invoked Procedure. By default all registers are preserved unless they return some value.

    Invoke %MACRO ProcName, Arguments
    ArgCheck %IF "%ProcName" === ""
               %ERROR ID=5926, 'Macro "Invoke" requires the name of called Procedure.'
               %EXITMACRO Invoke
             %ENDIF ArgCheck
    ArgNr    %FOR %#..2, STEP= -1
               PUSHD %*{%ArgNr}
             %ENDFOR ArgNr
             CALL %ProcName
           %ENDMACRO Invoke

      ENDHEAD stdcal32

▲Back to the top▲