go version go16.2, maxOS Mojave
原理能够从https://juejin.cn/post/684490...,本片单纯解析源码
哪里调用
原函数
package mainfunc 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字节
,函数返回PC8字节
字节共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