前書き
アセンブラを読んでいて気になることがあった
118e: 89 e5 mov ebp,esp
1190: 83 ec 10 sub esp,0x10 //ここ!
119d: c7 45 f4 01 00 00 00 mov DWORD PTR [ebp-0xc],0x1
11a4: c7 45 f8 03 00 00 00 mov DWORD PTR [ebp-0x8],0x3
こんな風にスタックポインタを使う分だけsub
してスタックフレームを広げる関数と、
1151: f3 0f 1e fa endbr64
1155: 55 push rbp
1156: 48 89 e5 mov rbp,rsp //この後引いてない!
1159: c7 45 fc 02 00 00 00 mov DWORD PTR [rbp-0x4],0x2
そうでない関数がいる。
これらの違いはどこからきているのかずっと気になっていた。
レッドゾーン
関数呼び出し規約にred zoneというものがある。
これはスタックポインタの上128バイトは予約されていて、割り込みによって書き換えることが禁止されているというものである。
割り込みによって書き換えられないことが保障されているならば、他の関数を呼ばない関数(そういう関数をleaf functionと呼ぶ)はその領域を事実上自由に使えるということになる。これによってバイナリを最適化することができるというわけだ。
事実、先ほどのアセンブラはそれぞれ 以下のコードをコンパイルして作成した
void test() {
printf("test");
return;
}
int main() {
int a = 1;
int b = 3;
test();
return 0;
}
int main() {
int a = 2;
return 0;
}
半年にわたる漠然とした疑問が晴れてすっきりである
参考文献
- wilipedia
-
ゼロからの OS 自作入門
- この本の3章でレッドゾーンの存在を知った