.seh_stackalloc 和堆栈对齐
.seh_stackalloc and stack alignment
我正在为 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:
The stack will always be maintained 16-byte aligned, except within the prolog
也许我可以'reason' 解决这个问题?如果打电话给我的人做对了(如果...),那么当他执行 call
时堆栈是对齐的,所以现在我少了 8 个字节(return 地址)加上无论我在序言中做什么。我可以依赖这个吗?看起来很脆弱。
我试过查看其他代码,但我不确定我是否相信我所看到的。我怀疑 gas
报告错误是因为滥用 .seh_*。您可能只会在实际异常期间看到问题(甚至可能并不总是如此)。
如果我要这样做,我想把它做好。堆栈对齐似乎很常见,所以这里必须有人有解决方案。我只是没看到。
看看gcc输出的一些代码,我想我知道答案了。我的 'reason' 方法走在了正确的轨道上。
当一个函数被调用时,堆栈暂时变得未对齐(由于 call
),但几乎立即通过 pushq %rbp
重新对齐。之后,总是使用 16 的倍数对堆栈进行调整(对于局部变量或堆栈 space 对于被调用函数的参数等)。所以在序言结束时,堆栈总是再次正确对齐,并保持这种状态直到下一个 call
.
这意味着虽然 andq $-16, %rsp
可用于对齐堆栈,但如果我正确编写序言,则不需要。
注意事项:叶函数(即不调用其他函数的函数)不需要对齐堆栈 (https://msdn.microsoft.com/en-us/library/67fa79wz.aspx)。
我正在为 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:
The stack will always be maintained 16-byte aligned, except within the prolog
也许我可以'reason' 解决这个问题?如果打电话给我的人做对了(如果...),那么当他执行 call
时堆栈是对齐的,所以现在我少了 8 个字节(return 地址)加上无论我在序言中做什么。我可以依赖这个吗?看起来很脆弱。
我试过查看其他代码,但我不确定我是否相信我所看到的。我怀疑 gas
报告错误是因为滥用 .seh_*。您可能只会在实际异常期间看到问题(甚至可能并不总是如此)。
如果我要这样做,我想把它做好。堆栈对齐似乎很常见,所以这里必须有人有解决方案。我只是没看到。
看看gcc输出的一些代码,我想我知道答案了。我的 'reason' 方法走在了正确的轨道上。
当一个函数被调用时,堆栈暂时变得未对齐(由于 call
),但几乎立即通过 pushq %rbp
重新对齐。之后,总是使用 16 的倍数对堆栈进行调整(对于局部变量或堆栈 space 对于被调用函数的参数等)。所以在序言结束时,堆栈总是再次正确对齐,并保持这种状态直到下一个 call
.
这意味着虽然 andq $-16, %rsp
可用于对齐堆栈,但如果我正确编写序言,则不需要。
注意事项:叶函数(即不调用其他函数的函数)不需要对齐堆栈 (https://msdn.microsoft.com/en-us/library/67fa79wz.aspx)。