Login With Github

3 Ways For Getting The Assembly Code Of Go Programs

There are several ways to get the assembly code of Go programs. Although their output formats may be somewhat different, they are all assembly code which is easy to read and can help us understand the underlying operation mode of the program better.

Let's take a look at the following piece of code, which is the implementation of sync.Once. Here I remove the unnecessary comments, and just copy a small piece.

type Once struct {
	m    sync.Mutex
	done uint32
}
func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 1 {
		return
	}
	o.m.Lock()
	defer o.m.Unlock()
	if o.done == 0 {
		defer atomic.StoreUint32(&o.done, 1)
		f()
	}
}

Method 1: go tool compile

Use go tool compile -N -l -S once.go to generate the assembly code.

"".(*Once).Do STEXT size=239 args=0x10 locals=0x28
	0x0000 00000 (once.go:13)	TEXT	"".(*Once).Do(SB), $40-16
	0x0000 00000 (once.go:13)	MOVQ	(TLS), CX
	0x0009 00009 (once.go:13)	CMPQ	SP, 16(CX)
	0x000d 00013 (once.go:13)	JLS	229
	0x0013 00019 (once.go:13)	SUBQ	$40, SP
	0x0017 00023 (once.go:13)	MOVQ	BP, 32(SP)
	0x001c 00028 (once.go:13)	LEAQ	32(SP), BP
	0x0021 00033 (once.go:13)	FUNCDATA	$0, gclocals·fdbf1f5761f6d17e8ae3f0aaecb6a3c5(SB)
	0x0021 00033 (once.go:13)	FUNCDATA	$1, gclocals·7d2d5fca80364273fb07d5820a76fef4(SB)
	0x0021 00033 (once.go:13)	FUNCDATA	$3, gclocals·96839595c383af6ae8227769d90a999e(SB)
	0x0021 00033 (once.go:14)	PCDATA	$2, $1
	0x0021 00033 (once.go:14)	PCDATA	$0, $0
	0x0021 00033 (once.go:14)	MOVQ	"".o+48(SP), AX
	0x0026 00038 (once.go:14)	MOVL	8(AX), CX
	0x0029 00041 (once.go:14)	CMPL	CX, $1
	0x002c 00044 (once.go:14)	JEQ	213
	0x0032 00050 (once.go:18)	PCDATA	$2, $0
	0x0032 00050 (once.go:18)	MOVQ	AX, (SP)
	0x0036 00054 (once.go:18)	CALL	sync.(*Mutex).Lock(SB)
	0x003b 00059 (once.go:19)	PCDATA	$2, $1
	0x003b 00059 (once.go:19)	MOVQ	"".o+48(SP), AX
    ……

Method 2: go tool objdump

Compile the program first:

go tool compile -N -l once.go

Use go tool objdump once.o to disassemble the code (or use go tool objdump -s Do once.o to disassemble a specific function):

TEXT %22%22.(*Once).Do(SB) gofile../Users/……/once.go
  once.go:13		0x7cd			65488b0c2500000000	MOVQ GS:0, CX			[5:9]R_TLS_LE
  once.go:13		0x7d6			483b6110		CMPQ 0x10(CX), SP
  once.go:13		0x7da			0f86d2000000		JBE 0x8b2
  once.go:13		0x7e0			4883ec28		SUBQ $0x28, SP
  once.go:13		0x7e4			48896c2420		MOVQ BP, 0x20(SP)
  once.go:13		0x7e9			488d6c2420		LEAQ 0x20(SP), BP
  once.go:14		0x7ee			488b442430		MOVQ 0x30(SP), AX
  once.go:14		0x7f3			8b4808			MOVL 0x8(AX), CX
  once.go:14		0x7f6			83f901			CMPL $0x1, CX
  once.go:14		0x7f9			0f84a3000000		JE 0x8a2
  once.go:18		0x7ff			48890424		MOVQ AX, 0(SP)
  once.go:18		0x803			e800000000		CALL 0x808			[1:5]R_CALL:sync.(*Mutex).Lock
  once.go:19		0x808			488b442430		MOVQ 0x30(SP), AX
  once.go:19		0x80d			4889442410		MOVQ AX, 0x10(SP)
  once.go:19		0x812			c7042408000000		MOVL $0x8, 0(SP)
  ……

Method 3: go build -gcflags -S

You can also use go build -gcflags -S once.go to get the assembly code:

"".(*Once).Do STEXT size=239 args=0x10 locals=0x28
	0x0000 00000 (/Users/……/once.go:13)	TEXT	"".(*Once).Do(SB), $40-16
	0x0000 00000 (/Users/……/once.go:13)	MOVQ	(TLS), CX
	0x0009 00009 (/Users/……/once.go:13)	CMPQ	SP, 16(CX)
	0x000d 00013 (/Users/……/once.go:13)	JLS	229
	0x0013 00019 (/Users/……/once.go:13)	SUBQ	$40, SP
	0x0017 00023 (/Users/……/once.go:13)	MOVQ	BP, 32(SP)
	0x001c 00028 (/Users/……/once.go:13)	LEAQ	32(SP), BP
	0x0021 00033 (/Users/……/once.go:13)	FUNCDATA	$0, gclocals·fdbf1f5761f6d17e8ae3f0aaecb6a3c5(SB)
	0x0021 00033 (/Users/……/once.go:13)	FUNCDATA	$1, gclocals·7d2d5fca80364273fb07d5820a76fef4(SB)
	0x0021 00033 (/Users/……/once.go:13)	FUNCDATA	$3, gclocals·96839595c383af6ae8227769d90a999e(SB)
	0x0021 00033 (/Users/……/once.go:14)	PCDATA	$2, $1
	0x0021 00033 (/Users/……/once.go:14)	PCDATA	$0, $0
	0x0021 00033 (/Users/……/once.go:14)	MOVQ	"".o+48(SP), AX
	0x0026 00038 (/Users/……/once.go:14)	MOVL	8(AX), CX
	0x0029 00041 (/Users/……/once.go:14)	CMPL	CX, $1
	0x002c 00044 (/Users/……/once.go:14)	JEQ	213

go tool compile and go build -gcflags -S are used to generate assembly code that is in the process, while go tool objdump is used to generate assembly code for the final machine code.

0 Comment

temp