2

EBP とリターン アドレスの場所がわかりません。私の理解では、sub の呼び出しは、関数内のローカル変数用のスペースを確保するために行われます。特にこのコードについては少し混乱しています..

void countLines(FILE* f){
char buf[0x400];//should be big enough for anybody
int lines=0;
fread(buf,READSIZE,1,f);  

for(int i=0;i<0x400;i++)
  if(buf[i] == '\n')
    lines++;


printf("The number of lines in the file is %d\n",lines);
return;
}

この関数を gdb で逆アセンブルすると、次のようになります。

0x08048484 <+0>:    push   %ebp
0x08048485 <+1>:    mov    %esp,%ebp
0x08048487 <+3>:    sub    $0x428,%esp

なぜ 0x428 なのですか? ローカル変数の長さを合計すると、0x408 (char[400]、行、および i) のみが得られます。さらに、予約済みスペースの直後に EBP と戻りアドレスが見つかりましたか?

4

2 に答える 2

3

関数のプロローグが実行されると、スタックは次のようになります。

*****
*****
return address
old EBP   <---- EBP
.....
..F..
..r..
..e..          (0x428 bytes)
..e..
.....      <---  ESP

関数から戻るには、単に ESP を EBP に保持されている値に復元し、スタックから前の EBP をポップして戻して、 を呼び出しますret。これにより、スタックから戻りアドレスがポップされ、そこにジャンプします。

mov %ebp, %esp
pop %ebp
ret

(EBP を維持するポイントは、関数中に ESP をどれだけインクリメントしたかを覚えておく必要がないようにすることです ( と考えてください。ただし、GCC の などでは EBP を使用するalloca必要はありません-fomit-frame-pointer )

于 2013-07-21T19:43:42.613 に答える
1

関数の引数 (およびおそらくレジスター) も、その 0x428 バイト空間に保存されます。pushまた、他の関数を呼び出す場合、 /を使用する代わりにpop、GCC は単純にesp(たとえばmov 0x4(%esp),%eax) に対する引数を格納します。

したがって、0x428 は 0x408 (ローカル変数) + 0x4 (引数) + 0x10 (最大 4 つの引数用のスペースfread) + 0x8 (おそらく私が見逃している何か、おそらくレジスター) に由来します。

于 2013-07-21T20:43:29.667 に答える