刚开始学习x64程序集,我对函数,参数和堆栈有疑问。据我所知,函数中的前四个参数传递给Windows中的rcx,rdx,r8和r9寄存器(以及浮点数的xmm0-xmm3)。所以带有四个参数的简单加法函数如下所示:
add:
mov r10, rcx
add r10, rdx
add r10, r8
add r10, r9
mov rax, r10
ret
但是,我遇到了documentation that mentions this:
至少,每个函数必须在堆栈上保留32个字节(4个64位值)。此空间允许将传递给函数的寄存器轻松复制到众所周知的堆栈位置。 不需要被调用函数将输入寄存器参数溢出到堆栈,但堆栈空间预留确保它可以在需要时使用。
那么,即使我正在制作的函数采用四个或更少的参数,或者它只是一个推荐,我是否必须保留堆栈空间?
答案 0 :(得分:13)
您的引用来自文档的“调用约定”部分。至少,如果不从汇编代码中调用其他函数,则不必担心这一点。如果你这样做,那么你必须尊重“红区”和堆栈对齐方面的考虑因素,你引用的建议是为了确保。
编辑:this post阐明了“红区”和“影子空间”之间的区别。
答案 1 :(得分:0)
我只是碰到了这个不知道而且似乎就是这种情况。例如,GetAsyncKeyState中的前两个指令会覆盖堆栈上方的0x20字节区域中的返回值,该区域应该为被调用者保留用于参数:
user32.GetAsyncKeyState - mov [rsp+08],rbx
user32.GetAsyncKeyState+5- mov [rsp+10],rsi
user32.GetAsyncKeyState+A- push rdi
user32.GetAsyncKeyState+B- sub rsp,20