以下の例は、わかりやすく例示するためにのみ記載されたものであり、最適化されていません。これらの例では、ユーザーがアセンブラーのプログラミングに習熟している ことが前提になっています。各例では、スタックはページの下方へ伸びていきます。また、ESP は常に、スタックの上部を指します。
以下の例は、関数 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) | 戻り値 |
*--------------------*