Rational Developer for System z
PL/I for Windows, Version 8.0, Programming Guide

Examples using the STDCALL convention

The following examples are included for purposes of illustration and clarity only. The examples assume that you are familiar with programming in assembler. In the examples, the stack grows toward the bottom of the page, and ESP always points to the top of the stack.

For the following call, a, b, and c are 32-bit integers and func has two local variables, x and y (both 32-bit integers):

  m = func(a,b,c)

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

                                     Stack

                           .------------------------.       Higher Memory
                           |           c            |
                           '------------------------'
                           |           b            |
                           '------------------------'
                           |           a            |
                           '------------------------'
                           |     caller's EIP       |
                           '------------------------'
                           |     caller's EBP       |
           EBP  ------>    '------------------------'
                           |           x            |
                           '------------------------'
                           |           y            |
                           '------------------------'   <-.
                           |       Saved EDI        |     |
                           '------------------------'     | These would only
                           |       Saved ESI        |     | be pushed if they
                           '------------------------'     | were used in this
                           |       Saved EBX        |     | function.
           ESP  ------>    '------------------------'   <-'
                                                            Lower Memory

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@12
    .
    .
  MOV  m, EAX
    .
    .

For the callee, the code looks like this:

_func@12 PROC
         PUSH    EBP
         MOV     EBP, ESP           ; Allocating 8 bytes of storage
         SUB     ESP, 8             ;  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     0CH
_func@12 ENDP

The saved register set is EBX, ESI, and EDI.

Structures are not returned on the stack. The caller pushes the address where the returned structure is to be placed as a lexically first hidden parameter. A function that returns a structure must be aware that all parameters are four bytes farther away from EBP than they would be if no structure were involved. The address of the returned structure is returned in EAX.

Rational Developer for System z
PL/I for Windows, Version 8.0, Programming Guide