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 y ; Push p4 onto the 80386 stack
SUB ESP, 12 ; Allocate stack space for
; register parameters
MOV AL, 'A' ; Put p1 into AL
MOV DX, x ; Put p2 into DX
MOVSX ECX, DX ; Sign-extend x to long
ADD ECX, y ; Calculate p3 and put it into ECX
CALL FUNC1 ; Make call
Stack Just After Call Register Set Just After Call
· · .---------.----.----.
| caller's Local | EAX | undefined | p1 |
'--------------------' '---------+----+----'
| p4 | EBX | caller's EBX |
'--------------------' '---------+----+----'
| Blank Slot For p3 | ECX | p3 | |
'--------------------' '---------+----+----'
| Blank Slot For p2 | EDX |undefined| p2 |
'--------------------' '---------+----'----'
| Blank Slot For p1 | EDI | caller's EDI |
'--------------------' '---------+---------'
| caller's EIP | ESI | caller's ESI |
ESP ---> '--------------------' '---------'---------'
callee's Prolog Code:
PUSH EBP ; Save caller's EBP
MOV EBP, ESP ; Set up callee's EBP
SUB ESP, callee's local size ; Allocate callee's Local
PUSH EBX ; Save preserved registers -
PUSH EDI ; will optimize to save
PUSH ESI ; only registers callee uses
Stack After Prolog Register Set After Prolog
· · .----------.----.----.
| caller's Local | EAX | undefined | p1 |
'-------------------' '----------+----+----'
| p4 | EBX | undefined |
'-------------------' '----------+----'----'
| Blank Slot For p3 | ECX | p3 |
'-------------------' '----------+----.----'
| Blank Slot For p2 | EDX |undefined | p2 |
'-------------------' '----------+----'----'
| Blank Slot For p1 | EDI | undefined |
'-------------------' '----------+---------'
| caller's EIP | ESI | undefined |
'-------------------' '----------'---------'
| caller's EBP |
'-------------------' The term "undefined" in
| | registers EBX, EDI and ESI
. . refers to the fact that they
. callee's Local . can be safely overwritten by
. . the code in FUNC1.
| |
'-------------------'
| Saved EBX |
'-------------------'
| Saved EDI |
'-------------------'
| Saved ESI |
ESP --> '-------------------'
callee's Epilog Code:
MOV EAX, RetVal ; Put return value in EAX
POP ESI ; Restore preserved registers
POP EDI
POP EBX
MOV ESP, EBP ; Deallocate callee's local
POP EBP ; Restore caller's EBP
RET ; Return to caller
Stack After Epilog Register Set After Epilog
· · .---------.----.---.
| caller's Local | EAX | Return|Value |
'-------------------' '---------+----+---'
| p4 | EBX | caller's EBX |
'-------------------' '---------+----+---'
| Blank Slot For p3 | ECX | undefined |
'-------------------' '---------+----+---'
| Blank Slot For p2 | EDX | undefined |
'-------------------' '---------+----'---'
| Blank Slot For p1 | EDI | caller's EDI |
| | '---------+--------'
ESP ---> '-------------------' ESI | caller's ESI |
'---------'--------'
caller's Code Just After Call:
ADD ESP, 16 ; Remove parameters from stack
MOV y, EAX ; Use return value.
Stack After Cleanup Register Set After Cleanup
· · .---------.----.---.
| caller's Local | EAX | Return|Value |
ESP ---> '----------------' '---------+----+---'
EBX | caller's EBX |
'---------+----+---'
ECX | undefined |
'---------+----+---'
EDX | undefined |
'---------+----'---'
EDI | caller's EDI |
'---------+--------'
ESI | caller's ESI |
'---------'--------'
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 2ND DWORD OF c ; Push upper 4 bytes of c onto stack
PUSH 1ST DWORD OF c ; Push lower 4 bytes of c onto stack
FLD DWORD_PTR e ; Load e into 80387, promotion
; requires no conversion code
FLD QWORD_PTR a ; Load a to calculate p3
FADD ST(0), QWORD_PTR c ; Calculate p3, result is float bin(64)
; from nature of 80387 hardware
FLD QWORD_PTR d ; Load d, no conversion necessary
FLD QWORD_PTR a ; Load a, demotion requires conversion
FSTP DWORD_PTR [EBP - T1] ; Store to a temp (T1) to convert to float
FLD DWORD_PTR [EBP - T1] ; Load converted value from temp (T1)
SUB ESP, 32 ; Allocate the stack space for
; parameter list
CALL FUNC2 ; Make call
Stack Just After Call 80387 Register Set Just After Call
. . .-------------------.
| caller's Local | ST(7) | Empty |
'---------------------' '-------------------'
| Upper Dword of p5 | ST(6) | Empty |
'- -- -- -- -- -- -- -' '-------------------'
| Lower Dword of p5 | ST(5) | Empty |
'---------------------' '-------------------'
| Blank Dword for p4 | ST(4) | Empty |
'---------------------' '-------------------'
| Four | ST(3) | p4 (e) |
'- -- -- -- -- -- -- -' '-------------------'
| Blank | ST(2) | p3 (a + c) |
'- -- -- -- -- -- -- -' '-------------------'
| Dwords | ST(1) | p2 (d) |
'- -- -- -- -- -- -- -' '-------------------'
| for p3 | ST(0) | p1 (a) |
'---------------------' '-------------------'
| Two Blank |
'- -- -- -- -- -- -- -'
| Dwords for p2 |
'---------------------'
| Blank Dword for p1 |
'---------------------'
| caller's EIP |
ESP ----> '---------------------'
callee's Prolog Code:
PUSH EBP ; Save caller's EBP
MOV EBP, ESP ; Set up callee's EBP
SUB ESP, callee's local size ; Allocate callee's Local
PUSH EBX ; Save preserved registers -
PUSH EDI ; will optimize to save
PUSH ESI ; only registers callee uses
Stack After Prolog 80387 Register Set After Prolog
· · .-----------------'
| caller's Local | ST(7) | Empty |
'--------------------' '-----------------'
| Upper Dword of p5 | ST(6) | Empty |
'- -- -- -- -- -- -- ' '-----------------'
| Lower Dword of p5 | ST(5) | Empty |
'--------------------' '-----------------'
| Blank Dword for p4 | ST(4) | Empty |
'--------------------' '-----------------'
| Four | ST(3) | p4 |
'- -- -- -- -- -- -- ' '-----------------'
| Blank | ST(2) | p3 |
'- -- -- -- -- -- -- ' '-----------------'
| Dwords | ST(1) | p2 |
'- -- -- -- -- -- -- ' '-----------------'
| for p3 | ST(0) | p1 |
'--------------------' '-----------------'
| 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 RETVAL ; Load return value onto floating-point stack
POP ESI ; Restore preserved registers
POP EDI
POP EBX
MOV ESP, EBP ; Deallocate callee's local
POP EBP ; Restore caller's EBP
RET ; Return to caller
Stack After Epilog 80387 Register Set After Epilog
· · .------------------.
| caller's Local | ST(7) | Empty |
'---------------------' '------------------'
| Upper Dword of p5 | ST(6) | Empty |
'- -- -- -- -- -- -- -' '------------------'
| Lower Dword of p5 | ST(5) | Empty |
'---------------------' '------------------'
| Blank Dword for p4 | ST(4) | Empty |
'---------------------' '------------------'
| Four | ST(3) | Empty |
'- -- -- -- -- -- -- -' '------------------'
| Blank | ST(2) | Empty |
'- -- -- -- -- -- -- -' '------------------'
| Dwords | ST(1) | Empty |
'- -- -- -- -- -- -- -' '------------------'
| for p3 | ST(0) | Return Value |
'---------------------' '------------------'
| Two Blank |
'- -- -- -- -- -- -- -'
| Dwords for p2 |
'---------------------'
| Blank Dword for p1 |
ESP ----> '---------------------'
caller's Code Just After Call:
ADD ESP, 40 ; Remove parameters from stack
FADD QWORD_PTR b ; Use return value
FSTP QWORD_PTR a ; Store expression to variable a
Stack After Cleanup 80387 Register Set After Cleanup
· · .--------------------.
| caller's Local | ST(7) | Empty |
| | '--------------------'
ESP ----> '-----------------' ST(6) | Empty |
'--------------------'
ST(5) | Empty |
'--------------------'
ST(4) | Empty |
'--------------------'
ST(3) | Empty |
'--------------------'
ST(2) | Empty |
'--------------------'
ST(1) | Empty |
'--------------------'
ST(0) | Return Value |
'--------------------'