Go Assembly 示例: Sqrt

这个例子摘自标准库 math package。 函数在不同的汇编文件中来实现,这是因为要使用不同架构下的硬件对开方根函数的支持。

package math
func Sqrt(x float64) float64

Go编译器会查找以 _GOOS_GOARCH_GOOS_GOARCH结尾的文件,以便选择合适的汇编文件来编译,具体可以查看 See go/build

∕∕ sqrt_386.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD   x+0(FP),F0
	FSQRT
	FMOVDP  F0,ret+8(FP)
	RET
∕∕ sqrt_amd64.s
#include "textflag.h"
TEXT ·Sqrt(SB), NOSPLIT, $0
	XORPS  X0, X0 // break dependency
	SQRTSD x+0(FP), X0
	MOVSD  X0, ret+8(FP)
	RET

amd64p32 是 native client (Nacl) amd64 指令集,使用32位地址空间, 32位的指针, 32位的int和uint。它是play.golang.org的沙箱架构。

∕∕ `sqrt_amd64p32.s`

因为 amd64 汇编文件可以使用,所以这里我们包含它。

#include "sqrt_amd64.s"
∕∕ sqrt_arm.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	MOVD   x+0(FP),F0
	SQRTD  F0,F0
	MOVD  F0,ret+8(FP)
	RET
∕∕ sqrt_arm64.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD	x+0(FP), F0
	FSQRTD	F0, F0
	FMOVD	F0, ret+8(FP)
	RET
∕∕ sqrt_mipsx.s

这个文件名并不包含 _GOOS.s 模式,相反它使用下面的注释告诉编译器mipsmipsle两种架构都可以使用这个汇编文件。

∕∕ +build mips mipsle
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	MOVD	x+0(FP), F0
	SQRTD	F0, F0
	MOVD	F0, ret+8(FP)
	RET
∕∕ sqrt_ppc64x.s
∕∕ +build ppc64 ppc64le
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD	x+0(FP), F0
	FSQRT	F0, F0
	FMOVD	F0, ret+8(FP)
	RET
∕∕ sqart_s389x.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD x+0(FP), F1
	FSQRT F1, F1
	FMOVD F1, ret+8(FP)
	RET

 下一个例子: goroutineid.