Microsoft Stack是否始终对齐16字节?

时间:2018-10-02 19:36:46

标签: windows assembly stack x86-64 calling-convention

Assembly Language, Seventh Edition for x86 Processors by Kip Irvine的第211页上,它在 5.53 x86调用约定下表示Microsoft的x64调用约定,

  
      
  1. 调用子例程时,堆栈指针(RSP)必须在16字节边界(16的倍数)上对齐。 CALL指令将8字节的返回地址压入堆栈,因此调用程序必须从堆栈指针中减去8 ,此外,它已经为阴影空间减去了32。
  2.   

接着显示的是sub rsp, 8之前带有sub rsp, 20h的某些程序集(用于32字节的阴影空间)。

这是安全的惯例吗? Microsoft堆栈是否保证在CALL指令之前 对齐16个字节?或者,这本书是否以为堆栈是错误的

  1. 对齐CALL之前的16个字节
  2. 使用CALL
  3. 将8字节的返回地址压入堆栈
  4. 需要额外的sub rsp, 8;才能返回16字节对齐方式吗?

1 个答案:

答案 0 :(得分:3)

  

我要询问是否满足x64 ABI的要求。通过每次调用后将其增长8个字节以达到16个字节的对齐方式来盲目的调整堆栈是否安全?

是的,这就是ABI要求/保证在call之前 16字节对齐的全部要点。


您可以在函数内 做任何您想做的事情,例如3次16位推入,然后sub rsp, (24 - 3*2)可以在进入函数后重新获得16字节的堆栈对齐方式。

或使用movq xmm0, rsp,然后使用rsp作为额外的暂存寄存器,以获取16个整数整型数,直到在制作另一个callret之前还原它为止。 > 1

没有要求在每个指令之后,仅在函数调用边界处将RSP对齐16字节。这就是为什么它们被称为“调用约定”的原因,不是“编码标准”。

这与rbx保留呼叫类似。是否将其保存/存储在堆栈中,xmm0中,静态存储中,否定然后再次否定它还是根本不触摸它都没有关系。重要的是,当您返回调用方时,它具有与调用函数时相同的值。


脚注1:只要您没有任何可能在用户空间堆栈上运行的异步回调/ SEH处理程序,它就可以工作。确实不能保证这是安全的,但可以作为黑客。

Is it valid to write below ESP?是相关的:正如Ped7g指出的那样,如果某些东西可以异步使用堆栈指针下方的空间,那么如果RSP根本不指向堆栈内存,它可能会中断。

我看过一个32位的示例avisynth视频过滤器(我认为),该过滤器用于获得8个tmp reg(当没有MMX可用时),并且在使用此技巧之前先调试代码中的大警告注释。