使用和保留注册在内联程序集

Microsoft 专用

通常,您不应假定,注册将具有特定值时, __asm 块启动时。寄存器值不能保证在单独的 __asm 之间保持被。如果您关闭内联代码块并启动另一种方法,您在第二个集合中的项目不能依赖于注册块保留它们的值从开始块。__asm 块继承任何注册值从正常控制流的结果。

如果使用 __fastcall 调用约定时,编译器通过在注册的函数参数而不是在堆栈。该功能可能会产生问题。 __asm 块,因为函数没有方式调用哪一个参数在哪注册。如果函数在 EAX 意外获得 EAX 的参数并立即存储其他,原始参数丢失。此外,还必须保留在这些函数的 ECX 注册声明 __fastcall。

若要避免此类注册冲突,不需要针对包含 __asm 阻塞功能使用 __fastcall 约定。如果全局指定 __fastcall 约定使用 /Gr 编译器选项的,声明包含 __asm 的每个功能块 __cdecl 或 __stdcall。( __cdecl 属性通知编译器为该函数使用 C 调用约定。)如果不使用 /Gr 进行编译,请避免使用声明 __fastcall 属性的函数。

在使用编写汇编语言的 __asm 在 C/C++ 函数,则不需要将 EAX、 EBX、 ECX ESI EDX、、或 EDI 注册。例如,在 具有内联程序集的写入功能的 POWER2.C 示例, power2 函数不保持在 EAX 寄存器值。但是,在中,因为注册分配程序无法使用它们存储在 __asm 中的值块,使用这些寄存器将影响代码质量。另外,可以使用 EBX, ESI,或 EDI 在内联程序集代码,则强制编译器保存和还原这些注册在 prolog 和收场白。

您应保留所使用的其他注册 (例如 SS SP DS、、、 BP 和标志注册)。 __asm 范围块。您应保留 ESP 和 EBP 寄存器,除非您出于某些原因更改这些 (如切换堆栈,)。另请参见 优化内联程序集

某个 SSE 类型需要八个字节的堆栈对齐方式,强制编译器将发出动态堆栈对齐代码。若要能够访问以及对齐后的局部变量函数参数,编译器包含两个帧指针。如果编译器执行帧指针缺少 (FPO),它将使用 EBP 和 ESP。如果编译器未执行 FPO,它将使用 EBX EBP 和。若要确保代码正确运行,而不修改在 asm 代码的 EBX,如果函数需要动态堆栈对齐,因为它能修改帧指针。使用 EBX,请将八个字节对齐的类型在函数之外或避免。

说明说明

使用 STD 或 CLD 命令,如果内联程序集代码更改方向标志,则必须还原标志为其原始值。

关闭 Microsoft 特定

请参见

参考

内联汇编