1

次のコードがあります

int isBST(struct node* node) 
{ 
  return(isBSTUtil(node, INT_MIN, INT_MAX)); 
} 

int isBSTUtil(struct node* node, int min, int max) 
{
  if (node==NULL) 
     return 1;      

  if (node->data <= min || node->data > max) 
     return 0; 

  return
    isBSTUtil(node->left, min, node->data) &&  // Allow only distinct values
    isBSTUtil(node->right, node->data, max);  // Allow only distinct values
}

GDB でコードをデバッグすると、2 番目のパラメーターがアドレス ebp + 0xc (0xbffff188 + 0xc) によって設定され、3 番目のパラメーターが ebp + 0x10 に設定され、最初のパラメーターがどこにあるのかがわかりません。関数の戻りアドレスが EBP + 4 にあり、最初のパラメーターが EBP +8 にあることを知っています....私が持っているものから?

4

1 に答える 1

0

理論的には、引数や戻りアドレスがどこにあるかはわかりません。特定のアーキテクチャでは、(通常) 生成されたアセンブラの一部を調べることで、特定のコンパイラが何をするかを理解できます。最初に調べるは関数 preable です。 Intel 32 ビット プロセッサでは、フレーム ポインタは EBP になり、レジスタを保存するために一定回数プッシュしたに設定されます。push EBP(特に、 EBP がローカル フレーム用に設定される前にが存在する必要があります。) Intel の典型的なプレアブルは次のようになります。

function:
        PUSH EBP
        MOV  EBP, ESP
        SUB  ESP, n         ;   allocate space for local variables

それを超えて:Intelスタックは成長し、Intelのコンパイラはほぼ普遍的に引数を右から左にプッシュするため、あなたの場合、max最高のアドレスがあり、その minすぐ下、そしてnodeその下になります。したがって、フレームの画像は次のようになります。

[EBP - ...]     local variables
[EBP + 0]       the pushed old EBP
[EBP + 4]       the return address
[EBP + 8]       the first argument (node)
[EBP + 12]      the second argument (min)
[EBP + 16]      the third argument (max)

(これは、引数がすべて 32 ビット値であることを前提としています。) もちろん、コンパイラは EBP をプッシュする前に追加のレジスタをプッシュする可能性があり、それに応じてオフセットが高くなります。これは可能なレイアウトの 1 つにすぎません。

于 2013-11-15T14:35:37.163 に答える