我有一个与MASM64 64/ML64 64组装的X64 ASM例程。它是一个独立的叶函数,并且不是内联程序集。它用于Visual解决方案中的C/C++程序中。
我找到了关于在MSDN上保存寄存器的两个引用:
第一个是内联程序集,但它特别声明在使用__fastcall时保留ECX。它似乎也缺乏对X64的处理,因为它引用了32位寄存器.
第二部分告诉我们"RAX、RCX、RDX、R8、R9、R10、R11被认为是易失性的,必须在函数调用时考虑销毁“。不幸的是,它没有明确说明是否需要保留这些文件。(如果你仔细观察,它使用的是误导,而不是陈述要采取的行动)。
我认为第二篇文章在这件事上很有控制力,但我想澄清一下,以避免混淆.CX/ECX/RCX是否需要为X64 Fastcall叶函数保留?
发布于 2015-10-16 23:15:17
“在内联装配中使用和保存寄存器”文章只讨论x86,不适用于x86-64。
“呼叫者/Callee保存登记册”文章是关于x86-64调用约定的,并且清楚地指出RCX寄存器是不稳定的,因此不需要被被调用者保存。
@rkhb的一条评论提到,“x64呼叫约定概述”的文章是造成混乱的根源,大概是因为它说:
x64只使用
__fastcall调用约定和基于RISC的异常处理模型。
但是,如果您在引用中遵循__fastcall链接,您将看到它说,“此调用约定__fastcall仅适用于x86体系结构”。我认为概述文章实际上意味着,"x64使用类似于__fastcall的调用约定,其中寄存器用于传递参数“。
发布于 2022-07-25 08:35:10
因为调用者必须假定函数破坏了这些寄存器,所以被调用者可以在不保存它们的情况下销毁它们。也就是说,这些寄存器是易失性,也就是所谓的失败。它适用于64位寄存器的整个列表,包括所有的arg传递寄存器.
函数内部与周围C/C++代码的内联__asm接口本质上与函数之间的ABI /调用约定无关。例如,x86 (32位) fastcall有调用失败的ECX,就像对arg传递寄存器一样。32位fastcall是Windows x64 fastcall之外的一个单独的调用约定,所以您所读到的关于32位fastcall的任何内容都是64位的权威。
MSVC内联asm支持是如此脆弱,并且在他们的编译器中很难实现。,他们需要您的asm在带有寄存器args的函数中跳转,因为它们的编译器太笨,无法像普通变量那样将它们保存在安全的地方。例如,你联系的那个医生说:“这会在__asm块的函数中产生问题,因为函数无法判断哪个参数在哪个寄存器中。”但这显然是胡说八道,因为电话会议把这一点打倒了。否则,编译器无法使asm在不使用内联asm的函数中访问其参数。(或者,这是对编译器中的内联asm代码不是为了处理寄存器-arg调用约定而编写的,而且从来没有重新编写的事实的描述。)其他编译器,包括clang-cl,没有这个问题。
这就是所有关于保持ECX的胡说八道的地方,与asm中函数相互调用的方式无关,只有在使用MSVC的易碎内联asm时对函数内部的要求。
https://stackoverflow.com/questions/33179577
复制相似问题