-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
调用Go函数时,内存栈发生了什么? #5
Comments
调用Go函数时,内存栈发生了什么?在Go中,函数调用发生时,内存调用栈都发生了什么? 示例package main
//go:noinline
func sum(a, b int) int {
return a + b
}
func main() {
a, b := 1, 2
sum(a, b)
} 其中 分析通过命令生成汇编代码: GOOS=linux GOARCH=amd64 go tool compile -S main.go 输出汇编内容:
注意:
main函数首先,看main函数,删除无关语句后。
初始化
先看一下Go汇编函数的定义规则。 根据上图中的规则,分析main函数。
需要关注的是
其中TLS的全称为Thread Local Storage,为每个线程私有的存储空间。后续介绍Goroutine调度时会详细介绍TLS。 这几条命令是从TLS中读取当前线程的寄存器信息,如果当前线程要求的栈空间不够用,则跳转到64行即
其中指令以
当完成main函数初始化后,栈空间的状态如下图所示,每一个表示8字节空间,绿色部分表示main()函数的栈空间。 调用sum函数
为了能够实现函数调用后,能继续之前的操作。CALL指令实际上完成了下列两步操作:
sum函数去掉暂时忽略的语句后,sum函数对应的汇编如下,
首先, 其次,由于之前的CALL指令对SP寄存器做了修改,所以保存a、b的地址分别变成了8(SP)和16(SP)。对这两个值进行ADDQ操作后保存到AX寄存器中,然后放入24(SP)的位置。如下图所示: 最后,调用RET指令,相当于执行了 返回main函数结束main函数前,通过更新BP、SP寄存器释放main所占用的栈空间。
首先,将24(SP)地址,即上图中旧栈的BP寄存器恢复到BP中。其次,对SP增加32,缩小32字节,对应的是main函数初始化时扩展的32字节。最后,RET。 |
在Go中,函数调用发生时,内存调用栈都发生了什么?
The text was updated successfully, but these errors were encountered: