__asm{}; return eax 的值?

Does __asm{}; return the value of eax?

简单的问题。 C 中的函数 asm 用于在您的代码中进行内联汇编。但是它 return 是什么意思?是不是约定俗成的eax,如果不是,那又是什么return?

不太可能;根据 C99 规范,在 J3 实现定义的行为下:

The asm keyword may be used to insert assembly language directly into the translator output (6.8). The most common implementation is via a statement of the form:

asm ( character-string-literal );

因此,实施者不太可能想出一种既能将汇编语言插入翻译器输出又能生成一些额外的中间链接代码以将特定寄存器连接为 return 结果的方法.

这是关键字,不是函数。

例如GCC 使用 "=r" 类型的约束语义来允许您在程序集中对变量进行写访问。但是你确保结果在正确的地方结束。

__asm__本身没有return一个值。 C 标准没有定义 __asm__ 应该如何处理 return 值,因此编译器之间的行为可能不同。您声明 Visual Studio 示例有效,但 Visual Studio 使用 __asm__asm__ 至少被 GCC 使用。

Visual Studio

要在 C 程序中获得结果,您可以在汇编代码中将 return 值设置为 eax,并在函数中设置 return。调用者将收到 eax 的内容作为 return 值。即使启用了优化,也支持此功能,即使编译器决定内联包含 __asm{} 块的函数。

它避免了 store/reload 否则你会从 moving 值到 asm 中的 C 变量和 returning 该 C 变量,因为 MSVC 内联 asm 语法不支持寄存器中的 inputs/outputs(此 return 值情况除外)。

Visual Studio 2015 documentation:

int power2( int num, int power )
{
   __asm
   {
      mov eax, num    ; Get first argument
      mov ecx, power  ; Get second argument
      shl eax, cl     ; EAX = EAX * ( 2 to the power of CL )
   }
   // Return with result in EAX
   // by falling off the end of a non-void function
}

clang -fasm-blocks 支持相同的 inline-asm 语法,但 not 支持从非 void 函数的末尾掉落,如 returning asm{} 块在 EAX/RAX 中留下的值。如果将 MSVC 内联 asm 移植到 clang,请注意这一点。在启用优化(函数内联)的情况下编译时,它会严重崩溃。

海湾合作委员会

GCC inline assembly HOWTO 不包含类似示例。您不能像在 Visual Studio 中那样使用隐式 return,但幸运的是您不需要这样做,因为 GNU C 内联 asm 语法允许在寄存器中指定输出。无需破解即可避免 store/reload 输出值。

HOWTO 显示您可以将结果存储到汇编块内的 C 变量中,并且在汇编块结束后 return 该变量的值。您甚至可以使用 "=r"(var) 让编译器选择它的寄存器选择,以防内联后 EAX 不是最方便的。

一个(低效的)字符串复制函数的例子,returning dest 的值:

static inline char * strcpy(char * dest,const char *src)
{
int d0, d1, d2;
__asm__ __volatile__(  "1:\tlodsb\n\t"
                       "stosb\n\t"
                       "testb %%al,%%al\n\t"
                       "jne 1b"
                     : "=&S" (d0), "=&D" (d1), "=&a" (d2)
                     : "0" (src),"1" (dest) 
                     : "memory");
return dest;
}

(请注意,dest 实际上不是内联 asm 语句的输出。虚拟输出操作数的匹配约束告诉编译器内联 asm 破坏了该变量的副本,因此它需要保留它以某种方式独立于 asm 语句。)


如果您在启用优化的非 void 函数中省略 return 语句,您会收到类似 warning: no return statement in function returning non-void [-Wreturn-type] 的警告,而最近的 GCC/clang 甚至不会发出 ret;它假设这条执行路径从未被采用(因为那将是 UB)。函数是否包含 asm 语句并不重要。