【转载】得到Go程序的汇编代码的方法

转自:https://colobu.com/2018/12/29/get-assembly-output-for-go-programs/

本文仅供个人备份学习,请访问原网址↑。

 

有多种方式可以获得Go程序的汇编代码, 尽管输出的格式有些不同,但是都是方便阅读的汇编代码,可以帮助我们更好的了解程序的底层运行方式。

我们看下面一段代码, 它是sync.Once的实现,去掉了不必要的注释,复制出来用来研究的一段小代码。

once.go

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

 

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()

}

}

方法一: go tool compile

使用go tool compile -N -l -S once.go生成汇编代码:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

 

"".(*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

……

方法二: go tool objdump

首先先编译程序: go tool compile -N -l once.go,

使用go tool objdump once.o反汇编出代码 (或者使用go tool objdump -s Do once.o反汇编特定的函数:):

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

 

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)

……

方法三: go build -gcflags -S

使用go build -gcflags -S once.go也可以得到汇编代码:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

 

"".(*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 和 go build -gcflags -S 生成的是过程中的汇编,和最终的机器码的汇编可以通过go tool objdump生成。

参考文档

  1. https://www.reddit.com/r/golang/comments/6a5557/how_to_get_assembly_output_from_a_small_go_program/
  2. https://stackoverflow.com/questions/43858356/how-to-get-assembly-output-for-a-short-go-program
  3. https://rakyll.org/codegen/
  4. https://stackoverflow.com/questions/22769246/how-to-disassemble-one-single-function-using-objdump
  5. https://golang.org/cmd/objdump/
  6. https://golang.org/cmd/compile/
  7. https://golang.org/cmd/go/#hdr-Compile_packages_and_dependencies

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值