go version go16.2, maxOS Mojave
原理能够从 https://juejin.cn/post/684490…,本片单纯解析源码
哪里调用
原函数
package main
func testMoreStack(a, b int) int {return testMoreStack(1, b)
}
func main() {}
编译
go tool compile -N -l -S ./main2.go > ./main2~~~~.s
关上生成文件 main2.s
"".testMoreStack STEXT size=93 args=0x18 locals=0x28 funcid=0x0
0x0000 00000 (./main2.go:7) TEXT "".testMoreStack(SB), ABIInternal, $40-24
0x0000 00000 (./main2.go:7) MOVQ (TLS), CX // CX = *g
0x0009 00009 (./main2.go:7) CMPQ SP, 16(CX) // if SP > g.stackguard1
0x000d 00013 (./main2.go:7) PCDATA $0, $-2
0x000d 00013 (./main2.go:7) JLS 86 // true 跳到 86
0x000f 00015 (./main2.go:7) PCDATA $0, $-1
0x000f 00015 (./main2.go:7) SUBQ $40, SP
0x0013 00019 (./main2.go:7) MOVQ BP, 32(SP)
0x0018 00024 (./main2.go:7) LEAQ 32(SP), BP
0x001d 00029 (./main2.go:7) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (./main2.go:7) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (./main2.go:7) MOVQ $0, "".~r2+64(SP)
0x0026 00038 (./main2.go:8) MOVQ "".b+56(SP), AX
0x002b 00043 (./main2.go:8) MOVQ $1, (SP)
0x0033 00051 (./main2.go:8) MOVQ AX, 8(SP)
0x0038 00056 (./main2.go:8) PCDATA $1, $0
0x0038 00056 (./main2.go:8) CALL "".testMoreStack(SB)
0x003d 00061 (./main2.go:8) MOVQ 16(SP), AX
0x0042 00066 (./main2.go:8) MOVQ AX, ""..autotmp_3+24(SP)
0x0047 00071 (./main2.go:8) MOVQ AX, "".~r2+64(SP)
0x004c 00076 (./main2.go:8) MOVQ 32(SP), BP
0x0051 00081 (./main2.go:8) ADDQ $40, SP
0x0055 00085 (./main2.go:8) RET
0x0056 00086 (./main2.go:8) NOP
0x0056 00086 (./main2.go:7) PCDATA $1, $-1
0x0056 00086 (./main2.go:7) PCDATA $0, $-2
0x0056 00086 (./main2.go:7) CALL runtime.morestack_noctxt(SB)
0x005b 00091 (./main2.go:7) PCDATA $0, $-1
0x005b 00091 (./main2.go:7) JMP 0 // 跳到 0
0x0000 65 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 47 48 eH..%....H;a.vGH
0x0010 83 ec 28 48 89 6c 24 20 48 8d 6c 24 20 48 c7 44 ..(H.l$ H.l$ H.D
0x0020 24 40 00 00 00 00 48 8b 44 24 38 48 c7 04 24 01 $@....H.D$8H..$.
0x0030 00 00 00 48 89 44 24 08 e8 00 00 00 00 48 8b 44 ...H.D$......H.D
0x0040 24 10 48 89 44 24 18 48 89 44 24 40 48 8b 6c 24 $.H.D$.H.D$@H.l$
0x0050 20 48 83 c4 28 c3 e8 00 00 00 00 eb a3 H..(........
rel 5+4 t=17 TLS+0
rel 57+4 t=8 "".testMoreStack+0
rel 87+4 t=8 runtime.morestack_noctxt+0
本函数栈 40 字节
, 调用栈24 字节
, 函数返回 PC 8 字节
字节共 72 字节
,
栈地位:
地位 | 值 |
---|---|
64(SP) | 返回值 |
56(SP) | 参数 b |
48(SP) | 参数 a |
40(SP) | PC |
32(SP) | base point |
24(SP) | 长期存调用 testMoreStack 的返回值 |
16(SP) | 调用 testMoreStack 的返回值 |
8(SP) | 调用 testMoreStack 的第二个参数 |
0(SP) | 调用 testMoreStack 的第一个参数 |
伪代码
label0:
if SP > g.stackguard1 {CALL runtime.morestack_noctxt(SB)
jump label0
} else {do something}
开始执行
以 asm_arm64.s 为例
TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
MOVW $0, R26
B runtime·morestack(SB)
// Called during function prolog when more stack is needed.
// Caller has already loaded:
// R3 prolog's LR (R30)
//
// The traceback routines see morestack on a g0 as being
// the top of a stack (for example, morestack calling newstack
// calling the scheduler calling newm calling gc), so we must
// record an argument size. For that purpose, it has no arguments.
TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
// Cannot grow scheduler stack (m->g0).
MOVD g_m(g), R8 // R8 = g.m
MOVD m_g0(R8), R4 // R4 = g.m.g0
CMP g, R4 // if g == g0
BNE 3(PC) // 不等跳过上面两个指令(不能在 g0 执行 morestack)
BL runtime·badmorestackg0(SB)
B runtime·abort(SB)
// Cannot grow signal stack (m->gsignal).
MOVD m_gsignal(R8), R4 // R4 = g.m.gsignal
CMP g, R4 // if g == gsignal
BNE 3(PC) // 不等跳过上面两个指令(不能在 g0 执行 gsignal)
BL runtime·badmorestackgsignal(SB)
B runtime·abort(SB)
// Called from f.
// Set g->sched to context in f
MOVD RSP, R0 // R0 = RSP
MOVD R0, (g_sched+gobuf_sp)(g) // g.sched.gobuf.sp = R0
MOVD R29, (g_sched+gobuf_bp)(g) // g.sched.gobuf.bp = R29
MOVD LR, (g_sched+gobuf_pc)(g) // g.sched.gobuf.pc = R29
MOVD R3, (g_sched+gobuf_lr)(g) // g.sched.gobuf.lr = R3
MOVD R26, (g_sched+gobuf_ctxt)(g)
// Called from f.
// Set m->morebuf to f's callers.
MOVD R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC
MOVD RSP, R0
MOVD R0, (m_morebuf+gobuf_sp)(R8) // f's caller's RSP
MOVD g, (m_morebuf+gobuf_g)(R8)
// Call newstack on m->g0's stack.
MOVD m_g0(R8), g //
BL runtime·save_g(SB)
MOVD (g_sched+gobuf_sp)(g), R0
MOVD R0, RSP
MOVD (g_sched+gobuf_bp)(g), R29
MOVD.W $0, -16(RSP) // create a call frame on g0 (saved LR; keep 16-aligned)
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// is still in this function, and not the beginning of the next.
UNDEF