Golang二进制反汇编问题
作者:风神韵
这篇文章主要介绍了Golang二进制反汇编问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
Golang二进制反汇编
Go的源码是Plan 9汇编与Go语言的混合使用,即有汇编调用Go,也有Go调用汇编。
在很多情况下,直接看汇编代码更直观,特别是在研究编译器生成的函数实现时更有用。
下面介绍两种反汇编方法:
假设有个helloworld.go程序,源码如下:
package main import "fmt" func main() { fmt.Println("Hello, World!") }
先将代码编译成二进制,命令如下:
go build --gcflags="-l -N" -o helloworld
会生成一个helloworld的二进制,--gcflags="-l -N"
参数的作用是去掉编译器优化,使生成的汇编代码与编写的代码更相近,同时也方便GDB调试。
反汇编成AT&T汇编
AT&T是Linux操作系统最常用的汇编语言,Linux系统提供的objdump工具也是将二进制反编译成AT&T汇编,命令如下:
objdump -d helloworld > att.asm
最终反汇编的结果放在了att.asm文件。
下面是汇编结果(截取了部分代码):
0000000000487200 <main.main>: 487200: 64 48 8b 0c 25 f8 ff mov %fs:0xfffffffffffffff8,%rcx 487207: ff ff 487209: 48 3b 61 10 cmp 0x10(%rcx),%rsp 48720d: 76 7a jbe 487289 <main.main+0x89> 48720f: 48 83 ec 68 sub $0x68,%rsp 487213: 48 89 6c 24 60 mov %rbp,0x60(%rsp) 487218: 48 8d 6c 24 60 lea 0x60(%rsp),%rbp 48721d: 0f 57 c0 xorps %xmm0,%xmm0 487220: 0f 11 44 24 38 movups %xmm0,0x38(%rsp) 487225: 48 8d 44 24 38 lea 0x38(%rsp),%rax ...
反汇编成Plan 9汇编
Plan 9目前看到的只有Go语言在用,而且网上的资料很匮乏,学习成本挺高的,但如果学会了Plan 9汇编,再看Go源码会非常简单,而且可以通过Go调用汇编写出高效率代码。
要把二进制反汇编成Plan 9汇编,也只能用Go提供的工具,命令如下:
go tool objdump -S helloworld > plan9.asm
最终反汇编的结果放在了plan9.asm文件。
下面是汇编结果(截取了部分代码):
TEXT main.main(SB) /root/program/golang/helloworld/helloworld.go func main() { 0x487200 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX 0x487209 483b6110 CMPQ 0x10(CX), SP 0x48720d 767a JBE 0x487289 0x48720f 4883ec68 SUBQ $0x68, SP 0x487213 48896c2460 MOVQ BP, 0x60(SP) 0x487218 488d6c2460 LEAQ 0x60(SP), BP fmt.Println("Hello, World!") 0x48721d 0f57c0 XORPS X0, X0 0x487220 0f11442438 MOVUPS X0, 0x38(SP) 0x487225 488d442438 LEAQ 0x38(SP), AX 0x48722a 4889442430 MOVQ AX, 0x30(SP)
建议
从上面展示的结果来看,两种汇编还是有点差别的。
在学习Go源码时,选择用哪种汇编去看这个要根据自已的实际情况来。
我的建议先必须对AT&T汇编有一定了解,因为Plan 9汇编资料实在是太少了,甚至没有一个对命令的完整介绍,一个没有汇编基础的人直接看Plan 9的一些文档,绝对会一脸绝望。
在整理网上一些Plan 9汇编资料时,发现都是讲的Plan 9与AT&T的差异,所以只有了解AT&T,才能进一步学好Plan 9汇编。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。