设为首页 收藏本站
查看: 868|回复: 0

[经验分享] /src/pkg/math/abs.go源码阅读兼谈golang与汇编

[复制链接]

尚未签到

发表于 2018-9-20 07:48:16 | 显示全部楼层 |阅读模式
  开头的碎碎念:
  对接微信公众平台的时候,开始有个字符串排序,我接触golang毕竟时间尚浅,很多东西都是能从网上找到就直接从网上找,结果就是找了好几个示例代码都不好用,好容易一个好用的,从头开始实现的,代码太多了。我就想,google应该把这些玩意都封装好了吧,不然一个新出的语言只有基础语法,没有强大的标准库,谁用这玩意啊。也就是那时候第一次接触src文件夹,后来发现pkg里的那些go文件是绝好的学习资料。
  那么多文件、文件夹从哪开始看呢,我的原则,先找没有依赖性的,也就是没有import的,这么寻摸着就找到了math文件夹。笨方法,从a开始按顺序来呗,这不就碰到了abs.go
  难以理解的第12行:
// Copyright 2009 The Go Authors. All rights reserved.  

// Use of this source code is governed by a BSD-style  

// license that can be found in the LICENSE file.  

  
package math
  

  
// Abs returns the absolute value of x.
  
//
  
// Special cases are:
  
//    Abs(±Inf) = +Inf
  
//    Abs(NaN) = NaN
  
func Abs(x float64) float64
  

  
func abs(x float64) float64 {
  
switch {
  
case x < 0:
  
return -x
  
case x == 0:
  
return 0 // return correctly abs(-0)
  
    }
  
return x
  
}
  孤零零的一行,一个方法声明,别的啥都没有,完全不解其意。
  下面那个abs()不用我说了吧,很简单的,取绝对值。
  不管了,先到math文件夹看看,abs_386.s、abs_amd64.s、abs_arm.s有这三个文件估计跟那行不知道哪来的代码有关系,.s结尾的,汇编语言文件,继续发动google的威力,golang、汇编混编,如此便找到了http://www.mikespook.com/2013/02/%E7%BF%BB%E8%AF%91go-%E5%92%8C%E6%B1%87%E7%BC%96/
  让程序跑起来:
  先让这段程序跑起来吧,因为我的机器是64位的,所以我把abs.go、abs_amd64.s两个文件拷贝到别处,abs.go的包改成了mymath,另外写了一个简单的测试程序
package main  

  
import(
  

"fmt"  
"mymath"
  
)
  

  
func main(){
  
fmt.Println(mymath.Abs(-12.00))
  
}
  在/pkg/tool/windows_amd64下有很多有用的工具,6g、6l啥的,不过常用的都被go命令给封装了,直接go build、go install等命令就解决了。
  涉及到汇编的,主要是6a,上面的代码按如下顺序编译:
  6a abs_amd64.s(生成abs_amd64.6)
  6g –o _go_.6 abs.go(生成_go_.6)
  pack grc abs.a  _go_.6 abs_amd64.6(生成abs.a)
  本来是想直接让主程序调用目录下的库的,import “./mymath”,不过,windows下提示出错import path contains invalid characte ‘:’:”c:/xxx/xxx”,所以只得将abs.a扔到pkg/windows_amd64文件夹中。
  剩下的就是:
  6g test.go(生成test.6)
  6l test.6(生成6.out.exe)
  从简单的golang编译器自动生成的汇编入手:
  先看一个新的命令,golang编译器自动生成汇编中间代码的命令,go tool 6g –S XXX.go,其实上面的那些命令也都可以用go tool XXX来代替,go命令把那些命令都封装进去了。
  来个最简单的代码吧:
package asm  

  
func Asm(i
int)int{  

return i  
}
  go tool 6g –S asm.go:
--- prog list "Asm" ---  
0000 (asm.go:3) TEXT    Asm+0(SB),$0-16
  
0001 (asm.go:3) LOCALS  ,$0
  
0002 (asm.go:3) TYPE    i+0(FP){int},$8
  
0003 (asm.go:3) TYPE    ~anon1+8(FP){int},$8
  
0004 (asm.go:4) MOVQ    i+0(FP),BX
  
0005 (asm.go:4) MOVQ    BX,~anon1+8(FP)
  
0006 (asm.go:4) RET     ,
  plan9汇编,语法跟AT&T颇为类似,传值是前面是源,后面是目的,这点跟masm、nasm啥的都是反的。
  000行:TEXT相当于定义了一个函数,Asm函数名,+0(SB)golang生成的都有这玩意;$0-16,经过我的反复尝试,起码对于int、float64这两者而言,是(参数个数+返回值个数)*8(这都是我自己验证的,没啥科学依据,相关文档我也翻阅过一些,不过鸟语不过关,将把能看懂的东西里没有我需要的,大胆假设,小心论证现在还做不到)。
  001行:我估计是执行指令的位置,不过这都不重要,关键是后头的。
  002、003行:i是变量名,~anon1其实也是变量名(系统自动生成的)
  稍微修改下
func Asm(i int) (j int){  
j
=i  

return  
}
  则003行,就变成了j+8(FP)
  至于0(FP)、8(FP),对于int来说,每个数字占8个字节(64位下),所以传入的参数,第一个就是+0(FP),第二个+8(FP),第三个+16(FP),第四个+24(FP)…
  返回值,如果有多个返回值,第一个+(8+最后一个传入参数的数值)(FP),后面都是依次+8
  {int}标明了数据类型,$8表明占据8个字节
  004行:将参数值传给寄存器BX,MOVQ,传递四字
  005行:将BX中的值传给返回值
  006行:RET
  看看float64又是啥样的:
package asm  

  
func Asm(f float64
)float64{  

return f  
}
--- prog list "Asm" ---  
0000 (asm.go:3) TEXT    Asm+0(SB),$0-16
  
0001 (asm.go:3) LOCALS  ,$0
  
0002 (asm.go:3) TYPE    i+0(FP){int},$8
  
0003 (asm.go:3) TYPE    ~anon1+8(FP){float64},$8
  
0004 (asm.go:4) MOVQ    i+0(FP),X0
  
0005 (asm.go:4) MOVQ    X0,~anon1+8(FP)
  
0006 (asm.go:4) RET     ,
  可以看出与前面用int去尝试大致相同,只是BX寄存器变成了X0,可以推测X0就是浮点数寄存器,有X0,大胆推测会有X1、X2、X3…
  试试吧
package asm  

  
func Asm(f1,f2 float64) float64{
  

return f1+f2  
}
--- prog list "Asm" ---  
0000 (asm.go:3) TEXT    Asm+0(SB),$0-24
  
0001 (asm.go:3) LOCALS  ,$0
  
0002 (asm.go:3) TYPE    f1+0(FP){float64},$8
  
0003 (asm.go:3) TYPE    f2+8(FP){float64},$8
  
0004 (asm.go:3) TYPE    ~anon2+16(FP){float64},$8
  
0005 (asm.go:4) MOVSD   f1+0(FP),X0
  
0006 (asm.go:4) MOVSD   f2+8(FP),X1
  
0007 (asm.go:4) ADDSD   X1,X0
  
0008 (asm.go:4) MOVSD   X0,~anon2+16(FP)
  
0009 (asm.go:4) RET     ,
  abs_amd64.s:
// Copyright 2010 The Go Authors.  All rights reserved.  

  

// Use of this source code is governed by a BSD-style  

  

// license that can be found in the LICENSE file.  

  

  

// func Abs(x float64) float64  

  
TEXT ·Abs(SB),7,$0
  

  
MOVQ   $(1

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598004-1-1.html 上篇帖子: 【GoLang】与或非 异或操作 下篇帖子: golang学习之slice基本操作
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表