我正在为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字节对齐,但在prolog中除外。
也许我能通过这个“推理”我的方式?如果打电话给我的人做了正确的事情(如果.),那么当他执行call时堆栈是对齐的,所以现在我用8个字节(返回地址)加上我在prolog中所做的任何操作。我能依赖这个吗?看上去很脆弱。
我试过看其他代码,但我不确定我是否相信我所看到的。我怀疑gas报告错误来自误用.seh_*。您可能只会在实际异常期间才会看到问题(甚至不总是这样)。
如果我要这么做,我想做的对。堆栈对齐似乎是一件常见的事情,所以这里必须有人有一个解决方案。我只是没看到而已。
发布于 2016-07-04 22:31:18
看看gcc的一些代码输出,我想我知道答案了。我用“理性”的方法走在正确的轨道上。
调用函数时,堆栈暂时不对齐(由于call),但几乎立即通过pushq %rbp重新对齐。在此之后,总是使用16倍的倍数来调整堆栈(对于局部变量或参数到调用函数的堆栈空间等)。因此,到prolog结束时,堆栈总是正确地对齐,并一直保持到下一个call。
这意味着,虽然可以使用andq $-16, %rsp对齐堆栈,但如果我正确地编写了prolog,就不需要这样做了。
注意:叶函数(即不调用其他函数的函数)不需要对齐堆栈(https://msdn.microsoft.com/en-us/library/67fa79wz.aspx)。
https://stackoverflow.com/questions/38183666
复制相似问题