1

次のコードがあります。

int func(int a)
{
  int b=2;
  int c,d,e,f,g;
  //some code which involves a,b,c,d,e,f,g
} 

int main()
{
 int s=3;
 func(s);
}

main が実行を開始すると、次のようになります。 1.
s をスタックにプッシュします 。
2. func() を呼び出し
ます。
a,b,c,d,e,fg が実行され、a の値を知るためには、func() のすべてのローカル変数をポップする必要があります。次に、a の値が取得されます。もう一度 bcdefg を使用する場合、それらの値はどのように取得されるのでしょうか (既にポップされているため)。

4

3 に答える 3

6

ローカル変数と引数は、実際にはスタックにプッシュされません。代わりに、コンパイラはすべての変数に適合するようにスタック ポインタを変更するコードを追加し、ローカル変数を参照するときに、スタック ポインタからのオフセットから値を取得するコードをコンパイラに追加します。

サンプル プログラムのアセンブラ出力を見て、その動作を理解することをお勧めします。

于 2012-09-27T06:24:12.600 に答える
1

void func(int a)の同等のコード

    void func(int a)
{
00413880  push        ebp  
00413881  mov         ebp,esp 
00413883  sub         esp,108h 
00413889  push        ebx  
0041388A  push        esi  
0041388B  push        edi  
0041388C  lea         edi,[ebp-108h] 
00413892  mov         ecx,42h 
00413897  mov         eax,0CCCCCCCCh 
0041389C  rep stos    dword ptr es:[edi] 
  int b=2;
0041389E  mov         dword ptr [b],2 
  int c,d,e,f,g;
  //some code which involves a,b,c,d,e,f,g
} 

次に、以下のコードと同等のアセンブリ コードを見てみましょう::

    void func(int a)
{
  int b=2;
  int c,d,e,f,g;
  c = 10 ;
  d = 15 ;
  e = 20 ;
  a = a + 2 ;
} 

アセンブリ コード::

    void func(int a)
{
00413880  push        ebp  
00413881  mov         ebp,esp 
00413883  sub         esp,108h 
00413889  push        ebx  
0041388A  push        esi  
0041388B  push        edi  
0041388C  lea         edi,[ebp-108h] 
00413892  mov         ecx,42h 
00413897  mov         eax,0CCCCCCCCh 
0041389C  rep stos    dword ptr es:[edi] 
  int b=2;
0041389E  mov         dword ptr [b],2 
  int c,d,e,f,g;
  c = 10 ;
004138A5  mov         dword ptr [c],0Ah 
  d = 15 ;
004138AC  mov         dword ptr [d],0Fh 
  e = 20 ;
004138B3  mov         dword ptr [e],14h 
  a = a + 2 ;
004138BA  mov         eax,dword ptr [a] 
004138BD  add         eax,2 
004138C0  mov         dword ptr [a],eax 
} 

したがって、それらはスタック (ESP または SP) にプッシュされますが、各ローカル変数へのポインターも格納されるため、必要なときに簡単にアクセスできます。

同様に、コードが変数 aを使用する必要がある場合、dword ptr [a]は単純にレジスタEAXに移動されます。

注: 技術的にはプッシュされていませんが、すべての変数に適合するように調整されています。(提供:ヨアヒム・ピレボルグ)

于 2012-09-27T06:36:26.853 に答える
0

func() のすべてのローカル変数の値を知るには、ポップする必要があります。この行は文法的にあいまいですが。関数で使用されているときに変数がポップされると言うつもりだと思います..

しかし、実際のケースでは、関数が呼び出し元に戻ったときにのみローカル変数がポップアウトされます。それらが自動である場合。一方、関数が変数にアクセス(読み取り/書き込み)したい場合。ベースからのオフセット(距離)を使用してアクセスするため、評価のためにアクセス中に変数がポップアウトされるという問題はありません。

于 2012-09-27T06:40:21.103 に答える