__asm{} 吗?返回 eax 的值? [英] Does __asm{}; return the value of eax?

查看:39
本文介绍了__asm{} 吗?返回 eax 的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单的问题.C 中的函数 asm 用于在代码中进行内联汇编.但它返回什么?是传统的eax,如果不是,它返回什么?

Simple question. The function asm in C is used to do inline assembly in your code. But what does it return? Is it the conventional eax, and if not, what does it return?

推荐答案

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

__asm__ itself does not return a value. C standard does not define how __asm__ should handle the return value, so the behavior might be different between compilers. You stated that Visual Studio example is valid, but Visual Studio uses __asm. __asm__ is used at least by GCC.

要在C程序中得到结果,可以将返回值放在汇编代码中eax,然后从函数中返回.调用者将接收eax 的内容作为返回值.即使启用优化,也支持此功能,即使编译器决定内联包含 __asm{} 块的函数.

To get the result in a C program, you can place return value to eax in the assembly code, and return from the function. The caller will receive contents of eax as the return value. This is supported even with optimization enabled, even if the compiler decides to inline the function containing the __asm{} block.

它避免了存储/重新加载,否则您将通过 mov 将值转换为 asm 中的 C 变量并返回该 C 变量,因为 MSVC 内联 asm 语法不支持输入/寄存器中的输出(此返回值情况除外).

It avoids a store/reload you'd otherwise get from moving the value to a C variable in the asm and returning that C variable, because MSVC inline asm syntax doesn't support inputs/outputs in registers (except for this return-value case).

Visual Studio 2015 文档:

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 语法,但支持从非void 函数的末尾脱落作为返回 asm{} 块留在 EAX/RAX 中的值.如果将 MSVC 内联 asm 移植到 clang,请注意这一点.在启用优化(函数内联)的情况下编译时,它会崩溃.

clang -fasm-blocks supports the same inline-asm syntax but does not support falling off the end of a non-void function as returning the value that an asm{} block left in EAX/RAX. Beware of that if porting MSVC inline asm to clang. It will break horribly when compiled with optimization enabled (function inlining).

GCC 内联汇编 HOWTO 不包含一个类似的例子.您不能像在 Visual Studio 中那样使用隐式返回,但幸运的是您不需要这样做,因为 GNU C 内联 asm 语法允许在寄存器中指定输出.无需 hack 即可避免存储/重新加载输出值.

GCC inline assembly HOWTO does not contain a similar example. You can't use an implicit return as in Visual Studio, but fortunately you don't need to because GNU C inline asm syntax allows specifying outputs in registers. No hack is needed to avoid a store/reload of an output value.

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

The HOWTO shows that you can store the result to C variable inside the assembly block, and return value of that variable after the assembly block has ended. You can even use "=r"(var) to let the compiler pick its choice of register, in case EAX isn't the most convenient after inlining.

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

An example of an (inefficient) string copy function, returning value of dest:

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

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

(Note that dest isn't actually an output from the inline asm statement. The matching constraint for the dummy output operands tells the compiler the inline asm destroyed that copy of the variable so it needs to preserve it across the asm statement on its own somehow.)

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

If you omit a return statement in a non-void function with optimization enabled, you get a warning like warning: no return statement in function returning non-void [-Wreturn-type] and recent GCC/clang won't even emit a ret; it assumes this path of execution is never taken (because that would be UB). It doesn't matter whether or not the function contained an asm statement or not.

这篇关于__asm{} 吗?返回 eax 的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆