### Examples Using the __cdecl Convention

The following examples are for illustration only. They have not been optimized. The examples assume that you are familiar with programming in assembler. Note that, in the examples, the stack grows toward the bottom of the page, and ESP always points to the top of the stack.

For the call

       m = func(a,b,c);

a, b, and c are 32-bit integers and func has two local variables, x and y (both 32-bit integers).

The stack for the call to func would look like this:

The instructions used to create this activation record on the stack look like this on the calling side:

       PUSH    c
       PUSH    b
       PUSH    a
       CALL    _func
           .
           .
       ADD     ESP, 12    ; Cleaning up the parameters
           .
           .
       MOV     m, EAX
           .
           .

For the callee, the code looks like this:

    _func PROC
       PUSH    EBP
       MOV     EBP, ESP       ;  Allocating 8 bytes of storage
       SUB     ESP, 08H       ;   for two local variables.
       PUSH    EDI            ; These would only be
       PUSH    ESI            ;  pushed if they were used
       PUSH    EBX            ;  in this function.
       .
       .
       MOV     EAX, [EBP - 8]    ; Load y into EAX
       MOV     EBX, [EBP + 12]   ; Load b into EBX
       .
       .
       XOR     EAX, EAX           ; Zero the return value
       POP     EBX                ; Restore the saved registers
       POP     ESI
       POP     EDI
       LEAVE                      ; Equivalent to  MOV   ESP, EBP
                                  ;                POP   EBP
       RET
    _func ENDP

The saved register set is EBX, ESI, and EDI. In the case where the structure is passed as a value parameter and the size of the structure is 5, 6, 7, or more than 8 bytes in size, the address to place the return values is passed as a hidden parameter, and the address passed back in EAX.

        struct test_tag {
                 int a;
                 int some_array[100];
                 } test_struct;

       struct test_tag __cdecl test_function(struct test_tag test_parm)
       {
          test_parm.a = 42;
          return test_parm;
       }

       int main(void)
       {
          test_struct = test_function(test_struct);
          return test_struct.a;
       }

The code generated for the above example would be:

    _test_function  PROC
       PUSH    EDI
       PUSH    ESI
       MOV     DWORD PTR [ESP+0cH], 02aH   ; test_parm.a
       MOV     EAX, [ESP+08H]              ; Get the target of the return value
       MOV     EDI, EAX                    ; Value
       LEA     ESI, [ESP+0cH]              ; test_parm
       REP MOVSD
       POP     ESI
       POP     EDI
       RET
    _test_function  ENDP

       PUBLIC  ?main
    ?main  PROC
       PUSH    EBP
       MOV     EBP, ESP
       PUSH    ESI
       PUSH    EDI

       SUB     ESP, 0194H                  ; Adjust the stack pointer
       MOV     EDI, ESP
       MOV     ESI, OFFSET FLAT:_test_struct
       MOV     ECX, 065H
       REP MOVSD                           ; Copy the parameter
       PUSH    OFFSET FLAT:_test_struct    ; Push the address of the target
       CALL    _TEST_FUNCTION
       ADD     ESP,0198H

       MOV     EAX, DWORD PTR _test_struct  ; Take care of the return
       POP     EDI                         ;  from main
       POP     ESI
       LEAVE
       RET
    ?main   ENDP

Calling Conventions

__cdecl Calling Convention