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 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦