为啥写
Go的汇编一直是我感兴趣的地方,为了验证之前所学的汇编知识和好玩 ,我决定往Go官方提交一个性能patch。 所以到官方的标准库里搜了一圈,发现adler32并没有硬件加速的实现,而Intel已经公布了相关的SSE加速实现 https://github.com/01org/isa-l/
所以我决定把Intel的抄过来,结果不停地掉坑和爬出来,终于提交了patch(撒花)
https://go-review.googlesource.com/c/51850
希望在Go 1.10发布的时候能进入官方源:)
坑
写法的区别Go汇编不支持难以调试内存越界与LEA向官方提交代码需要注意的地方,保证Change ID一致
坑一:Intel和AT&T的写法的区别
Intel写法是: opcode destination source
AT&T 也就是Go官方汇编语言的写法正好是反过来的: opcode destination source
抄代码的时候有点绕
坑二 Go汇编不支持:
Go的维护者们对于新添加汇编opcode一直是很保守的,比如2001年前后就有的SSE2 里的PSHLLW()竟然不支持(= =||)。 所以得自己填BYTE,比如官方文档中的MOVQ用BYTE方式编写https://golang.org/doc/asm
BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (AX), M0
但这里就有一个坑,比如PSHLLD和PSHRQ的Opcode是一样的……只是按/r 寄存器类型进行区别。需要注意
坑三:调试困难
一般代码测试时,都可以直接输出日志,帮助定位问题,但是汇编不行,所以我是通过把需要的值放入某个不用的寄存器, 例如
#define debug R15 // min(a, b int) int TEXT min(SB), NOSPLIT, $0
在需要的时候,提前把函数返回
MOVQ debug, ret+16(FP) RET
当然应该有更好的方法,可以把所有寄存器打印出来,不过这个方法够我自己调试用了。
坑四:内存越界与LEA
一般程序中都是指针,或者直接结构体。不过,汇编这里回归