面试题答案
一键面试参数传递
- 基本规则:在Go语言汇编中,函数参数传递时,小的整数和指针类型参数通常直接通过寄存器传递,而较大的结构体等类型参数可能通过栈传递。
- 寄存器传递:例如在amd64架构下,前6个整数或指针类型参数会依次通过寄存器
DI
、SI
、DX
、CX
、R8
、R9
传递。如果参数数量超过6个,多余的参数会从栈上传递,栈上的参数是从右向左入栈的。
寄存器使用
- 调用者保存寄存器:某些寄存器被定义为调用者保存寄存器(caller-saved registers),调用函数的代码(调用者)有责任在调用函数之前保存这些寄存器的值,并在函数返回后恢复。在amd64架构中,
AX
、CX
、DX
、SI
、DI
、R8
-R11
属于调用者保存寄存器。这意味着调用者在调用函数前,若需要使用这些寄存器,需自行保存其值,防止被被调用函数修改后影响后续调用者代码逻辑。 - 被调用者保存寄存器:另一些寄存器是被调用者保存寄存器(callee-saved registers),被调用的函数有责任保存和恢复这些寄存器的值。在amd64架构中,
BX
、BP
、R12
-R15
属于被调用者保存寄存器。被调用函数在使用这些寄存器前,需先保存其值,函数返回前恢复,以确保调用者函数不受影响。
返回值处理
- 单个返回值:如果函数只有一个返回值,且返回值类型为整数或指针类型,通常会通过
AX
(对于64位返回值为RAX
)寄存器返回。例如,一个返回整数的函数,会将计算结果存储到RAX
寄存器中,调用者从RAX
寄存器获取返回值。 - 多个返回值或复杂类型返回值:对于多个返回值或者复杂类型(如结构体)的返回值,可能会通过栈来传递。如果是多个返回值,会按照一定顺序存储在栈上。对于复杂类型结构体返回值,可能会先在栈上分配空间,然后将结构体的内容填充到该栈空间,调用者从栈上获取返回值。