我正在为 GNU 汇编器编写一些 x64 程序集。我一直在尝试阅读有关 .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),我不应该对齐堆栈吗?根据女士:
堆栈将始终保持 16 字节对齐,序言内除外
也许我可以通过这个“推理”我的方式?如果打电话给我的人做对了(如果...),那么当他做call
. 我可以依赖这个吗?看起来很脆弱。
我试过查看其他代码,但我不确定我是否相信我所看到的。我怀疑gas
报告误用 .seh_* 的错误。您可能只会在实际异常期间看到问题(甚至可能并非总是如此)。
如果我要这样做,我想把它做对。看起来堆栈对齐是一件很常见的事情,所以这里必须有人有解决方案。我只是没看到。