今天在翻阅Golang代码时,发现了Golang调用汇编代码的方法(详见pkg/bytes)。大概要做三件事,我以用汇编实现一个判断字符串是否相等的方法Equal为例,测试一下:
准备工作,创建工程目录:
asm_demo
|--bin
|--pkg
|--src
| |--strlib
| |--demo
第一、编写平台对应的编码代码。
汇给代码文件以如下格式的命名:asm_$ARCH.s (asm_386.s, asm_amd64.s, asm_arm.s, ...),我的环境是Ubuntu 12.04 LTS amd64架构.
$ GOPATH=<youpath>/asm_demo
$ cd $GOPATH
$ cat <<EOF > src/strlib/asm_amd64.s
TEXT .Equal(SB),7,$0
MOVL len+8(FP), BX
MOVL len1+24(FP), CX
MOVL $0, AX
CMPL BX, CX
JNE eqret
MOVQ p+0(FP), SI
MOVQ q+16(FP), DI
CLD
REP; CMPSB
MOVL $1, DX
CMOVLEQ DX, AX
eqret:
MOVB AX, ret+32(FP)
RET
EOF
本段代码来自 $GOROOT/src/pkg/bytes/asm_amd64.s
可以看出,其中的语法大致和Linux汇编一致,只是寄存器表示不相同,是来自plan9的语法吗?哪个同鞋可以科普一下?
第二件事,就是让用Go语言封装一下这个API,让编译器可以识别:
$ cat <<EOF > src/strlib/equal.go
package strlib
func Equal(a[]byte, b[]byte) bool
EOF
最后一件事,使用之:
$ cat <<EOF > src/demo/main.go
package main
import "strlib"
func main() {
e := strlib.Equal([]byte("hello"), []byte("hello"))
println(e)
e := strlib.Equal([]byte("hessssllo"), []byte("hello"))
println(e)
}
EOF
执行看看效果:
$ go run src/demo/main.go
true
false
调用成功,使用起来非常简单,也很易读。
结果是出来了,其中还有好多疑问。