为了账号安全,请及时绑定邮箱和手机立即绑定

读懂go汇编

标签:
Go

go的汇编感觉比较抽象,和之前接触的masm或者nasm,亦或是arm下的汇编指令都有一些不同,而且和语言本身的一些数据结构,如string或者slice相关联,要读懂这些指令之前,需要先明白这些数据结构的内存布局
今天通过对一小段汇编指令的解析,来进一步学习go的汇编

先上源代码
type Bean struct {
    Name string}func main() {
    m := make(map[string]*Bean)
    b := Bean{"Jim"}
    m["Jim"] = &b
    fmt.Println(m["Jim"])
}

简书支持代码高亮了吗?

本次只对最后一条语句的汇编进行分析
使用

$ go tool compile -S main.go >> main.S

生成汇编文件 main.S
打开之后,找到该语句所对应的汇编指令

需要先介绍一下map的取值函数签名
func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer
这个函数,该函数位于runtime包中

    ;获取*maptype
    LEAQ    type.map[string]*"".Bean(SB), AX
    AX, (SP)
    ;获取*hmap,map实际上是一个*hmap类型指针
    LEAQ    ""..autotmp_6+72(SP), AX
    MOVQ    AX, 8(SP)
    ;构造参数key,key是一个string,由字节数组和len字段构成
    ;字符串的字节数组
    LEAQ    go.string."Jim"(SB), AX
    MOVQ    AX, 16(SP)
    ;字符串的字符长度3
    MOVQ    $3, 24(SP)
    PCDATA  $0, $1   ;通过key获取map中的value
    CALL    runtime.mapaccess1_faststr(SB)
    ;获取mapaccess1_faststr的返回值,是unsafe.Pointer(&value)
    MOVQ    32(SP), AX
    ;获取value的内容,因为value类型是指针,直接保存到AX
    MOVQ    (AX), AX
    ;内存置零
    XORPS   X0, X0
    MOVUPS  X0, ""..autotmp_4+56(SP)
    ;构造*Bean的空接口值
    ;*Bean的type
    LEAQ    type.*"".Bean(SB), CX
    MOVQ    CX, ""..autotmp_4+56(SP)
    ;AX保存的是*Bean的类型
    MOVQ    AX, ""..autotmp_4+64(SP)
    ;保存空接口值的地址到AX
    LEAQ    ""..autotmp_4+56(SP), AX
    ;可变长参数实际上是一个slice,底层数组只有一个元素
    MOVQ    AX, (SP)
    ;len为1
    MOVQ    $1, 8(SP)
    ;cap为1
    MOVQ    $1, 16(SP)
    PCDATA  $0, $3
    ;调用fmt.Println
    CALL    fmt.Println(SB)

汇编高亮?

go的汇编中,调用一个函数时,调用方要先把参数类型的内存布局和函数的参数声明顺序放到SP伪寄存器对应的函数栈中,而被调用函数把返回值写到紧接参数之后的位置,调用方可以直接获取到



作者:咖啡加方糖
链接:https://www.jianshu.com/p/86a59f709ea0

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消