内联 (x86) 汇编如何影响程序流程?

How does inline (x86) assembly affect the program flow?

我试图了解在 运行 时间内如何调用此类片段:

__asm{
    PUSH ES
    MOV CX,0
    //... More x86 assembly
};

调整寄存器不会破坏程序流程执行吗?

比如:如果上面的CX有一些值,是不是意味着这个寄存器的值就不再有效了?

编译器是否会处理这些依赖关系,或者代码片段的执行是否在特殊情况下发生?

内联汇编在哪些编译器上的使用是不透明的?

有一些额外的标志可以传递给内联汇编代码。其中之一是 "clobber list",它向 C/C++ 编译器指示将由汇编代码块修改的寄存器列表。

请注意,指定这些附加标志的方式取决于编译器(在 Microsoft Visual C++、GCC 等中完全不同...)

对于 GCC,请参阅示例:

https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3

海湾合作委员会

GCC 中,您 必须明确指定 受影响的寄存器以防止执行流程损坏:

asm [volatile] ( AssemblerTemplate
                  : OutputOperands
                  [ : InputOperands
                  [ : Clobbers ] ])

While the compiler is aware of changes to entries listed in the output operands, the inline asm code may modify more than just the outputs.[...] calculations may require additional registers, [...] list them in the clobber list.

如果您的代码对其他项目执行读取或写入操作,请使用 “内存” clobber 参数,而不是已列出的项目。

The "memory" clobber tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands

参考https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

MSVC

另一方面,在 MSVC 中,您 不需要保留 通用寄存器:

When using __asm to write assembly language in C/C++ functions, you don't need to preserve the EAX, EBX, ECX, EDX, ESI, or EDI registers. [...]

You should preserve other registers you use (such as DS, SS, SP, BP, and flags registers) for the scope of the __asm block. You should preserve the ESP and EBP registers unless you have some reason to change them.

参考: https://msdn.microsoft.com/en-us/library/k1a8ss06.aspx


EDITS:将 should 更改为 have to for gcc 并添加了关于“内存”破坏论点,遵循 Olafs 的建议。