以下の例は、関数 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 の Blank 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 の Blank 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) 戻り値