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