C++ 为什么赢了';简单的内联汇编函数在GCC中是否正常工作?

C++ 为什么赢了';简单的内联汇编函数在GCC中是否正常工作?,c++,xcode,gcc,inline-assembly,C++,Xcode,Gcc,Inline Assembly,我有一个简单的内联汇编函数,它在MSVC中运行良好,但由于某种原因拒绝在Apple GCC 4.2.1下工作(i386 arch,强制32位模式)。幸运的是,更复杂的汇编函数可以很好地工作,但是我不明白为什么这个函数不能工作。。。不幸的是,我无法调试它-从外观上看,XCode 4.0.2中没有寄存器窗口(它在3.2版本中) 我确信问题与英特尔风格的汇编无关 int Convert(double value) { _asm { fld value

我有一个简单的内联汇编函数,它在MSVC中运行良好,但由于某种原因拒绝在Apple GCC 4.2.1下工作(i386 arch,强制32位模式)。幸运的是,更复杂的汇编函数可以很好地工作,但是我不明白为什么这个函数不能工作。。。不幸的是,我无法调试它-从外观上看,XCode 4.0.2中没有寄存器窗口(它在3.2版本中)

我确信问题与英特尔风格的汇编无关

int Convert(double value)
{
     _asm
     {
         fld value
         push eax
         fistp dword ptr [esp]
         pop eax
     }

// The returned value is insane
}
幸运的是,更复杂的汇编函数可以正常工作[…]

这些也是内联汇编函数吗?因为GCC使用内联汇编程序的语法。但是,您可以使语法看起来更熟悉,请参见

这就是我要做的
=m
指定我们需要一个内存操作数来存储结果(我们不需要寄存器,因为
first
不适用于这些寄存器)
t
指定在堆栈顶部传递该值,这也确保了我们的正确清理

编辑:

另一件要尝试的事情是,假设带有xcode的gcc允许与msvc相同类型的内联汇编程序,则是:

 int Convert(double value)
 {
      int result;
      _asm
      {
          fld value
          push eax
          fistp dword ptr [esp]
          pop eax
          mov [result], eax
      }
      return result;
 } 

这也应该关闭关于您可能得到的缺少返回值的警告。这可能只是因为它更严格地允许您通过编写eax从汇编程序块返回值,而不是msvc。

您的代码适用于Apple gcc 4.2.1:

#include <stdio.h>

static int Convert(double value)
{
     _asm
     {
         fld value
         push eax
         fistp dword ptr [esp]
         pop eax
     }
}

int main(void)
{
    int i = Convert(42.0);

    printf("i = %d\n", i);

    return 0;
}

我的猜测是您无意中编译了64位。查看Xcode中的构建记录,确保在编译此代码时可以看到
-m32
——设置很容易在项目中的某个地方被覆盖。您还可以尝试从命令行构建并运行上面的代码示例,以确保它与您的工具链配合使用。

GCC的语法要求您指定要在程序集编码部分内使用的变量。发布的代码没有这样做,实际上可能是在随机内存上操作,而不是在您期望的变量上操作

此外,除了标准的“在堆栈上传递所有内容”(例如fastcall和尾部递归调用)之外,GCC还可以使用一些调用约定。发布的程序集代码假定所有内容都在堆栈上传递。您的汇编代码所期望的和GCC所做的可能不匹配


user786653答案中的汇编代码避免了这些问题。

在Xcode 4.0.2中对我来说效果很好(带有关于控件到达非void函数末尾的警告)。我在3.2.6中创建了这个项目,当我第一次将它加载到Xcode 4.0.2时,它不会编译。在我将体系结构设置为32位、有效体系结构设置为i386、编译器设置为GCC4.2之后,我最终将其编译。当编译器设置为LLVM GCC 4.2时,它将运行,但函数返回0


为什么要在组装中执行此操作?浮点数a=3.14;int b=*(int*)&a;同样的道理。另外,您传入一个double,但将其转换为32位。@dascandy:这行代码是未定义的行为。这是一个要点。是否使用内联程序集定义的行为?这是一个很好的笑话,Dascandy!旁注:GCC有一个允许不同汇编语言的开关,不是吗?它同时允许AT&T和英特尔语法。@Kerrek SB:你在考虑
gcc-masm=Intel-S
?这(至少在我的机器上)只是将一个
.intel\u语法noprefix
(如我文章中的维基百科链接所述)放在文件的顶部。是的,就是那个。我只是想,当您从其他代码库进行移植,并且不想重写汇编程序部分时,了解这一点可能会很有用。是的,AT&t一开始非常混乱:)(关于这一点,已经很老了。
#include <stdio.h>

static int Convert(double value)
{
     _asm
     {
         fld value
         push eax
         fistp dword ptr [esp]
         pop eax
     }
}

int main(void)
{
    int i = Convert(42.0);

    printf("i = %d\n", i);

    return 0;
}
$ gcc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5666.3~123/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5666) (dot 3)
$ gcc -Wall -m32 -O3 -fasm-blocks convert.c -o convert
convert.c: In function ‘Convert’:
convert.c:14: warning: no return statement in function returning non-void
$ ./convert
i = 42