15分钟
3.4.2 函数参数和返回值
对于函数来说,最重要的是函数对外提供的API约定,包含函数的名称、参数和返回值。当这些都确定之后,如何精确计算参数和返回值的大小是第一个需要解决的问题。
比如有一个Swap函数的签名如下:
func Swap(a, b int) (ret0, ret1 int)
对于这个函数,我们可以轻易看出它需要4个int类型的空间,参数和返回值的大小也就是32个字节:
TEXT ·Swap(SB), $0-32
那么如何在汇编中引用这4个参数呢?为此Go汇编中引入了一个FP伪寄存器,表示函数当前帧的地址,也就是第一个参数的地址。因此我们以通过+0(FP)
、+8(FP)
、+16(FP)
和+24(FP)
来分别引用a、b、ret0和ret1四个参数。
但是在汇编代码中,我们并不能直接以+0(FP)
的方式来使用参数。为了编写易于维护的汇编代码,Go汇编语言要求,任何通过FP伪寄存器访问的变量必和一个临时标识符前缀组合后才能有效,一般使用参数对应的变量名作为前缀。
下图是Swap函数中参数和返回值在内存中的布局图:
图 3-9 函数定义
下面的代码演示了如何在汇编函数中使用参数和返回值:
TEXT ·Swap(SB), $0
MOVQ a+0(FP), AX // AX = a
MOVQ b+8(FP), BX // BX = b
MOVQ BX, ret0+16(FP) // ret0 = BX
MOVQ AX, ret1+24(FP) // ret1 = AX
RET
从代码可以看出a、b、ret0和ret1的内存地址是依次递增的,FP伪寄存器是第一个变量的开始地址。
学员评价