Skip to content
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

ch6sched:stack.md 6.7.3 G 的创生,示例编译后的代码新版本有变化 #76

Closed
cnbailian opened this issue Jan 21, 2021 · 2 comments

Comments

@cnbailian
Copy link

问题描述

欧神你好,在《6.7.3 G 的创生》一章中,示例代码在新版本编译后有一些变化。以下是我的理解:

	0x001d 00029 (hello.go:8)	MOVL	$16, (SP) // 将 16 放到 SP 的位置,16 是第一个参数 siz,因为是 int32,所以是 MOVL。数字是 16 是因为有 string 和 string.len 两个参数加一起占 16 个字节
	0x0024 00036 (hello.go:8)	LEAQ	"".hello·f(SB), AX // 将 hello 的调用地址传给 AX
	0x002b 00043 (hello.go:8)	MOVQ	AX, 8(SP) // 将 hello 的调用地址放入 8(SP) 的位置
	0x0030 00048 (hello.go:8)	LEAQ	go.string."hello world"(SB), AX // 将“hello world”放入 AX
	0x0037 00055 (hello.go:8)	MOVQ	AX, 16(SP) // 将“hello world”放在 16(SP) 的位置
	0x003c 00060 (hello.go:8)	MOVQ	$11, 24(SP) // 将 $11 放在 24(SP) 的位置,11 是 string 的长度,string 是结构体,结构体在传参中会扁平化为多个参数

在新版本变化后,栈布局的图依然能帮助理解,但有些细节不一致了,在我看来现在的布局是这样的:

             栈布局
40(SP)+-----------------+      高地址
      |    caller BP    |       
32(SP)+-----------------+ <-- main.BP
      |  11 string.len  |
24(SP)+-----------------+ 
      |  "hello world"  |
16(SP)+-----------------+ <-- fn + sys.PtrSize
      |      hello      |
8(SP) +-----------------+ <-- fn
      |       siz       |
(SP)  +-----------------+ <-- SP
      |    newproc PC   |  
      +-----------------+ callerpc: 要运行的 Goroutine 的 PC
      |                 |
      |                 |       低地址

对比两个图,我有些疑惑:
hello 函数地址现在占了 8 个字节,而不是原有图中的两个字节,是因为内存对齐的需求吗?
“hello world” 现在是字符串完整的值传递,而不是地址传递,是有什么区别吗?
“newproc PC” 是如何计算出的在 main.SP 下方的地址呢?我在生成的汇编代码中没有发现这里的处理。

环境

$ go version
go version go1.15.5 darwin/amd64
@changkun
Copy link
Member

  1. 原图中使用的是 16 进制,0x10 表示十进制下的 16
  2. 你生成的代码中 helloworld 仍然是通过地址的方式放入 AX 的,参见 LEA 指令
  3. 例子最后因为需要调用 newproc,执行 CALL 指令,他的本质是 push+jmp,newproc PC 是指 newproc 函数的 program counter,因此会执行压栈,从而 newproc PC 被放在了 SP 的位置。

@cnbailian
Copy link
Author

感谢解惑!我这边生成的代码是十进制就没仔细看,提出了低级的问题,抱歉抱歉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants