在Assembly Language, Seventh Edition for x86 Processors by Kip Irvine的第211页上,它在 5.53 x86调用约定下表示Microsoft的x64调用约定,
- 调用子例程时,堆栈指针(
RSP
)必须在16字节边界(16的倍数)上对齐。CALL
指令将8字节的返回地址压入堆栈,因此调用程序必须从堆栈指针中减去8 ,此外,它已经为阴影空间减去了32。
接着显示的是sub rsp, 8
之前带有sub rsp, 20h
的某些程序集(用于32字节的阴影空间)。
这是安全的惯例吗? Microsoft堆栈是否保证在CALL
指令之前 对齐16个字节?或者,这本书是否以为堆栈是错误的
CALL
之前的16个字节CALL
sub rsp, 8;
才能返回16字节对齐方式吗?答案 0 :(得分:3)
我要询问是否满足x64 ABI的要求。通过每次调用后将其增长8个字节以达到16个字节的对齐方式来盲目的调整堆栈是否安全?
是的,这就是ABI要求/保证在call
之前 16字节对齐的全部要点。
您可以在函数内 做任何您想做的事情,例如3次16位推入,然后sub rsp, (24 - 3*2)
可以在进入函数后重新获得16字节的堆栈对齐方式。
或使用movq xmm0, rsp
,然后使用rsp
作为额外的暂存寄存器,以获取16个整数整型数,直到在制作另一个call
或ret
之前还原它为止。 > 1
没有要求在每个指令之后,仅在函数调用边界处将RSP对齐16字节。这就是为什么它们被称为“调用约定”的原因,不是“编码标准”。
这与rbx保留呼叫类似。是否将其保存/存储在堆栈中,xmm0中,静态存储中,否定然后再次否定它还是根本不触摸它都没有关系。重要的是,当您返回调用方时,它具有与调用函数时相同的值。
脚注1:只要您没有任何可能在用户空间堆栈上运行的异步回调/ SEH处理程序,它就可以工作。确实不能保证这是安全的,但可以作为黑客。
Is it valid to write below ESP?是相关的:正如Ped7g指出的那样,如果某些东西可以异步使用堆栈指针下方的空间,那么如果RSP根本不指向堆栈内存,它可能会中断。
我看过一个32位的示例avisynth视频过滤器(我认为),该过滤器用于获得8个tmp reg(当没有MMX可用时),并且在使用此技巧之前先调试代码中的大警告注释。