我试图了解在运行时如何调用此类代码段:
__asm{
PUSH ES
MOV CX,0
//... More x86 assembly
};
不会调整寄存器会破坏程序流程执行吗?
例如:如果上面的CX保留了某个值,那么这不意味着该寄存器值将不再有效吗?
编译器是否会处理这些依赖项,或者在特殊情况下是否会执行代码段?
在哪些编译器中内联汇编的使用不透明?
答案 0 :(得分:3)
在 GCC 中,必须明确指定受影响的寄存器,以防止影响exectution流:
asm [volatile] ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ])
虽然编译器知道输出中列出的条目的更改 操作数,内联asm代码可能不仅仅修改 输出。[......]计算可能需要额外的登记册,[...] 将它们列在clobber列表中。
如果您的代码执行了对已经列出的其他项目的读取或写入,请使用“memory” clobber参数。
“memory”clobber告诉编译器汇编代码 对内存以外的项目执行内存读取或写入操作 输入和输出操作数
参考:https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
另一方面,在 MSVC 中,您不需要保留通用寄存器:
使用__asm在C / C ++函数中编写汇编语言时,你 不需要保留EAX,EBX,ECX,EDX,ESI或EDI寄存器。 [...]
您应该保留您使用的其他寄存器(例如DS,SS,SP,BP, 和标志寄存器)用于__asm块的范围。你应该 保留ESP和EBP寄存器除非您有某些理由 改变它们。
参考: https://msdn.microsoft.com/en-us/library/k1a8ss06.aspx
编辑:将 更改为gcc,并添加了关于“memory”clobber参数的说明,并附上了Olafs建议。
答案 1 :(得分:1)
可以将一些其他标志传递给内联汇编代码。其中一个是“clobber list”,它向C / C ++编译器指示将由汇编代码块修改的寄存器列表。
请注意,指定这些附加标志的方式取决于编译器(在Microsoft Visual C ++,GCC等中完全不同...)
对于GCC,请参阅:
https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3