以下の例は、関数 FUNC1 に対する呼び出しのときの、コード・シーケンスおよびスタックの図を示しています。このプログラムは、PREFIX(NOFIXEDOVERFLOW) オプションでコンパイルされることが前提になっています。
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
呼び出し直後のスタック 呼び出し直後のレジスター設定
| | .----------.----.----.
| 呼び出し側の Local | EAX | 未定義 | p1 |
|-------------------------| |----------.----.----|
| p4 | EBX | 呼び出し側の EBX |
|-------------------------| |----------.----.----|
| p3 のブランク・スロット | ECX | p3 | |
|-------------------------| |----------.----.----|
| p2 のブランク・スロット | EDX | 未定義 | p2 |
|-------------------------| |----------.----.----|
| p1 のブランク・スロット | EDI | 呼び出し側の EDI |
|-------------------------| |----------.---------|
| 呼び出し側の EIP | ESI | 呼び出し側の 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
Prolog 後のスタック Prolog 後のレジスター設定
| | .----------.----.----.
| 呼び出し側の Local | EAX | 未定義 | p1 |
|------------------------| |----------.----.----|
| p4 | EBX | 未定義 |
|------------------------| |----------.----.----|
| p3 のブランク・スロット | ECX | p3 |
|------------------------| |----------.----.----|
| p2 のブランク・スロット | EDX |未定義 | p2 |
|------------------------| |----------.----.----|
| p1 のブランク・スロット | EDI | 未定義 |
|------------------------| |----------.---------|
| 呼び出し側の EIP | ESI | 未定義 |
|------------------------| .----------.---------.
| 呼び出し側の EBP |
|------------------------| レジスター EBX、EDI、および
| | ESI における「未定義」と
. . いう用語は、FUNC1 のコード
. 呼び出し側の Local . で安全に上書きできることを
. . 意味します。
|------------------------|
| 保管 EBX |
|------------------------|
| 保管 EDI |
|------------------------|
| 保管 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
Epilog 後のスタック Epilog 後のレジスター設定
| | .---------.----.---.
| 呼び出し側の Local | EAX | 戻り値 |
|-------------------------| |---------.----.---|
| p4 | EBX | 呼び出し側の EBX |
|-------------------------| |---------.----.---|
| p3 のブランク・スロット | ECX | 未定義 |
|-------------------------| |---------.----.---|
| p2 のブランク・スロット | EDX | 未定義 |
|-------------------------| |---------.----.---|
| p1 のブランク・スロット | EDI | 呼び出し側の EDI |
| | |---------.--------|
ESP ---> .-------------------------. ESI | 呼び出し側の ESI |
.---------.--------.
caller's Code Just After Call:
ADD ESP, 16 ; Remove parameters from stack
MOV y, EAX ; Use return value.
クリーンアップ後のスタック クリーンアップ後のレジスター設定
| | .---------.----.---.
| 呼び出し側の Local | EAX | 戻り値 |
ESP ---> .--------------------. |---------.----.---|
EBX | 呼び出し側の EBX |
|---------.----.---|
ECX | 未定義 |
|---------.----.---|
EDX | 未定義 |
|---------.----.---|
EDI | 呼び出し側の EDI |
|---------.--------|
ESI | 呼び出し側の ESI |
.---------.--------.
以下の例は、ルーチン FUNC2 に対する呼び出しのときの、コード・シーケンス、80386 のスタック・レイアウト、および浮動小数点レジスター・スタック の状態を示しています。単純にするために、汎用レジスターは示しません。このプログラムは、IMPRECISE オプションでコンパイルされることが前提になっています。
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
呼び出し直後のスタック 呼び出し直後の 80387 レジスター設定
. . .-------------------.
| 呼び出し側の Local | ST(7) | 空 |
|----------------------| |-------------------|
| p5 の Upper Dword | ST(6) | 空 |
|- -- -- -- -- -- -- --| |-------------------|
| p5 の Lower Dword | ST(5) | 空 |
|----------------------| |-------------------|
| p4 の Blank Dword | ST(4) | 空 |
|----------------------| |-------------------|
| Four | ST(3) | p4 (e) |
|- -- -- -- -- -- -- --| |-------------------|
| ブランク | ST(2) | p3 (a + c) |
|- -- -- -- -- -- -- --| |-------------------|
| Dwords | ST(1) | p2 (d) |
|- -- -- -- -- -- -- --| |-------------------|
| for p3 | ST(0) | p1 (a) |
|----------------------| .-------------------.
| 2 つのブランク |
|- -- -- -- -- -- -- --|
| p2 の Dwords |
|----------------------|
| p1 のブランク Dword |
|----------------------|
| 呼び出し側の 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
Prolog 後のスタック Prolog 後の 80387 レジスター設定
| | .-----------------|
| 呼び出し側の Local | ST(7) | 空 |
|----------------------| |-----------------|
| p5 の Upper Dword | ST(6) | 空 |
|- -- -- -- -- -- -- --| |-----------------|
| p5 の Lower Dword | ST(5) | 空 |
|----------------------| |-----------------|
| p4 の Blank Dword | ST(4) | 空 |
|----------------------| |-----------------|
| Four | ST(3) | p4 |
|- -- -- -- -- -- -- --| |-----------------|
| ブランク | ST(2) | p3 |
|- -- -- -- -- -- -- --| |-----------------|
| Dwords | ST(1) | p2 |
|- -- -- -- -- -- -- --| |-----------------|
| for p3 | ST(0) | p1 |
|----------------------| .-----------------.
| 2 つのブランク |
|- -- -- -- -- -- -- --|
| p2 の Dwords |
|----------------------|
| p1 の Blank Dword |
|----------------------|
| 呼び出し側の EIP |
|----------------------|
| 呼び出し側の EBP |
|----------------------|
| |
. .
. 呼び出し先の Local .
. .
| |
|----------------------|
| 保管 EBX |
|----------------------|
| 保管 EDI |
|----------------------|
| 保管 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
Epilog 後のスタック Epilog 後の 80387 レジスター設定
| | .------------------.
| 呼び出し側の Local | ST(7) | 空 |
|----------------------| |------------------|
| p5 の Upper Dword | ST(6) | 空 |
|- -- -- -- -- -- -- --| |------------------|
| p5 の Lower Dword | ST(5) | 空 |
|----------------------| |------------------|
| p4 の Blank Dword | ST(4) | 空 |
|----------------------| |------------------|
| Four | ST(3) | 空 |
|- -- -- -- -- -- -- --| |------------------|
| ブランク | ST(2) | 空 |
|- -- -- -- -- -- -- --| |------------------|
| Dwords | ST(1) | 空 |
|- -- -- -- -- -- -- --| |------------------|
| for p3 | ST(0) | 戻り値 |
|----------------------| .------------------.
| 2 つのブランク |
|- -- -- -- -- -- -- --|
| p2 の Dwords |
|----------------------|
| p1 のブランク Dword |
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
クリーンアップ後のスタック クリーンアップ後の 80387 レジスター設定
| | .--------------------.
| 呼び出し側の Local | ST(7) | 空 |
| | |--------------------|
ESP ----> .---------------------. ST(6) | 空 |
|--------------------|
ST(5) | 空 |
|--------------------|
ST(4) | 空 |
|--------------------|
ST(3) | 空 |
|--------------------|
ST(2) | 空 |
|--------------------|
ST(1) | 空 |
|--------------------|
ST(0) | 戻り値 |
.--------------------.