コンテンツにスキップ

Go/Goのプログラムがどんなアセンブリにコンパイルされるか?

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Go

Goのプログラムがどんなアセンブリにコンパイルされるか?

[編集]

Goは簡素化された構文とキャッシュの使用により、非常に高速にコンパイルされますが、(中間コードではなく)ネイティブな機械語を生成します。

では、実際にどのようなコードが生成されるかを検証してみましょう。

Hello, World を逆アセンブル

[編集]
hello.go
package main

import "fmt"

func main() {
	fmt.Println("Hello, World")
}

上のような単純で完全なプログラム hello.go を用意します。

% % go build hello.go
helloにコンパイル結果が出力されます。
go tool objdump という Go の逆アセンブラーは、実効形式を理解できます(-S はソースも併せて表示するオプションです)。
% go tool objdump -S -s main.main hello > hello.objdump
hello.objdump
TEXT main.main(SB) /home/eguchi/tut/go/hello.go
func main() {
  0x48fd80              493b6610                CMPQ SP, 0x10(R14)
  0x48fd84              7646                    JBE 0x48fdcc
  0x48fd86              55                      PUSHQ BP
  0x48fd87              4889e5                  MOVQ SP, BP
  0x48fd8a              4883ec38                SUBQ $0x38, SP
    fmt.Println("Hello, World")
  0x48fd8e              488d156b970000          LEAQ 0x976b(IP), DX
  0x48fd95              4889542428              MOVQ DX, 0x28(SP)
  0x48fd9a              488d15076d0400          LEAQ 0x46d07(IP), DX
  0x48fda1              4889542430              MOVQ DX, 0x30(SP)
        return Fprintln(os.Stdout, a...)
  0x48fda6              488b1dbb9b0c00          MOVQ os.Stdout(SB), BX
  0x48fdad              488d05f4720400          LEAQ go:itab.*os.File,io.Writer(SB), AX
  0x48fdb4              488d4c2428              LEAQ 0x28(SP), CX
  0x48fdb9              bf01000000              MOVL $0x1, DI
  0x48fdbe              4889fe                  MOVQ DI, SI
  0x48fdc1              e8baafffff              CALL fmt.Fprintln(SB)
}
  0x48fdc6              4883c438                ADDQ $0x38, SP
  0x48fdca              5d                      POPQ BP
  0x48fdcb              c3                      RET
func main() {
  0x48fdcc              e80faafdff              CALL runtime.morestack_noctxt.abi0(SB)
  0x48fdd1              ebad                    JMP main.main(SB)
ターゲットは AMD64 なのですが、あまり見慣れないニーモニックだと思います。
これは、Plan9 のアセンブラフォーマットでIntelともAT&Tとも違います。
レジスタは8086の頃にあったものならば8086当時の名前で、AMD64で追加されたレジスタはRnnの形式で表示されます。
演算や転送の幅は SUBQ や MOVL のようにオペレーションの末尾の文字で指定されます。

Goはコンパイラーですが、コンパイラー自体がGoで書かれ、ソースコードとともに配布されており、他にも

go tool nm

go tool pack

の様なハウスキーピング用のコマンドがあります(機会を見て紹介します)。

脚註

[編集]


参考文献

[編集]