【发布时间】:2019-03-07 23:41:46
【问题描述】:
在Assembly Language, Seventh Edition for x86 Processors by Kip Irvine 的第 211 页,它在 5.53 The x86 Calling Convention 下说,它解决了 Microsoft x64 调用约定,
- 调用子程序时,堆栈指针 (
RSP) 必须在 16 字节边界(16 的倍数)上对齐。CALL指令将一个 8 字节的返回地址压入堆栈,因此调用程序必须从堆栈指针中减去 8,除了它已经为影子空间减去的 32。李>
接着在sub rsp, 20h 之前显示一些带有sub rsp, 8 的程序集(对于32 字节的影子空间)。
这是一个安全的约定吗? Microsoft 堆栈是否保证在CALL 指令之前 对齐 16 字节?或者,这本书假设堆栈是错误的
- 与
CALL之前的 16 字节对齐 - 有一个 8 字节的返回地址使用
CALL压入堆栈 - 需要额外的
sub rsp, 8;才能恢复到 16 字节对齐?
【问题讨论】:
-
是的,堆栈指针(Rsp)在调用之前必须对齐 16 字节(任何外部 api,用于自身代码(在 asm 中,因为 c/c++ 不是让你这样做,你当然违反了这个))。这只是协议,因为任何 api 都等待并基于此。当然,您并不完全需要
sub rsp, 8。说可能sub rsp, 78h和许多其他人 -
您将编写/执行代码的要求与机器功能混合在一起。代码需要在调用之前将堆栈对齐到 16 个字节,但是机器代码可以通过执行一些不符合要求的操作来轻松打破该规则,例如将字 (2B = 16b) 值推入堆栈。这样的代码很可能会触发一些错误,当被调用的代码会尝试利用该对齐假设来发挥自己的优势并且
rsp将是错误的。但是 CPU 本身不会阻止您调用错误对齐的rsp的其他代码。 -
@Ped7g 不,我问的是满足 x64 ABI 的要求。每次调用后通过将堆栈增长 8 字节以实现 16 字节对齐来盲目调整堆栈是否安全。
-
sub rsp,8是安全的,因为可以安全地假设调用您的代码按要求运行(即安全,因为代码破坏它是错误,应该修复)。如果上面的代码不能满足这个要求,那么sub rsp,8也将无法重新对齐rsp,并且调用 next 函数可能会因此而失败。您可能需要一些时间才能真正找到有效使用该对齐方式的函数(例如,用于对齐的矢量化内存访问),因此您可能经常通过调用未对齐的rsp函数来逃避,但这只是错误,没有演示一下,这不是正确的代码。 -
相关:Why does the x86-64 / AMD64 System V ABI mandate a 16 byte stack alignment? - 同样的设计原因也适用于 MS。
标签: windows assembly stack x86-64 calling-convention