【问题标题】:.seh_stackalloc and stack alignment.seh_stackalloc 和堆栈对齐
【发布时间】:2016-07-04 11:30:13
【问题描述】:

我正在为 GNU 汇编器编写一些 x64 汇编。我一直在尝试read 关于 .seh_* 指令,但我没有找到太多关于它们的信息。 gas 文档根本没有提到它们。

但据我了解,如果我的代码在 SEH 展开操作期间可能在堆栈中,我应该使用这些。而且由于我的代码会进行堆栈操作并调用其他函数,因此 SEH 是可能的,所以我应该使用这些。

主要是我认为我做对了:

.seh_proc FCT
FCT:

push %rbp
.seh_pushreg    %rbp

mov  %rsp, %rbp
.seh_setframe   %rbp, 0

push %r14
.seh_pushreg %r14

lea -(iOffset + iBytes)(%rsp), %rsp
.seh_stackalloc iOffset + iBytes

andq $-16, %rsp <---- But what about this?

.seh_endprologue

etc...

但有一点不清楚。我有这个指令:

andq $-16, %rsp

我到底如何告诉 SEH 我正在执行堆栈对齐?这可能会将堆栈调整从 15 个字节(非常不可能)到 8 个字节(很可能)到 0 个字节(当然可能)。由于实际金额可能要到运行时才能确定,所以我被卡住了。

我想我可以跳过 .seh 指令,但如果 8 字节的堆栈确实被保留在那里,我可能已经破坏了展开,不是吗?这不是破坏了这里的全部目的吗?

或者,我可以省略对齐。但是如果我调用其他函数(比如 memcpy),我不应该对齐堆栈吗?根据MS:

堆栈将始终保持 16 字节对齐,序言内除外

也许我可以通过这个“推理”我的方式?如果打电话给我的人做对了(如果...),那么当他执行call 时堆栈是对齐的,所以现在我偏离了 8 个字节(返回地址)加上我在序言中所做的任何事情.我可以依赖这个吗?看起来很脆弱。

我已经尝试查看其他代码,但我不确定我是否相信我所看到的。我怀疑gas 报告滥用.seh_* 的错误。您可能只会在实际异常期间看到问题(甚至可能并非总是如此)。

如果我要这样做,我想把它做好。看起来堆栈对齐是一件很常见的事情,所以这里必须有人有解决方案。我只是没看到。

【问题讨论】:

    标签: exception-handling memory-alignment gnu-assembler calling-convention structured-exception


    【解决方案1】:

    看看gcc输出的一些代码,我想我知道答案了。我的“理性”方法走在了正确的轨道上。

    当一个函数被调用时,堆栈暂时变得未对齐(由于call),但几乎立即通过pushq %rbp 重新对齐。之后,总是使用 16 的倍数对堆栈(局部变量或调用函数的参数的堆栈空间等)进行调整。因此,在序言结束时,堆栈总是再次正确对齐,并保持这种状态直到下一个call。

    这意味着虽然andq $-16, %rsp 可用于对齐堆栈,但如果我正确编写我的序言,我不应该这样做。

    CAVEAT:叶函数(即不调用其他函数的函数)不需要对齐堆栈 (https://msdn.microsoft.com/en-us/library/67fa79wz.aspx)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 2011-06-16
      • 2019-02-19
      • 1970-01-01
      • 2018-07-18
      相关资源
      最近更新 更多