go 函数调用规则(三)

本文详细解析了Go函数如何处理大量参数,重点在于理解为何选择九个寄存器存放常用参数,其余存于栈顶,并揭示了返回值的处理方式。了解这些规则有助于编写高效可读的Go代码。

书接上回go 函数调用规则(二)
我们来解决最后一个问题
关于传参到底用哪些寄存器的问题

package main

func val(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t int) (a1 int, b1 int, c1 int, d1 int, e1 int, f1 int, g1 int, h1 int, i1 int, j1 int, k1 int, l1 int, m1 int, n1 int, o1 int, p1 int, q1 int, r1 int, s1 int, t1 int) {
	a1 = a + 2
	b1 = b * 2
	c1 = c + 3
	d1 = d * 3
	e1 = e + 4
	f1 = f * 4
	g1 = g + 1
	h1 = h + 1
	i1 = i + 1
	j1 = j + 1
	k1 = k + 1
	l1 = l + 1
	m1 = m + 1
	n1 = n + 1
	o1 = o + 1
	p1 = p + 1
	q1 = q + 1
	r1 = r + 1
	s1 = s + 1
	t1 = t + 1
	return
}

func test() {
	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 := val(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
	var c int = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20
	c = c + 2
}

func main() {
	test()
}

丧心病狂的传了20个参数

依旧是无关紧要的main函数

sub     rsp, 8
mov     [rsp+8+var_8], rbp
lea     rbp, [rsp+8+var_8]
call    main_test
mov     rbp, [rsp+8+var_8]
add     rsp, 8
nop
retn
sub     rsp, 280h                     #开了0x280的栈
mov     [rsp+280h+var_8], rbp         #处理一下栈底指针
lea     rbp, [rsp+280h+var_8]
mov     [rsp+280h+var_280], 0Ah       #看的出来这是后十一个参数
mov     [rsp+280h+var_278], 0Bh       #直接就在栈顶
mov     [rsp+280h+var_270], 0Ch
mov     [rsp+280h+var_268], 0Dh
mov     [rsp+280h+var_260], 0Eh
mov     [rsp+280h+var_258], 0Fh
mov     [rsp+280h+var_250], 10h
mov     [rsp+280h+var_248], 11h
mov     [rsp+280h+var_240], 12h
mov     [rsp+280h+var_238], 13h
mov     [rsp+280h+var_230], 14h
mov     eax, 1                        #所以前九个是寄存器
mov     ebx, 2                        #eax  ebx  ecx  edi  esi  r8d  r9d  r10d  r11d
mov     ecx, 3
mov     edi, 4
mov     esi, 5
mov     r8d, 6
mov     r9d, 7
mov     r10d, 8
mov     r11d, 9
nop     dword ptr [rax+00h]
call    main_val                     #去看看val函数试试
mov     rdx, [rsp+280h+var_228]      #这是在处理返回的后十一个返回值
mov     r12, [rsp+280h+var_220]      #他们都被放在栈里的十一个传参参数的后面
mov     r13, [rsp+280h+var_218]
mov     r15, [rsp+280h+var_210]
mov     [rsp+280h+var_B0], r15
mov     r15, [rsp+280h+var_208]
mov     [rsp+280h+var_B8], r15
mov     r15, [rsp+280h+var_200]
mov     [rsp+280h+var_C0], r15
mov     r15, [rsp+280h+var_1F8]
mov     [rsp+280h+var_C8], r15
mov     r15, [rsp+280h+var_1F0]
mov     [rsp+280h+var_D0], r15
mov     r15, [rsp+280h+var_1E8]
mov     [rsp+280h+var_D8], r15
mov     r15, [rsp+280h+var_1E0]
mov     [rsp+280h+var_E0], r15
mov     r15, [rsp+280h+var_1D8]
mov     [rsp+280h+var_10], rax
mov     [rsp+280h+var_18], rbx
mov     [rsp+280h+var_20], rcx
mov     [rsp+280h+var_28], rdi
mov     [rsp+280h+var_30], rsi
mov     [rsp+280h+var_38], r8
mov     [rsp+280h+var_40], r9
mov     [rsp+280h+var_48], r10
mov     [rsp+280h+var_50], r11
mov     [rsp+280h+var_58], rdx
mov     [rsp+280h+var_60], r12
mov     [rsp+280h+var_68], r13
mov     rdx, [rsp+280h+var_B0]
mov     [rsp+280h+var_70], rdx
mov     rdx, [rsp+280h+var_B8]
mov     [rsp+280h+var_78], rdx
mov     rdx, [rsp+280h+var_C0]
mov     [rsp+280h+var_80], rdx
mov     rdx, [rsp+280h+var_C8]
mov     [rsp+280h+var_88], rdx
mov     rdx, [rsp+280h+var_D0]
mov     [rsp+280h+var_90], rdx
mov     rdx, [rsp+280h+var_D8]
mov     [rsp+280h+var_98], rdx
mov     rdx, [rsp+280h+var_E0]
mov     [rsp+280h+var_A0], rdx
mov     [rsp+280h+var_A8], r15
mov     rdx, [rsp+280h+var_10]
mov     [rsp+280h+var_E8], rdx
mov     rdx, [rsp+280h+var_18]
mov     [rsp+280h+var_140], rdx
mov     rdx, [rsp+280h+var_20]
mov     [rsp+280h+var_150], rdx
mov     rdx, [rsp+280h+var_28]
mov     [rsp+280h+var_158], rdx
mov     rdx, [rsp+280h+var_30]
mov     [rsp+280h+var_160], rdx
mov     rdx, [rsp+280h+var_38]
mov     [rsp+280h+var_168], rdx
mov     rdx, [rsp+280h+var_40]
mov     [rsp+280h+var_170], rdx
mov     rdx, [rsp+280h+var_48]
mov     [rsp+280h+var_178], rdx
mov     rdx, [rsp+280h+var_50]
mov     [rsp+280h+var_180], rdx
mov     rdx, [rsp+280h+var_58]
mov     [rsp+280h+var_F0], rdx
mov     rdx, [rsp+280h+var_60]
mov     [rsp+280h+var_F8], rdx
mov     rdx, [rsp+280h+var_68]
mov     [rsp+280h+var_100], rdx
mov     rdx, [rsp+280h+var_70]
mov     [rsp+280h+var_108], rdx
mov     rdx, [rsp+280h+var_78]
mov     [rsp+280h+var_110], rdx
mov     rdx, [rsp+280h+var_80]
mov     [rsp+280h+var_118], rdx
mov     rdx, [rsp+280h+var_88]
mov     [rsp+280h+var_120], rdx
mov     rdx, [rsp+280h+var_90]
mov     [rsp+280h+var_128], rdx
mov     rdx, [rsp+280h+var_98]
mov     [rsp+280h+var_130], rdx
mov     rdx, [rsp+280h+var_A0]
mov     [rsp+280h+var_138], rdx
mov     rdx, [rsp+280h+var_A8]
mov     [rsp+280h+var_148], rdx
mov     rdx, [rsp+280h+var_E8]
add     rdx, [rsp+280h+var_140]
add     rdx, [rsp+280h+var_150]
add     rdx, [rsp+280h+var_158]
add     rdx, [rsp+280h+var_160]
add     rdx, [rsp+280h+var_168]
add     rdx, [rsp+280h+var_170]
add     rdx, [rsp+280h+var_178]
add     rdx, [rsp+280h+var_180]
add     rdx, [rsp+280h+var_F0]
add     rdx, [rsp+280h+var_F8]
add     rdx, [rsp+280h+var_100]
add     rdx, [rsp+280h+var_108]
add     rdx, [rsp+280h+var_110]
add     rdx, [rsp+280h+var_118]
add     rdx, [rsp+280h+var_120]
add     rdx, [rsp+280h+var_128]
add     rdx, [rsp+280h+var_130]
add     rdx, [rsp+280h+var_138]
add     rdx, [rsp+280h+var_148]
mov     [rsp+280h+var_188], rdx
add     rdx, 2
mov     [rsp+280h+var_188], rdx
mov     rbp, [rsp+280h+var_8]
add     rsp, 280h
retn

val

var_50= qword ptr -50h
var_48= qword ptr -48h
var_40= qword ptr -40h
var_38= qword ptr -38h
var_30= qword ptr -30h
var_28= qword ptr -28h
var_20= qword ptr -20h
var_18= qword ptr -18h
var_10= qword ptr -10h
var_8= qword ptr -8
arg_0= qword ptr  8
arg_8= qword ptr  10h
arg_10= qword ptr  18h
arg_18= qword ptr  20h
arg_20= qword ptr  28h
arg_28= qword ptr  30h
arg_30= qword ptr  38h
arg_38= qword ptr  40h
arg_40= qword ptr  48h
arg_48= qword ptr  50h
arg_50= qword ptr  58h
arg_58= qword ptr  60h
arg_60= qword ptr  68h
arg_68= qword ptr  70h
arg_70= qword ptr  78h
arg_78= qword ptr  80h
arg_80= qword ptr  88h
arg_88= qword ptr  90h
arg_90= qword ptr  98h
arg_98= qword ptr  0A0h
arg_A0= qword ptr  0A8h
arg_A8= qword ptr  0B0h
arg_B0= qword ptr  0B8h
arg_B8= qword ptr  0C0h
arg_C0= qword ptr  0C8h
arg_C8= qword ptr  0D0h
arg_D0= qword ptr  0D8h
arg_D8= qword ptr  0E0h
arg_E0= qword ptr  0E8h
arg_E8= qword ptr  0F0h
arg_F0= qword ptr  0F8h

sub     rsp, 50h
mov     [rsp+50h+var_8], rbp
lea     rbp, [rsp+50h+var_8]
mov     [rsp+50h+arg_B0], rax        #可以看到前面九个参数放在了后面十一个参数的后面
mov     [rsp+50h+arg_B8], rbx
mov     [rsp+50h+arg_C0], rcx
mov     [rsp+50h+arg_C8], rdi
mov     [rsp+50h+arg_D0], rsi
mov     [rsp+50h+arg_D8], r8
mov     [rsp+50h+arg_E0], r9
mov     [rsp+50h+arg_E8], r10
mov     [rsp+50h+arg_F0], r11
mov     [rsp+50h+var_10], 0
mov     [rsp+50h+var_18], 0
mov     [rsp+50h+var_20], 0
mov     [rsp+50h+var_28], 0
mov     [rsp+50h+var_30], 0
mov     [rsp+50h+var_38], 0
mov     [rsp+50h+var_40], 0
mov     [rsp+50h+var_48], 0
mov     [rsp+50h+var_50], 0
mov     [rsp+50h+arg_58], 0           #但是两组参数中间隔了这么一段
mov     [rsp+50h+arg_60], 0
mov     [rsp+50h+arg_68], 0
mov     [rsp+50h+arg_70], 0
mov     [rsp+50h+arg_78], 0
mov     [rsp+50h+arg_80], 0
mov     [rsp+50h+arg_88], 0
mov     [rsp+50h+arg_90], 0
mov     [rsp+50h+arg_98], 0
mov     [rsp+50h+arg_A0], 0
mov     [rsp+50h+arg_A8], 0
mov     rdx, [rsp+50h+arg_B0]
add     rdx, 2
mov     [rsp+50h+var_10], rdx
mov     rdx, [rsp+50h+arg_B8]
shl     rdx, 1
mov     [rsp+50h+var_18], rdx
mov     rdx, [rsp+50h+arg_C0]
add     rdx, 3
mov     [rsp+50h+var_20], rdx
mov     rdx, [rsp+50h+arg_C8]
lea     rdx, [rdx+rdx*2]
mov     [rsp+50h+var_28], rdx
mov     rdx, [rsp+50h+arg_D0]
add     rdx, 4
mov     [rsp+50h+var_30], rdx
mov     rdx, [rsp+50h+arg_D8]
shl     rdx, 2
mov     [rsp+50h+var_38], rdx
mov     rdx, [rsp+50h+arg_E0]
inc     rdx
mov     [rsp+50h+var_40], rdx
mov     rdx, [rsp+50h+arg_E8]
inc     rdx
mov     [rsp+50h+var_48], rdx
mov     rdx, [rsp+50h+arg_F0]
inc     rdx
mov     [rsp+50h+var_50], rdx
mov     rdx, [rsp+50h+arg_0]
inc     rdx
mov     [rsp+50h+arg_58], rdx
mov     rdx, [rsp+50h+arg_8]
inc     rdx
mov     [rsp+50h+arg_60], rdx
mov     rdx, [rsp+50h+arg_10]
inc     rdx
mov     [rsp+50h+arg_68], rdx
mov     rdx, [rsp+50h+arg_18]
inc     rdx
mov     [rsp+50h+arg_70], rdx
mov     rdx, [rsp+50h+arg_20]
inc     rdx
mov     [rsp+50h+arg_78], rdx
mov     rdx, [rsp+50h+arg_28]
inc     rdx
mov     [rsp+50h+arg_80], rdx
mov     rdx, [rsp+50h+arg_30]
inc     rdx
mov     [rsp+50h+arg_88], rdx
mov     rdx, [rsp+50h+arg_38]
inc     rdx
mov     [rsp+50h+arg_90], rdx
mov     rdx, [rsp+50h+arg_40]
inc     rdx
mov     [rsp+50h+arg_98], rdx
mov     rdx, [rsp+50h+arg_48]
inc     rdx
mov     [rsp+50h+arg_A0], rdx
mov     rdx, [rsp+50h+arg_50]
inc     rdx
mov     [rsp+50h+arg_A8], rdx
mov     rax, [rsp+50h+var_10]       #返回的时候前面九个还是寄存器返回
mov     rbx, [rsp+50h+var_18]       #那十一个返回就放在两组参数中间隔着的那么一段中欧冠返回
mov     rcx, [rsp+50h+var_20]
mov     rdi, [rsp+50h+var_28]
mov     rsi, [rsp+50h+var_30]
mov     r8, [rsp+50h+var_38]
mov     r9, [rsp+50h+var_40]
mov     r10, [rsp+50h+var_48]
mov     r11, [rsp+50h+var_50]
mov     rbp, [rsp+50h+var_8]
add     rsp, 50h
retn
main_val endp

总结一下
这次就聚焦一个问题
函数传参比较多咋办?
可以看到传参的时候首先使用九个寄存器
分别是eax ebx ecx edi esi r8d r9d r10d r11d
剩下的都放在栈顶

返回的时候也是先使用那九个寄存器 剩下的要放在传参使用的栈之后的地方。

这就是go函数调用规则。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值