You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go汇编中add函数栈帧24~32地址段未使用原因咨询

Go汇编中栈帧未使用段的原因解析

问题背景

Go代码

package main

func add(a, b int) int {
    sum := 0
    sum = a + b
    return sum
}
func main() {
    println(add(1, 2))
}

Go版本

$ go version
go version go1.19.1 darwin/amd64

汇编生成命令

$ go tool compile -N -l -S main.go

生成的汇编代码:

main.add STEXT nosplit size=70 args=0x10 locals=0x18 funcid=0x0 align=0x0
        0x0000 00000 (main.go:3)        TEXT    main.add(SB), NOSPLIT|ABIInternal, $24-16
        0x0000 00000 (main.go:3)        SUBQ    $24, SP
        0x0004 00004 (main.go:3)        MOVQ    BP, 16(SP)
        0x0009 00009 (main.go:3)        LEAQ    16(SP), BP
        0x000e 00014 (main.go:3)        FUNCDATA        $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
        0x000e 00014 (main.go:3)        FUNCDATA        $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
        0x000e 00014 (main.go:3)        FUNCDATA        $5, main.add.arginfo1(SB)
        0x000e 00014 (main.go:3)        MOVQ    AX, main.a+32(SP)
        0x0013 00019 (main.go:3)        MOVQ    BX, main.b+40(SP)
        0x0018 00024 (main.go:3)        MOVQ    $0, main.~r0(SP)
        0x0020 00032 (main.go:4)        MOVQ    $0, main.sum+8(SP)
        0x0029 00041 (main.go:5)        MOVQ    main.a+32(SP), AX
        0x002e 00046 (main.go:5)        ADDQ    main.b+40(SP), AX
        0x0033 00051 (main.go:5)        MOVQ    AX, main.sum+8(SP)
        0x0038 00056 (main.go:6)        MOVQ    AX, main.~r0(SP)
        0x003c 00060 (main.go:6)        MOVQ    16(SP), BP
        0x0041 00065 (main.go:6)        ADDQ    $24, SP
        0x0045 00069 (main.go:6)        RET
        0x0000 48 83 ec 18 48 89 6c 24 10 48 8d 6c 24 10 48 89  H...H.l$.H.l$.H.
        0x0010 44 24 20 48 89 5c 24 28 48 c7 04 24 00 00 00 00  D$ H.\$(H..$....
        0x0020 48 c7 44 24 08 00 00 00 00 48 8b 44 24 20 48 03  H.D$.....H.D$ H.
        0x0030 44 24 (H.D$.H..$H.l$)
        0x0040 10 48 83 c4 18 c3                                .H....
main.main STEXT size=86 args=0x0 locals=0x20 funcid=0x0 align=0x0
        0x0000 00000 (main.go:8)        TEXT    main.main(SB), ABIInternal, $32-0
        0x0000 00000 (main.go:8)        CMPQ    SP, 16(R14)
        0x0004 00004 (main.go:8)        PCDATA  $0, $-2
        0x0004 00004 (main.go:8)        JLS     79
        0x0006 00006 (main.go:8)        PCDATA  $0, $-1
        0x0006 00006 (main.go:8)        SUBQ    $32, SP
        0x000a 00010 (main.go:8)        MOVQ    BP, 24(SP)
        0x000f 00015 (main.go:8)        LEAQ    24(SP), BP
        0x0014 00020 (main.go:8)        FUNCDATA        $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
        0x0014 00020 (main.go:8)        FUNCDATA        $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
        0x0014 00020 (main.go:9)        MOVL    $1, AX
        0x0019 00025 (main.go:9)        MOVL    $2, BX
        0x001e 00030 (main.go:9)        PCDATA  $1, $0
        0x001e 00030 (main.go:9)        NOP
        0x0020 00032 (main.go:9)        CALL    main.add(SB)
        0x0025 00037 (main.go:9)        MOVQ    AX, main..autotmp_0+16(SP)
        0x002a 00042 (main.go:9)        CALL    runtime.printlock(SB)
        0x002f 00047 (main.go:9)        MOVQ    main..autotmp_0+16(SP), AX
        0x0034 00052 (main.go:9)        CALL    runtime.printint(SB)
        0x0039 00057 (main.go:9)        CALL    runtime.printnl(SB)
        0x003e 00062 (main.go:9)        NOP
        0x0040 00064 (main.go:9)        CALL    runtime.printunlock(SB)
        0x0045 00069 (main.go:10)       MOVQ    24(SP), BP
        0x004a 00074 (main.go:10)       ADDQ    $32, SP
        0x004e 00078 (main.go:10)       RET
        0x004f 00079 (main.go:10)       NOP
        0x004f 00079 (main.go:8)        PCDATA  $1, $-1
        0x004f 00079 (main.go:8)        PCDATA  $0, $-2
        0x004f 00079 (main.go:8)        CALL    runtime.morestack_noctxt(SB)
        0x0054 00084 (main.go:8)        PCDATA  $0, $-1
        0x0054 00084 (main.go:8)        JMP     0
        0x0000 49 3b 66 10 76 49 48 83 ec 20 48 89 6c 24 18 48  I;f.vIH.. H.l$.H
        0x0010 8d 6c 24 18 b8 01 00 00 00 bb 02 00 00 00 66 90  .l$...........f.
        0x0020 e8 00 00 00 00 48 89 44 24 10 e8 00 00 00 00 48  .....H.D$......H
        0x0030 8b 44 24 10 e8 00 00 00 00 e8 00 00 00 00 66 90  .D$...........f.
        0x0040 e8 00 00 00 00 48 8b 6c 24 18 48 83 c4 20 c3 e8  .....H.l$.H.. ..
        0x0050 00 00 00 00 eb aa                                ......
        rel 33+4 t=7 main.add+0
        rel 43+4 t=7 runtime.printlock+0
        rel 53+4 t=7 runtime.printint+0
        rel 58+4 t=7 runtime.printnl+0
        rel 65+4 t=7 runtime.printunlock+0
        rel 80+4 t=7 runtime.morestack_noctxt+0
go.cuinfo.producer.<unlinkable> SDWARFCUINFO dupok size=0
        0x0000 2d 4e 20 2d 6c 20 72 65 67 61 62 69              -N -l regabi
go.cuinfo.packagename.main SDWARFCUINFO dupok size=0
        0x0000 6d 61 69 6e                                      main
main..inittask SNOPTRDATA size=24
        0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x0010 00 00 00 00 00 00 00 00                          ........
gclocals·g2BeySu+wFnoycgXfElmcg== SRODATA dupok size=8
        0x0000 01 00 00 00 00 00 00 00                          ........
main.add.arginfo1 SRODATA static dupok size=5
        0x0000 00 08 08 08 ff                                   .....

用户对栈布局的理解

以SP为add函数栈顶,用户梳理的栈区间用途:

  • 0~8:~r0,add函数的返回值
  • 8~16:sum,add函数的局部变量sum
  • 16~24:BP,用于返回至调用者main函数
  • 32~40:a,add函数的参数a
  • 40~48:b,add函数的参数b

未使用段的原因解析

你提到的24~32地址段并非未被使用,而是存储了调用者main执行CALL main.add时自动压入栈的返回地址,这段内容看起来“无操作”的原因如下:

  1. RET指令自动处理返回地址:当add函数执行到RET指令时,CPU会自动从栈顶弹出该返回地址,并跳转到该地址继续执行main函数,无需在汇编代码中显式读取或修改这段内容。
  2. 栈帧结构的规范要求:在x86-64架构的Go函数调用流程中,CALL指令会先将返回地址(8字节)压入栈,之后add函数通过SUBQ $24, SP分配局部栈空间,此时返回地址恰好位于SP+24的位置(即24~32区间)。这段空间属于调用者栈帧的一部分,被调用者add不需要直接操作它。

另外从add函数的TEXT指令参数$24-16也能佐证:$24是当前函数的局部栈大小(包含BP存储位置),-16是调用者传递的参数总大小(两个int共16字节),而返回地址的8字节是调用过程中CPU自动压入的,不属于局部栈或参数的计数范围。


内容的提问来源于stack exchange,提问作者spongecaptain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:50:29