云林县网站建设_网站建设公司_动画效果_seo优化
2025/12/23 18:15:04 网站建设 项目流程

【笔记】golang plan9 汇编中,一个汇编函数调用另一个汇编函数

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!

  • cnblogs博客
  • zhihu
  • Github
  • 公众号:一本正经的瞎扯

1. 调试方法

  • 把一个 test 程序编译为二进制
go test \-c \-gcflags="all=-N -l" \-o xxhash.test \github.com/cespare/xxhash/v2
  • 使用 gdb 来调试这个二进制
gdb --args ./xxhash.test \-test.fullpath=true \-test.run=^TestBatch1$
  • 在汇编函数上设置断点
(gdb) break github.com/cespare/xxhash/v2.BatchSum64String
  • 单步调试

    • step
    • s (或者简写为 s)
  • 查看寄存器的值

    • p/x $r8
  • 查看一个指针的内存区域的数据

x/16bx $r8  // 输出 16 字节的内容

2. 一句话总结

一个汇编函数 call 另一个汇编函数,则必然需要栈的空间来存放被调用函数的参数和返回值

// 我的函数
//go:noescape
func BatchSum64String(src []string, dst []uint64) int64// 被调用的函数
//go:noescape
func Sum64(b []byte) uint64

可以发现

  • 主调函数:
    • 参数: src []string, 一共 24 字节
    • 参数:dst []string, 一共 24 字节
    • 参数: int64, 8 字节
  • 被调函数
    • 参数为: []byte,一共 24 字节
    • 返回值为:uint64, 8 字节

因此,需要这样定义函数原型:

// func BatchSum64String(src []string, dst []uint64) int64
// 栈空间 32 字节
// 参数, 56 字节
TEXT ·BatchSum64String(SB), NOSPLIT, $32-56

call 一个函数之前,参数要写到栈上;call 之后,要从栈上取得返回值

    // 把 Data 写到 Sum64 的参数区LEAQ +0(R8)(R11*8), R12MOVQ (R12), R13MOVQ R13, 0(SP)// LenLEAQ +8(R8)(R11*8), R12MOVQ (R12), R13MOVQ R13, 8(SP)MOVQ R13, 16(SP)  // cap// =========================// 2. 调用函数// =========================CALL ·Sum64(SB)// =========================// 3. 取返回值// =========================MOVQ 24(SP), R12
  • 如果有多个参数,则栈布局的顺序是:参数 1, 参数 2...参数 n, 返回值1, 返回值 2... 返回值 n

call 一个函数的时候,不会自动保存寄存器。需要开发者自己维护寄存器。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询