使用MASM编写x64汇编代码,我们可以使用这些指令来提供退帧信息。例如,从.SETFRAME
定义中:
这些指令不会生成代码;它们仅生成.xdata和.pdata。
由于这些指令不会产生任何代码,因此我无法在反汇编窗口中看到其效果。因此,当我编写带有或不带有这些指令的汇编函数时,我看不出任何区别。
我如何查看这些指令的结果-使用.SETFRAME
或其他?
如何编写可以测试此展开功能的代码?例如,我故意编写导致异常的汇编代码。我想看看使用或不使用这些指令编写函数时异常处理行为的差异。
就我而言,呼叫者是用C ++编写的,可以使用dumpbin
,SSE等-与这种情况有关的任何东西。
[最好的选择是让asm函数调用另一个C ++函数,并使C ++函数抛出C ++异常。 (不像来自asm的非法内存那样,它会发生故障并可能导致SEH处理程序。正常的C ++异常比Windows SEH更简单)。
因此,需要创建一个C ++异常需要通过asm函数展开堆栈的情况;如果可行,那么您可以正确执行堆栈展开元数据指令。具体来说,C ++调用程序中的try-catch
和C ++函数中的try{}catch
是您从asm throw
获得的。
我认为那个投掷者是call
,因此您可以从asm调用它,而无需更改名称。或通过函数指针调用它,或仅查看MSVC编译器的输出并将错误的名称复制到asm。
BTW,此元数据的非Windows(例如GNU / Linux)等效项是DWARF extern "C"
指令,该指令创建了.cfi
节。
我不知道Windows的等效详细信息,但我确实知道它们使用类似的元数据,这使得无需依赖RBP帧指针即可展开堆栈。这使编译器可以编写优化的代码,而不会浪费函数序言/结尾中的.eh_frame
/ push rbp
和mov rbp,rsp
上的指令,并释放了RBP用作通用寄存器。 (在32位代码中更有用,在该代码中,除了堆栈指针外,还有7个寄存器而不是6个寄存器比15 vs. 14要大得多。)
这个想法是,给定一个RIP,您可以查找从RSP到堆栈上返回地址的偏移量,以及任何保留呼叫的寄存器的位置。因此,您可以还原它们,并使用该返回地址继续展开到父级。