【笔记】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