スタックの構造を理解するための小さなプログラムを書きました。
#include <stdio.h>
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
int *ret = buffer1 + 13;
(*ret) += 8;
}
int main() {
int x = 0;
function(1,2,3);
x = 1;
printf("x = %d\n",x);
return 0;
}
今まで、スタックが以下のパターンに従うことを学びました
------------------
| arguments | High
------------------
| return address |
------------------
| ebp |
------------------
| buffer1 |
------------------
| buffer2 | Low
------------------
また、5 バイトのデータを割り当てると、プログラムは 8 バイトを割り当てることも学びました (これは、ワード サイズの倍数でなければならないためです)。
function のアセンブラ コードのダンプfunction
:
0x08048414 <+0>: push %ebp
0x08048415 <+1>: mov %esp,%ebp
0x08048417 <+3>: sub $0x20,%esp
0x0804841a <+6>: lea -0x9(%ebp),%eax
0x0804841d <+9>: add $0xd,%eax
0x08048420 <+12>: mov %eax,-0x4(%ebp)
0x08048423 <+15>: mov -0x4(%ebp),%eax
0x08048426 <+18>: mov (%eax),%eax
0x08048428 <+20>: lea 0x8(%eax),%edx
0x0804842b <+23>: mov -0x4(%ebp),%eax
0x0804842e <+26>: mov %edx,(%eax)
0x08048430 <+28>: leave
0x08048431 <+29>: ret
アセンブラー・ダンプの終わり。
gdb の下でプログラムを実行すると、次のようになります。
(gdb) x/x $ebp
0xbffff318: 0xbffff348
(gdb) x/x buffer1
0xbffff30f: 0xfc73e461
(gdb) x/x buffer2
0xbffff305: 0x0108049f
すべてがワードサイズの倍数で割り当てられている場合、buffer1
との違いはどのようにbuffer2
なるのでしょうか。10
9
また、 %ebp との間にはどのような違いがありbuffer1
ますか?
ここで正確に何が起こっているのですか?
注:
- スタックが High から Low に成長することを考慮してください
- ワードサイズ = 4
Intel プロセッサ、Ubuntu 12.04、32 ビットを使用しています。
gcc -o stack -g -fno-stack-protector -O0 main.c
構築する。