GoLang 栈帧 实现分析

实验环境

  • Ubuntu 20.10 x86_64 5.4.0-48
  • Go 1.17.12

进程虚拟地址空间

在这里插入图片描述
栈帧分配是在运行时动态申请和释放的, 如图所示,是进城虚拟地址空间组成的一部分,Linux 进程默认栈空间大小8MB, 那么栈空间如何申请和释放的呢?请往下看…

ubuntu@localhost:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 14635
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 14635
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

栈空间申请和释放

栈空间的申请和释放主要和两个寄存器有关:

  • BP (Base Pointer) 栈基
  • SP (Stack Pointer) 栈指针

在这里插入图片描述

栈申请

在这里插入图片描述

SUBQ    $48, SP         //SUBQ 减法  栈申请48字节,因为栈是从高地址--> 低地址
MOVQ    BP, 40(SP)      //存储 BP值
LEAQ    40(SP), BP      //更新 BP值

栈释放

在这里插入图片描述

MOVQ    40(SP), BP    //还原 BP值
ADDQ    $48, SP       //ADDQ 加法  栈释放48字节,因为栈是从高地址--> 低地址
RET                   //返回执行下一条指令

函数栈空间

  • caller 函数调用方 (A)
  • callee 函数被调用方 (B)

GoLang 语言 caller 负责 callee 的参数和返回值空间的申请和释放
在这里插入图片描述
在这里插入图片描述

示例验证

package main
//go:noinline
func sum(a, b int) int {
	sum := 0
	sum = a + b
	return sum
}
//go:noinline
func main() {
	a := 3
	b := 5
	c := sum(a, b)
	a = c + b
}
go tool compile -N -l -S cmd.go | less   //查看汇编代码

在这里插入图片描述

"".sum STEXT nosplit size=70 args=0x10 locals=0x18 funcid=0x0
.....
MOVQ    AX, "".a+32(SP) 访问到"".main的栈空间, 即 "".a+32(SP) =="".main+0(SP)
MOVQ    BX, "".b+40(SP) 访问到"".main的栈空间, 即 "".b+40(SP) =="".main+8(SP)
...
"".main STEXT size=88 args=0x0 locals=0x30 funcid=0x0
...
MOVQ    AX, "".c+16(SP) 访问到
...

在这里插入图片描述

验证:GoLang 语言 caller 负责 callee 的参数和返回值空间的申请和释放

遗留问题

"".sum STEXT nosplit size=70 args=0x10 locals=0x18 funcid=0x0
  0x0000 00000 (cmd.go:4) TEXT    "".sum(SB), NOSPLIT|ABIInternal, $24-16
  ...

$24-16: $24 表示栈大小,16网友描述说是参数+返回值大小,那么应该是18,但实际是16, 感觉只是参数的大小。如果你知道原因,请在评论区留言,感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cugriver

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值