Skip to content

Go ABIにおけるレジスタの意味

以下の資料に準拠。

スタックポインタ。疑似レジスタ SP 相当。

最も下位のアドレスを記録してあり、関数呼び出しがあるたびに減算されていく。

ベースポインタ。現在のスタックフレーム底アドレスを保持する。SP よりローカル変数領域を含まない。

BP レジスタが参照するメモリアドレスの値はリンクリストになっているので、

MOVQ (BP), BP

とすると関数呼び出し前の BP 値を取得できる。同じようにすればさらに上位の呼び出し元にも戻れる。具体的な探索例はGoアセンブリ上のスタック探索にある。

クロージャコンテキストポインタを保持するレジスタ。コンテキストの具体的な内容はGoのコンテキストレジスタに書いた。

インストラクションポインタ。次に実行する命令のメモリ位置を記録する。疑似レジスタ PC 相当。

スレッドローカルストレージを指す疑似レジスタ。TLS レジスタは、現在のスレッドで実行している runtime.g 構造体を参照する。ドキュメントでは Thread pointer と表記されているが、これはRISC-Vだけ?

ところで runtime パッケージには

#define get_tls(r) MOVL TLS, r
#define g(r) 0(r)(TLS*1)

のようなマクロが定義されているけど、これはランタイムは自身以外のゴルーチンも扱うため必要なだけで、自身のゴルーチンだけを扱う場合は直接 TLS を操作すればいいものではないか。

常にカレントゴルーチンの g 構造体を参照している。ただし、このレジスタは386には存在しないので、32bit環境では次のように TLS から runtime.g を取得する。

MOVL (TLS), AX // AXがg構造体の場所を指す
MOVL 4(AX), BX // g.stack.hi -> BX

Arm64呼び出し規約にも少し書いた。