x64网上说rcx,rdx,r8,r9,堆栈,但实际上,堆栈必须预留够相应的参数大小。比如传入rcx,rdx两个参数,则调用入口(call指令处rsp)必须上面要留2个寄存器大小的地址。而超过的部分,也就是需要用堆栈来传递的部分,则从调用入口处向上偏移4个处传递。也就是说前4个参数虽然用寄存器,但是堆栈的位置必须预留出来,以便于函数体内调用。难怪现在gcc编译出来的代码不使用压栈方式,而是直接改堆栈数据了。
以上研究结果来自于delphi cpu调试。
后又经过使用vc++2015编写x64DLL导出测试,跟delphi调试结果相同,而且不做堆栈平衡。由调用者在调用前分配好堆栈,类似于:
fmmain.pas.137: begin
00000000006FB090 55 push rbp
00000000006FB091 4883EC40 sub rsp,$40
00000000006FB095 488BEC mov rbp,rsp
00000000006FB098 48894D50 mov [rbp+$50],rcx
00000000006FB09C 48895558 mov [rbp+$58],rdx
...
...
...
fmmain.pas.146: end;
00000000006FB0E8 488D6540 lea rsp,[rbp+$40]
00000000006FB0EC 5D pop rbp
00000000006FB0ED C3 ret