Skip to content

Go ABIにおけるスタックのレイアウト

複数あるABIの違いはGoにおけるABI仕様も参照。

[! Todo] Mermaidにはpacket diagramがあるけどObsidian同梱のバージョンには入ってない。更新されたら図を書き直したい。

関数呼び出しを行ったとき、上位から下位に向かって以下のようなフレームレイアウトになる。混乱するが BPFP は同じものらしいので、Go ABIにおけるレジスタの意味も参照するといい。

内容(上位→下位)サイズ補足
BPレジスタの値8関数呼び出し前のBPレジスタを退避している
戻り値可変
関数引数可変FPレジスタはこの場所を指す
リターンアドレス8SPレジスタはこの場所を指す
ローカル変数可変

ドキュメントは見つからなかったが、過去にGoアセンブリの書き方で調べたことがある。

スタックフレームのレイアウトはアーキテクチャごとに異なる。

おそらく 386amd64 どちらも同じ。このレイアウトはAMD64の呼び出し規約と同じらしい。Goのエラーハンドリングを集約するライブラリを作った + Goが管理するスタック周りの挙動についての記事でスタック図を描いた。

内容(上位→下位)サイズ補足
リターンアドレス8
BPレジスタの値8関数呼び出し前のBPレジスタを退避している
関数引数可変レジスタに入らなかった残り
戻り値可変
ローカル変数可変SPレジスタはこの場所を指す

FP レジスタの定義としては

The FP pseudo-register is a virtual frame pointer used to refer to function arguments.

なので、たぶん関数引数の下位アドレスを指すが、ABIInternal を自分で書くことはないので詳細は調べていない。

Arm64呼び出し規約に少し書いたが、BP レジスタや SP レジスタの意味は amd64 と同じだった。

スタックの使い方を調べる。

Terminal window
go build -gcflags='-S -N -l' .
go tool compile -S -N [file]

-S でアセンブリを出力、-N で最適化を抑制、-I でインライン化を抑制している。-gcflags という名前から分かるように、オプションの詳細は go tool compile -h で調べられる。