书接上回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函数调用规则。