4. 関数呼び出しとスタック
4.1 なぜ戻り先を保存するのか
mainの途中でread_nameへ移ったCPUは、read_nameの後にmainのどこへ戻ればよいかを覚えておく必要がある。read_nameがgreetを呼ぶと、その戻り先も必要になる。
main の続きの位置
└─ read_name の実行中に保存
greet 呼び出し後は、その戻り先も追加で保存
後から呼ばれたgreetが先に戻り、次にread_nameが戻る。「後から入れたものを先に出す」スタックは、この入れ子構造と相性がよい。
4.2 RSP、call、ret
x86-64でRSPは現在のスタック先頭を指す。ここで「先頭」は最後に積んだ値の位置であり、図の上端とは限らない。
call target:
RSP = RSP - 8
[RSP] = callの次の命令アドレス
RIP = target
ret:
RIP = [RSP]
RSP = RSP + 8
[RSP]は「RSPが指すメモリの内容」を意味する。callは戻り先をスタックへ書き、retはそれを命令位置として読み戻す。

図: スタック全体は残したまま、
RSPより外側になった部分だけを薄く示す。
4.3 スタックフレームとRBP
このビルドでは、関数の入口で呼び出し元のRBPを保存し、新しいRBPを基準に局所領域を参照する。
高アドレス
┌──────────────────────┐
│ mainへの戻り先 │ [RBP+8]
├──────────────────────┤
│ 保存されたRBP │ [RBP]
├──────────────────────┤ ← RBP
│ name[8..15] │
├──────────────────────┤
│ name[0..7] │ ← RBP-16
└──────────────────────┘ ← RSP
低アドレス
局所配列nameと戻り先は論理的に関係ないデータだが、この実行ファイルでは同じスタック上に連続して置かれる。この物理的な近さが後で効く。