如何制作跨平台的c ++内联汇编语言?

时间:2009-04-21 09:50:52

标签: c++ cross-platform assembly

我破解了以下代码:

unsigned long long get_cc_time () volatile {
  uint64 ret;
  __asm__ __volatile__("rdtsc" : "=A" (ret) : :);
  return ret;
}

它适用于g ++但不适用于Visual Studio。 我该如何移植它? 检测VS / g ++的正确宏是什么?

4 个答案:

答案 0 :(得分:3)

#if defined(_MSC_VER)
// visual c
#elif defined(__GCCE__)
// gcce
#else
// unknown
#endif

我的内联汇编程序技能很生疏,但它的工作方式如下:

__asm
{
// some assembler code
}

但是只使用 rdtsc ,你可以使用内在函数:

unsigned __int64 counter;
counter = __rdtsc();

http://msdn.microsoft.com/en-us/library/twchhe95.aspx

答案 1 :(得分:2)

VC ++中有一个_MSC_VER宏,在MSDN中被描述为“Microsoft特定”,并且可能在其他编译器上编译代码时未定义。您可以使用#ifdef来确定它是什么编译器,并为gcc和VC ++编译不同的代码。

#ifdef _MSC_VER
    //VC++ version
#else
    //gcc version
#endif

答案 2 :(得分:2)

直接使用RDTSC指令有一些严重的缺点:

  • 不保证TSC在所有CPU上同步,因此如果您的线程/进程从一个CPU核心迁移到另一个CPU核心,TSC可能会向前或向后“扭曲”,除非您使用线程/进程亲和性防止迁移。
  • 不保证TSC以恒定速率前进,特别是在启用了电源管理或“C1时钟斜坡”的PC上。使用多个CPU时,这可能会增加偏斜(例如,如果您有一个正在旋转的线程而另一个正在休眠,则一个TSC可能比另一个更快)。
  • 直接访问TSC不允许您利用HPET

使用OS定时器接口更好,但仍可能有一些相同的缺点,具体取决于实现:

另请注意,Microsoft Visual C ++在定位64位处理器时不支持内联汇编,因此Virne指出了__rdtsc()内在函数。

答案 3 :(得分:2)

OP没有具体问题:我找到了一种定义适用于两种语法版本的宏的方法:

#ifdef _MSC_VER
#   define ASM(asm_literal) \
        __asm { \
            asm_literal \
        };
#elif __GNUC__ || __clang__
#   define ASM(asm_literal) \
        "__asm__(\"" \
            #asm_literal \
        "\" : : );"
#endif

不幸的是,因为预处理器strips newlines before macro expansion,你必须用这个宏包围每个汇编语句。

float abs(float x) {
    ASM( fld     dword ptr[x] );
    ASM( fabs                 );
    ASM( fstp    dword ptr[x] );

    return x;
}

但请注意GCC和clang use AT&T/UNIX assembly synax但是MSVC使用英特尔汇编语法(虽然找不到任何官方来源)。但幸运的是,GCC / clang也可以是configured to use Intel syntax。使用__asm__(".intel_syntax noprefix"); / __asm__(".att_syntax prefix");(确保重置更改,因为它会影响从该点生成的所有程序集,甚至是编译器从C源生成的那个) )。这将给我们留下这样一个宏:

#ifdef _MSC_VER
#   define ASM(asm_literal) \
        __asm { \
            asm_literal \
        };
#elif __GNUC__ || __clang__
#   define ASM(asm_literal) \
        "__asm__(\".intel_syntax noprefix\");" \
        "__asm__(\"" \
            #asm_literal \
        "\" : : );" \
        "__asm__(\".att_syntax prefix\");"
#endif

或者您也可以使用-masm=intel标志使用GCC / clang进行编译,该标志会全局切换语法。