我试图重写此代码段以在visual studio中工作,但我显然不明白如何使用冒号的目的和__volatile__
的含义,
__asm__ __volatile__ (
"mov %0, %%edi\n"
"xor %%eax, %%eax\n"
"xor %%ecx, %%ecx\n"
"dec %%ecx\n"
"repne scasb\n"
"sub %%ecx, %%eax\n"
"dec %%eax\n"
:
: "m" (src)
: "memory", "%ecx", "%edi", "%eax");
谢谢!
答案 0 :(得分:2)
两个内联汇编程序完全不同。 Visual Studio内联汇编程序更原始但更易于使用。在VS:
你的代码没有任何输出操作符(在第一个冒号之后),所以我不知道它是如何产生任何影响的。但是假设eax
寄存器最后要保存在src
变量中。那你想要这样的东西:
char* src;
...
__asm {
mov edi,src
xor eax,eax
xor ecx,ecx
dec ecx
repne scasb
sub eax,ecx
dec eax
mov src,eax // save result
}
顺便说一下,它对我来说看起来不是最理想的。如果我正确理解了代码,那么eax
的所有业务都可以由not ecx
完成:
__asm {
mov edi,src
xor al,al
xor ecx,ecx
dec ecx
repne scasb
not ecx
mov src,ecx // save result
}
答案 1 :(得分:0)
......我不明白......冒号的目的......
Columbo在评论中指出,这是相关的手册页:6.43.2 Extended Asm - Assembler Instructions with C Expression Operands。冒号只是在ASM块中分隔标记。它们类似于分号终止C语句(或者更确切地说,可能是逗号运算符,因为它们是相关的)。
要重申页面的内容,一般格式为:
asm (
Instructions (Assembler Code)
: Outputs (C variables modified by the instructions)
: Inputs (C expressions read by the instructions)
: Clobbers (Registers or other values changed by the instructions)
)
有时在分号之间不会有任何标记。例如,这就是内存屏障的样子:
__asm__ __volatile__ ("" ::: "memory")
没有汇编代码,没有C变量用作输出,并且没有C表达式用作输入。但是内存被列为破坏,因此编译器知道在下一条指令执行之前已经完成了挂起的读写操作。
......我不明白......
的含义__volatile__
好的,所以这是一堆蠕虫,因为GCC和Visual Studio以不同的方式解释volatile
的含义(即使它们使用相同的C语言规范)。
在GCC中,使用volatile
的唯一原因是硬件可以改变内存。所以我认为在上面的例子中使用限定符volatile
是一种滥用(因为看起来该函数正在扫描NULL
字节,而不执行内存映射I / O)。
您可以在volatile shared memory找到GCC邮件列表上的相关讨论。 Ian Lance Taylor提供了以下答复,是GCC开发人员之一:
不,不能解决这个问题。这不是什么波动 限定词是为了。 volatile限定符专为使用而设计 内存映射硬件。它不是为多处理器共享而设计的 记忆。如果程序不是多处理器安全的,那么添加 volatile永远不会使多处理器安全。
编辑:正如Tony在下面指出的那样volatile
is used to tame the optimizer,以便在编译期间不会删除ASM块。
另请注意,您可以将代码转换为x86的内联汇编程序,但是您无法为x64执行此操作。 Microsoft不支持x64的内联汇编。请参阅MSDN上的Intrinsics and Inline Assembly。