是否为少于四个参数的函数保留了必要的堆栈空间?

时间:2011-09-12 18:39:41

标签: assembly stack 64-bit cpu-registers

刚开始学习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位值)。此空间允许将传递给函数的寄存器轻松复制到众所周知的堆栈位置。 不需要被调用函数将输入寄存器参数溢出到堆栈,但堆栈空间预留确保它可以在需要时使用。

那么,即使我正在制作的函数采用四个或更少的参数,或者它只是一个推荐,我是否必须保留堆栈空间?

2 个答案:

答案 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