Chapter 21. Calling conventions. IBM Version 8.5
Quảng cáo
Quảng cáo
Chapter 21. Calling conventions
This chapter discusses the calling conventions used by PL/I for Windows:
OPTLINK
SYSTEM
STDCALL
CDECL
The OPTLINK linkage convention (see “OPTLINK linkage” on page 396 for
details) is also supported by VisualAge for C++ (OS/2 and Windows) and is the fastest method of calling PL/I procedures, C functions, or assembler routines.
OPTLINK is not, however, standard for all Windows applications.
On Windows, specifying SYSTEM linkage is synonymous with STDCALL linkage and is implemented the same as STDCALL. The compiler, however, considers the names SYSTEM and STDCALL to be distinct and complains if you mix them. The
STDCALL linking convention is described in “STDCALL linkage (Windows only)” on page 405.
You can specify the calling convention for all functions within a program using the
LINKAGE suboption of the DEFAULT compile-time option. You can also use the
LINKAGE option of the OPTIONS attribute to specify the linkage for individual functions.
Note:
You cannot call a function using a different calling convention than the one with which it is compiled. For example, if a function is compiled with
SYSTEM linkage, you cannot later call it specifying OPTLINK linkage.
Understanding linkage considerations
On Windows, there are three primary linkages that the PL/I compiler supports:
OPTLINK, CDECL, and STDCALL. On Windows, all the system services use the
STDCALL linkage.
These linkages differ in their parameter passing conventions: v
The OPTLINK linkage is the only one that attempts to pass some parameters in registers; the other linkages pass all the parameters on the stack.
v
The STDCALL linkage is the only one that makes the callee responsible for cleaning up the stack; the other linkages make the caller responsible.
The PL/I for Windows compiler interprets any specification of the SYSTEM linkage as if the STDCALL linkage were intended. The VisualAge C compiler does the same.
On Windows, all external names are decorated. If the external attribute does not specify a name, the name decoration depends on the linkage: v
Routines with the CDECL linkage have a '_' added as a prefix so that, for example, the name FUNKY would become _FUNKY.
v
Routines with the OPTLINK linkage have a '?' added as a prefix so that, for example, the name FUNKY would become ?FUNKY.
v
Routines with the STDCALL linkage have a '_' added as a prefix and a '@' followed by the bytes used by its parameters added as a suffix. For example,
© Copyright IBM Corp. 1998, 2012
395
Understanding linkage considerations
then, if the name FUNKY had two byvalue pointers or any two byaddr parameters, it would become _FUNKY@8.
One consequence of these name decorations is that if a caller of a routine specifies the wrong linkage for that routine, the program fails to link.
So far, the discussion of name decoration has applied only to routines for which the external attribute did not specify a name. It also applies when the external attribute specifies a name that differs only in case from the declared name. In these situations, the name specified as part of the external attribute is decorated.
For example, given the following declare, the name that the linker sees is
?getenv
.
dcl getenv ext(’getenv’) entry( char(*) varz byaddr nonasgn ) returns( pointer ) options( nodescriptor linkage(optlink) );
Similarly, for the following declare (for the Windows system routine that loads a
DLL), the name specified as part of the external attribute is decorated, and the linker sees the name as
_LoadLibraryA@4
.
dcl loadlibrarya ext(’LoadLibraryA’) entry( char(*) varz byaddr nonasgn ) returns( pointer byvalue ) options( linkage(stdcall) nodescriptor );
If, however, a name is specified as part of the external attribute and that name differs from the declared name by more than its case, then no name decoration occurs.
For example, given the following declare, no name decoration occurs and the name that the linker sees is
?getenv
.
dcl getenv ext(’?getenv’) entry( char(*) varz byaddr nonasgn ) returns( pointer ) options( nodescriptor linkage(optlink) );
Performing name decoration yourself as illustrated in this last example usually makes your code less portable. For instance, only the first declare for getenv in the preceding examples is valid for Windows and AIX.
OPTLINK linkage
This is the default calling convention. It is an alternative to SYSTEM linkage that is normally used for calls to the operating system. This linkage provides better total performance than SYSTEM linkage.
Features of OPTLINK
The OPTLINK convention has the following features: v
Parameters are pushed from right to left onto the stack.
v
The caller cleans up the stack.
v
The general-purpose registers EBX, EDI, and ESI are preserved across the call.
v
The general-purpose registers EAX, ECX, and EDX are not preserved across the call.
v
Floating-point registers are not preserved across the call.
396
PL/I for Windows Programming Guide
OPTLINK linkage
v
The three conforming parameters that are lexically leftmost (conforming parameters are the addresses for all BYADDR parameters and the following
BYVALUE parameters: pointer, handle, ordinal, offset, limited entry, real fixed binary, character(1), and nonvarying bits occupying 1 byte or less) are passed in the three unpreserved general-purpose registers.
v
Up to four real floating-point or two complex parameters (the lexically first four) are passed in extended precision format (80-bit) in the floating-point register stack.
v All conforming parameters not passed in registers and all nonconforming parameters are passed on the 80386 stack.
v
Space for the parameters in registers is allocated on the stack, but the parameters are not copied into that space.
v
Conforming return values are returned in EAX.
v
Real floating-point return values are returned in extended precision format in the topmost register of the floating-point stack.
v
Complex floating-point return values are returned in extended precision format in the topmost two registers of the floating-point stack.
v
When you are calling external functions, the floating-point register stack contains only valid parameter registers on entry, and valid return values on exit.
v
Functions returning aggregates pass the address of a storage area determined by the caller as a hidden parameter. This area becomes the returned aggregate. The address of this aggregate is returned in EAX.
v
The direction flag must be clear upon entry to functions, and clear on exit from functions. The state of the other flags is ignored on entry to a function, and undefined on exit.
v
The compiler does not change the contents of the floating-point control register.
If you want to change the control register contents for a particular operation, save the contents before making the changes and restore them after the operation.
Tips for using OPTLINK
By following the tips given below when you use OPTLINK linkage, you can improve the performance of your applications.
v
The conforming and floating-point parameters that are most heavily used should be lexically leftmost in the parameter list so they will be considered for registers first. If they are adjacent to each other, the preparation of the parameter list will be faster.
v
If you have a parameter that is used near the end of a function, put it at or near the end of the parameter list. If all of your parameters are used near the end of functions, consider using SYSTEM linkage.
v
Compile with OPTIMIZE. (See “OPTIMIZE” on page 99.)
General-purpose register implications
Parameters
EAX, EDX, and ECX are used for the lexically first three conforming parameters with EAX containing the first parameter, EDX the second, and ECX the third. Four bytes of stack storage are allocated for each register parameter that is present, but the parameters exist only in the registers at the time of the call.
Chapter 21. Calling conventions
397
General-purpose register implications
Examples of passing parameters
The following examples are included only for purposes of illustration and clarity and have not been optimized. These examples assume that you are familiar with programming in assembler. In each example, the stack grows toward the bottom of the page, and ESP always points to the top of the stack.
Passing conforming parameters to a routine
The following example shows the code sequences and a picture of the stack for a call to the function FUNC1. It is assumed that this program is compiled with the
PREFIX(NOFIXEDOVERFLOW) option.
dcl func1 entry( char(1), fixed bin(15), fixed bin(31), fixed bin(31) ) returns( fixed bin(31) ) options( byvalue nodescriptor ); dcl x fixed bin(15); dcl y fixed bin(31); y = func1(’A’, x, y+x, y); caller’s Code Up Until Call:
PUSH
SUB
MOV
MOV
MOVSX
ADD
CALL y
ESP, 12
AL, ’A’
DX, x
ECX, DX
ECX, y
FUNC1
; Push p4 onto the 80386 stack
; Allocate stack space for
; register parameters
; Put p1 into AL
; Put p2 into DX
; Sign-extend x to long
; Calculate p3 and put it into ECX
; Make call
Stack Just After Call
.
│ caller’s Local
├───────────────────┤
│ p4 │
.
│
├───────────────────┤
│ Blank Slot For p3 │
├───────────────────┤
│ Blank Slot For p2 │
├───────────────────┤
│ Blank Slot For p1 │
├───────────────────┤
│ caller’s EIP │
ESP ─── └───────────────────┘
Register Set Just After Call
┌─────────┬────┬───┐
EAX │ undefined │p1 │
├─────────┼────┼───┤
EBX │ caller’s EBX │
├─────────┼────┼───┤
ECX │ p3 │ │
├─────────┼────┼───┤
EDX │undefined│ p2 │
├─────────┼────┴───┤
EDI │ caller’s EDI │
├─────────┼────────┤
ESI │ caller’s ESI │
└─────────┴────────┘ callee’s Prolog Code:
PUSH
MOV
SUB
PUSH
PUSH
PUSH
EBP
EBP, ESP
; Save caller’s EBP
; Set up callee’s EBP
ESP, callee’s local size ; Allocate callee’s Local
EBX
EDI
ESI
Stack After Prolog
; Save preserved registers -
; will optimize to save
; only registers callee uses
Register Set After Prolog
.
.
│ caller’s Local │
├──────────────────┤
┌──────────┬────┬────┐
EAX │ undefined │p1 │
├──────────┼────┼────┤
398
PL/I for Windows Programming Guide
General-purpose register implications
│ p4 │
├──────────────────┤
│Blank Slot For p3 │
├──────────────────┤
│Blank Slot For p2 │
├──────────────────┤
│Blank Slot For p1 │
├──────────────────┤
│ caller’s EIP │
├──────────────────┤
│
.
│ caller’s EBP │
├──────────────────┤
│
.
.
callee’s Local .
.
.
│ │
├──────────────────┤
│ Saved EBX │
├──────────────────┤
│ Saved EDI │
├──────────────────┤
│ Saved ESI │
ESP ─── └──────────────────┘ callee’s Epilog Code:
MOV
POP
POP
POP
MOV
POP
RET
EBX │ undefined │
├──────────┼────┴────┤
ECX │ p3 │
├──────────┼────┬────┤
EDX │undefined │ p2 │
├──────────┼────┴────┤
EDI │ undefined │
├──────────┼─────────┤
ESI │ undefined │
└──────────┴─────────┘
The term "undefined" in registers EBX, EDI and ESI refers to the fact that they can be safely overwritten by the code in FUNC1.
EAX, RetVal ; Put return value in EAX
ESI ; Restore preserved registers
EDI
EBX
ESP, EBP
EBP
; Deallocate callee’s local
; Restore caller’s EBP
; Return to caller
ESP ───
Stack After Epilog
.
.
│ caller’s Local │
├──────────────────┤
│ p4 │
├──────────────────┤
│Blank Slot For p3 │
├──────────────────┤
│Blank Slot For p2 │
├──────────────────┤
│Blank Slot For p1 │
│ │
└──────────────────┘
Register Set After Epilog
┌─────────┬────┬──┐
EAX │ Return │Value │
├─────────┼────┼──┤
EBX │ caller’s EBX │
├─────────┼────┼──┤
ECX │ undefined │
├─────────┼────┼──┤
EDX │ undefined │
├─────────┼────┴──┤
EDI │ caller’s EDI │
├─────────┼───────┤
ESI │ caller’s ESI │
└─────────────────┘ caller’s Code Just After Call:
ADD
MOV
ESP, 16 y, EAX
; Remove parameters from stack
; Use return value.
Chapter 21. Calling conventions
399
General-purpose register implications
ESP ───
Stack After Cleanup
.
.
│caller’s Local │
└───────────────┘
Register Set After Cleanup
┌─────────┬────┬──┐
EAX │ Return │Value │
├─────────┼────┼──┤
EBX │ caller’s EBX │
├─────────┼────┼──┤
ECX │ undefined │
├─────────┼────┼──┤
EDX │ undefined │
├─────────┼────┴──┤
EDI │ caller’s EDI │
├─────────┼───────┤
ESI │ caller’s ESI │
└─────────────────┘
Passing floating-point parameters to a routine:
The following example shows code sequences, 80386 stack layouts, and floating-point register stack states for a call to the routine FUNC2. For simplicity, the general-purpose registers are not shown. It is assumed that this program is compiled with the IMPRECISE option.
dcl func2 entry( float bin(21), float bin(53), float bin(64), float bin(21), float bin(53) ) returns( float bin(53) ) options( byvalue nodescriptor ); dcl (a, b, c) float bin(53); dcl (d, e) float bin(21); a = b + func2(a, d, prec(a + c, 53), e, c); caller’s Code Up Until Call:
PUSH
PUSH
FLD
FLD
FADD
FLD
FLD
FSTP
FLD
SUB
CALL
2ND DWORD OF c
1ST DWORD OF c
DWORD_PTR e
FUNC2
; Push upper 4 bytes of c onto stack
; Push lower 4 bytes of c onto stack
; Load e into 80387, promotion
; requires no conversion code
QWORD_PTR a ; Load a to calculate p3
ST(0), QWORD_PTR c ; Calculate p3, result is float bin(64)
QWORD_PTR d
QWORD_PTR a
; from nature of 80387 hardware
; Load d, no conversion necessary
; Load a, demotion requires conversion
DWORD_PTR [EBP - T1] ; Store to a temp (T1) to convert to float
DWORD_PTR [EBP - T1] ; Load converted value from temp (T1)
ESP, 32 ; Allocate the stack space for
; parameter list
; Make call
400
PL/I for Windows Programming Guide
General-purpose register implications
Stack Just After Call
┌
│ caller’s Local
├────────────────────┤
│Upper Dword of p5 │
┐
│
├─ ── ── ── ── ── ─ ─┤
│Lower Dword of p5 │
├────────────────────┤
│Blank Dword for p4 │
├────────────────────┤
│ Four │
├─ ── ── ── ── ── ─ ─┤
│ Blank │
├─ ── ── ── ── ── ─ ─┤
│ Dwords │
├─ ── ── ── ── ── ─ ─┤
│ for p3 │
├────────────────────┤
│ Two Blank │
├─ ── ── ── ── ── ─ ─┤
│ Dwords for p2 │
├────────────────────┤
│Blank Dword for p1 │
├────────────────────┤
│ caller’s EIP │
ESP ─── └────────────────────┘
80387 Register Set Just After Call
┌──────────────────┐
ST(7) │ Empty │
├──────────────────┤
ST(6) │ Empty │
├──────────────────┤
ST(5) │ Empty │
├──────────────────┤
ST(4) │ Empty │
├──────────────────┤
ST(3) │ p4 (e) │
├──────────────────┤
ST(2) │ p3 (a + c) │
├──────────────────┤
ST(1) │ p2 (d) │
├──────────────────┤
ST(0) │ p1 (a) │
└──────────────────┘ callee’s Prolog Code:
PUSH
MOV
SUB
PUSH
PUSH
PUSH
EBP
EBP, ESP
; Save caller’s EBP
; Set up callee’s EBP
ESP, callee’s local size ; Allocate callee’s Local
EBX ; Save preserved registers -
EDI
ESI
; will optimize to save
; only registers callee uses
Chapter 21. Calling conventions
401
General-purpose register implications
Stack After Prolog
.
.
│ caller’s Local │
├───────────────────┤
│Upper Dword of p5 │
├─ ── ── ── ── ── ──┤
│Lower Dword of p5 │
├───────────────────┤
│Blank Dword for p4 │
├───────────────────┤
│ Four │
├─ ── ── ── ── ── ──┤
│ Blank │
├─ ── ── ── ── ── ──┤
│ Dwords │
├─ ── ── ── ── ── ──┤
│ for p3 │
├───────────────────┤
│ Two Blank │
├─ ── ── ── ── ── ──┤
│ Dwords for p2 │
├───────────────────┤
│Blank Dword for p1 │
├───────────────────┤
│ caller’s EIP │
├───────────────────┤
│ caller’s EBP │
├───────────────────┤
│ │
.
│
.
.
.
callee’s Local .
├───────────────────┤
│ Saved EBX │
.
│
├───────────────────┤
│ Saved EDI │
├───────────────────┤
│ Saved ESI │
ESP ─── └───────────────────┘ callee’s Epilog Code:
FLD
POP
POP
POP
MOV
POP
RET
RETVAL
ESI
EDI
EBX
ESP, EBP
EBP
80387 Register Set After Prolog
┌────────────────┐
ST(7) │ Empty │
├────────────────┤
ST(6) │ Empty │
├────────────────┤
ST(5) │ Empty │
├────────────────┤
ST(4) │ Empty │
├────────────────┤
ST(3) │ p4 │
├────────────────┤
ST(2) │ p3 │
├────────────────┤
ST(1) │ p2 │
├────────────────┤
ST(0) │ p1 │
└────────────────┘
; Load return value onto floating-point stack
; Restore preserved registers
; Deallocate callee’s local
; Restore caller’s EBP
; Return to caller
402
PL/I for Windows Programming Guide
General-purpose register implications
Stack After Epilog
.
│ caller’s Local
├────────────────────┤
│Upper Dword of p5 │
.
│
├─ ── ── ── ── ── ─ ─┤
│Lower Dword of p5 │
├────────────────────┤
│Blank Dword for p4 │
├────────────────────┤
│ Four │
├─ ── ── ── ── ── ─ ─┤
│ Blank │
├─ ── ── ── ── ── ─ ─┤
│ Dwords │
├─ ── ── ── ── ── ─ ─┤
│ for p3 │
├────────────────────┤
│ Two Blank │
├─ ── ── ── ── ── ─ ─┤
│ Dwords for p2 │
├────────────────────┤
│Blank Dword for p1 │
ESP ─── └────────────────────┘
80387 Register Set After Epilog
┌─────────────────┐
ST(7) │ Empty │
├─────────────────┤
ST(6) │ Empty │
├─────────────────┤
ST(5) │ Empty │
├─────────────────┤
ST(4) │ Empty │
├─────────────────┤
ST(3) │ Empty │
├─────────────────┤
ST(2) │ Empty │
├─────────────────┤
ST(1) │ Empty │
├─────────────────┤
ST(0) │ Return Value │
└─────────────────┘ caller’s Code Just After Call:
ADD
FADD
FSTP
ESP, 40 ; Remove parameters from stack
QWORD_PTR b ; Use return value
QWORD_PTR a ; Store expression to variable a
Stack After Cleanup
.
.
│ caller’s Local │
│ │
ESP ─── └────────────────┘
80387 Register Set After Cleanup
┌───────────────────┐
ST(7) │ Empty │
├───────────────────┤
ST(6) │ Empty │
├───────────────────┤
ST(5) │ Empty │
├───────────────────┤
ST(4) │ Empty │
├───────────────────┤
ST(3) │ Empty │
├───────────────────┤
ST(2) │ Empty │
├───────────────────┤
ST(1) │ Empty │
├───────────────────┤
ST(0) │ Return Value │
└───────────────────┘
SYSTEM linkage
To use this linkage convention, you must specify the
OPTIONS(LINKAGE(SYSTEM)) attribute in the declaration of the function, or specify the DEFAULT(LINKAGE(SYSTEM)) compile-time option.
Features of SYSTEM
The following rules apply to the SYSTEM linkage convention: v
All parameters are passed on the 80386 stack.
v
Parameters are pushed onto the stack in right-to-left order.
Chapter 21. Calling conventions
403
SYSTEM linkage
v
The calling function is responsible for removing parameters from the stack.
v
All parameters are doubleword (4-byte) aligned.
v
Values are returned in the same manner as the OPTLINK linkage.
v
The direction flag must be clear upon entry to functions and clear on exit from functions. The state of the other flags is ignored on entry to a function, and undefined on exit.
v The compiler does not change the contents of the floating-point control register.
If you want to change the control register contents for a particular operation, save the contents before making the changes and restore them after the operation.
Example using SYSTEM linkage
The following example is included only for purposes of illustration and clarity and has not been optimized. The example assumes that you are familiar with programming in assembler. In the example, the stack grows toward the bottom of the page, and ESP always points to the top of the stack.
The following example shows the code sequences and a picture of the stack for a call to the function FUNC3 which has two local variables, x and y (both fixed bin(31)). For the call dcl func3 entry( fixed bin(31), fixed bin(31), fixed bin(31) ) returns( fixed bin(31) ) options( byvalue nodescriptor linkage(system) ); m = func3(a,b,c); the stack for the call to FUNC3 would look like this:
Stack
EBP ─────→
ESP ─────→
┌───────────────────────┐
│ c │
├───────────────────────┤
│ b │
├───────────────────────┤
│ a │
├───────────────────────┤
│ caller’s EIP │
├───────────────────────┤
│ caller’s EBP │
├───────────────────────┤
│ x │
├───────────────────────┤
Higher Memory
│ y │
├───────────────────────┤ ─┐
│ Saved EDI │
├───────────────────────┤
│
│These would only
│ Saved ESI │
├───────────────────────┤
│be pushed if they
│were used in this
│ Saved EBX │ │function.
└───────────────────────┘ ←─┘
Lower Memory
The instructions used to build this activation record on the stack look like this on the calling side:
PUSH
PUSH
PUSH c b a
404
PL/I for Windows Programming Guide
SYSTEM linkage
MOV
CALL
.
.
ADD
.
.
MOV
.
.
AL, 3H func3
ESP, 12 m, EAX
; Cleaning up the parameters
For the callee, the code looks like this: func3 PROC
PUSH
MOV
SUB
PUSH
PUSH
PUSH
.
.
MOV
MOV
.
.
XOR
POP
POP
POP
LEAVE
EBP
EBP, ESP
ESP, 8
EDI
ESI
EBX
EAX, EAX
EBX
ESI
EDI
; Allocating 8 bytes of storage
; for two local variables.
; These would only be
; pushed if they were used
; in this function.
EAX, [EBP - 8] ; Load y into EAX
EBX, [EBP + 12] ; Load b into EBX
; Zero the return value
; Restore the saved registers
; Equivalent to MOV ESP, EBP
; POP EBP
RET func3 ENDP
The saved register set is EBX, ESI, and EDI. The other registers (EAX, ECX, and
EDX) can have their contents changed by a called routine.
Under some circumstances, the compiler does not use EBP to access automatic and parameter values, thus increasing the application's efficiency. Whether it is used or not, EBP does not change across the call.
When passing aggregates by value, the compiler generates code to copy the aggregate on to the 80386 stack. If the size of the aggregate is larger than an 80386 page size (4K), the compiler generates code to copy the aggregate backward (that is, the last byte in the aggregate is the first to be copied).
Aggregates are not returned on the stack. The caller pushes the address where the returned aggregate is to be placed as a lexically first hidden parameter. A function that returns an aggregate must be aware that all parameters are 4 bytes farther away from EBP than they would be if no aggregate return were involved. The address of the returned aggregate is returned in EAX.
STDCALL linkage (Windows only)
To use this linkage convention, you must specify the
OPTIONS(LINKAGE(STDCALL)) attribute in the declaration of the function, or specify the DEFAULT(LINKAGE(STDCALL)) compile-time option.
Chapter 21. Calling conventions
405
STDCALL linkage
Features of STDCALL
The following rules apply to the STDCALL calling convention: v
All parameters are passed on the stack.
v
The parameters are pushed onto the stack in a lexical right-to-left order.
v
The
called
function removes the parameters from the stack.
v Floating point values are returned in ST(0) , the top register of the floating point register stack. Functions returning aggregate values return them as follows:
Size of Aggregate
Value Returned in
8 bytes
EAX-EDX pair
5, 6, 7 bytes
EAX The address to place the return values is passed as a hidden parameter in EAX.
4 bytes
EAX
3 bytes
EAX The address to place the return values is passed as a hidden parameter to EAX.
2 bytes
AX
1 byte
AL
For functions that return aggregates 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 is passed back in
EAX
.
v
STDCALL has the restriction that an unprototyped STDCALL function with a variable number of arguments will not work.
v
Function names are decorated with an underscore prefix, and a suffix which consists of an at sign (@), followed by the number of bytes of parameters (in decimal). Parameters of less than four bytes are rounded up to four bytes.
Structure sizes are also rounded up to a multiple of four bytes. For example, consider a function fred prototyped as follows: dcl fred ext entry (fixed bin(31) byvalue, fixed bin(31) byvalue, fixed bin(15) byvalue);
It would appear as follows in the object module:
_FRED@12
When building export lists in
.DEF
files, the decorated version of the name should be used. If you use undecorated names in the DEF file, you must give the object files to ILIB along with the DEF file. ILIB uses the object files to determine how each name ended up after decoration.
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.
406
PL/I for Windows Programming Guide
STDCALL linkage
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
EBP ─────
ESP ─────
┌───────────────────────┐
│ c │
├───────────────────────┤
│ b │
├───────────────────────┤
│ a │
├───────────────────────┤
│ caller’s EIP │
├───────────────────────┤
│ caller’s EBP │
├───────────────────────┤
│ x │
├───────────────────────┤
│ y │
├───────────────────────┤ ─┐
│ Saved EDI │ │
Higher Memory
├───────────────────────┤
│ Saved ESI │
├───────────────────────┤
│ Saved EBX │
└───────────────────────┘ ─┘
│These would only
│be pushed if they
│were used in this
│function.
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
MOV
SUB
PUSH
.
.
PUSH
PUSH
.
.
MOV
MOV
XOR
POP
POP
POP
LEAVE
EBP
EBP, ESP
ESP, 8
EDI
ESI
EBX
; Allocating 8 bytes of storage
; for two local variables.
; These would only be
; pushed if they were used
; in this function.
EAX, [EBP - 8] ; Load y into EAX
EBX, [EBP + 12] ; Load b into EBX
EAX, EAX
EBX
ESI
EDI
; Zero the return value
; Restore the saved registers
; Equivalent to MOV ESP, EBP
; POP EBP
RET
_func@12 ENDP
0CH
Chapter 21. Calling conventions
407
STDCALL linkage
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.
Using WinMain (Windows only)
You can use WinMain by specifying OPTIONS(WINMAIN) on the procedure statement (see the PL/I Language Reference for syntax). This automatically implies
LINKAGE(STDCALL) and EXT('WinMain').
Your WinMain routine needs four parameters: v
An instance handle v
A previous handle v
A pointer to the command line v
An integer to be passed to ShowWindow
These are the same four parameters expected by WinMain in C. The calls made inside this routine are the same as those expected from a C routine.
An example guisamp.pli
is provided in the samples directory (see the program prolog for more details)
CDECL linkage
To use this linkage convention, you must specify the
OPTIONS(LINKAGE(CDECL)) attribute in the declaration of the function, or specify the DEFAULT(LINKAGE(CDECL)) compile-time option.
Features of CDECL
The following rules apply to the CDECL calling convention: v
All parameters are passed on the stack.
v
The parameters are pushed onto the stack in a lexical right-to-left order.
v
The
calling
function removes the parameters from the stack.
v
Floating point values are returned in
ST(0)
. All functions returning non-floating point values return them in
EAX
, except for the special case of returning aggregates less than or equal to eight bytes in size. For functions that return aggregates less than or equal to four bytes in size, the values are returned as follows:
Size of Aggregate
Value Returned in
8 bytes
EAX-EDX pair
5, 6, 7 bytes
EAX The address to place return values is passed as a hidden parameter in EAX.
4 bytes
EAX
408
PL/I for Windows Programming Guide
CDECL linkage
3 bytes
EAX The address to place return values is passed as a hidden parameter to EAX.
2 bytes
AX
1 byte
AL
For functions that return aggregates 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 is passed back in
EAX
.
v
Function names are decorated with an underscore prefix when they appear in object modules. For example, a function named fred in the source program will appear as
_fred in the object.
When building export or import lists in
.DEF
files, the decorated version of the name should be used. If you used undecorated names in the DEF file, you must give the object files to ILIB along with the DEF file. ILIB uses the object files to determine how each name ended up after decoration.
Examples using the CDECL convention
The following examples are included for purposes of illustration and clarity only.
They have not been optimized. 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.
Consider the following call: m = func(a,b,c);
The variables 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:
Stack
EBP ─────
ESP ─────
┌───────────────────────┐
│ c │
├───────────────────────┤
│ b │
├───────────────────────┤
│ a │
├───────────────────────┤
│ caller’s EIP │
├───────────────────────┤
Higher Memory
│ caller’s EBP │
├───────────────────────┤
│ x │
├───────────────────────┤
│ y │
├───────────────────────┤ ─┐
│ Saved EDI │
├───────────────────────┤
│
│These would only
│ Saved ESI │
├───────────────────────┤
│be pushed if they
│were used in this
│ Saved EBX │ │function.
└───────────────────────┘ ─┘
Lower Memory
Chapter 21. Calling conventions
409
CDECL linkage
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
MOV
SUB
PUSH
PUSH
PUSH
.
.
MOV
MOV
.
.
XOR
POP
POP
POP
LEAVE
EBP
EBP, ESP
ESP, 08H
EDI
ESI
EBX
EAX, EAX
EBX
ESI
EDI
; Allocating 8 bytes of storage
; for two local variables.
; These would only be
; pushed if they were used
; in this function.
EAX, [EBP - 8] ; Load y into EAX
EBX, [EBP + 12] ; Load b into EBX
; Zero the return value
; Restore the saved registers
; 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.
410
PL/I for Windows Programming Guide
Tải xuống
Quảng cáo