Go的源码是Plan9汇编与Go语言的混和使用,即有汇编调用Go,也有Go调用汇编。在好多情况下,直接看汇编代码更直观,非常是在研究编译器生成的函数实现时更有用。下边介绍两种反汇编方式:
假定有个helloworld.go程序,源码如下:
#1:3:b:2:e:5:8:5:6:6:9:f:a:7:0:5:7:6:3:7:c:1:1:5:5:c:8:4:3:1:2:4#
先将代码编译成二补码,命令如下:
#e:7:3:c:8:e:6:a:1:9:5:9:b:a:e:a:f:e:d:0:f:b:c:7:d:1:1:f:e:9:1:9#
会生成一个helloworld的二补码,--gcflags="-l-N"参数的作用是去除编译器优化,使生成的汇编代码与编撰的代码更相仿,同时也便捷GDB调试。
反汇编成AT&T汇编
AT&T是Linux操作系统最常用的汇编语言,Linux系统提供的objdump工具也是将二补码反编译成AT&T汇编,命令如下:
#9:1:3:a:9:1:2:d:4:6:a:4:a:7:4:2:b:0:c:7:9:1:8:2:0:f:7:e:8:8:a:4#
最终反汇编的结果放到了att.asm文件。下边是汇编结果(截取了部份代码):
#0:f:f:4:9:4:b:5:b:7:f:4:6:f:a:5:f:f:f:0:9:4:4:4:f:b:6:0:f:a:f:9#
反汇编成Plan9汇编
Plan9目前见到的只有Go语言在用,但是网上的资料很短缺,学习成本挺高的,但若果学会了Plan9汇编,再看Go源码会特别简单,但是可以通过Go调用汇编写出高效率代码。要把二补码反汇编成Plan9汇编,也只能用Go提供的工具,命令如下:
#8:8:c:1:8:9:f:3:c:6:9:a:6:1:0:b:8:e:c:4:a:e:e:9:b:8:d:9:d:2:e:7#
最终反汇编的结果放到了plan9.asm文件。下边是汇编结果(截取了部份代码):
#4:1:7:6:e:f:0:4:9:a:5:c:1:d:9:3:5:2:5:a:1:5:1:7:2:d:8:f:b:3:f:e#
建议
从里面展示的结果来看,两种汇编还是有点差异的。在学习Go源码时,选择用哪种汇编去看这个要按照自已的实际情况来。我的建议先必须对AT&T汇编有一定了解,由于Plan9汇编资料实在是太少了,甚至没有一个对命令的完整介绍,一个没有汇编基础的人直接看Plan9的一些文档,绝对会一脸绝望。在整理网上一些Plan9汇编资料时,发觉都是讲的Plan9与AT&T的差别,所以只有了解AT&T,能够进一步学好Plan9汇编。