为什么简单的内联汇编功能在GCC中不能正常工作?

时间:2011-08-17 14:10:49

标签: 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
         push eax
         fistp dword ptr [esp]
         pop eax
     }

// The returned value is insane
}

4 个答案:

答案 0 :(得分:8)

  

幸运的是,更复杂的汇编函数工作正常[...]

这些也是内联汇编功能吗?因为GCC对内联汇编程序使用completely different语法。您可以使语法看起来更熟悉,请参阅wikipedia

1     int Convert(double value) 
2     {   
3         int result; 
4         __asm__ __volatile__ ( 
5             "fist %0\n\t" 
6             : "=m" (result) 
7             : "t" (value) 
8             );          
9         return result; 
10     }   

我是怎么做的。 =m指定我们想要一个内存操作数来存储结果(我们不希望寄存器fist不能用于那些)。 t指定值在堆栈顶部传递,这也确保了我们的正确清理。

编辑:

尝试另一件事,假设gcc与xcode允许与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来从汇编程序块返回值更严格。

答案 1 :(得分:2)

使用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;
}


$ 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

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

答案 2 :(得分:1)

GCC的语法要求您指定要在汇编编码部分中使用的变量。发布的代码不会这样做,实际上可能是在随机内存上运行而不是您期望的变量。

此外,GCC还具有使用除标准“传递堆栈中的所有内容”之外的调用约定的能力(例如,fastcall和尾递归调用)。发布的汇编代码假定所有内容都在堆栈上传递。您的汇编代码期望与GCC正在做什么之间可能不匹配。

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

答案 3 :(得分:0)

在Xcode 4.0.2中它对我来说很好(有关控件到达非void函数结束的警告)。我在3.2.6中创建了项目,当我第一次将它加载到Xcode 4.0.2中时,它无法编译。在我将架构设置为32位,有效架构设置为i386,编译器设置为GCC 4.2后,我终于将其编译。将编译器设置为LLVM GCC 4.2,它会运行,但函数返回0.

Compiler set to LLVM GCC 4.2 Compiler set to GCC 4.2