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

Łuk*_*Lew 5 c++ assembly cross-platform

我破解了以下代码:

unsigned long long get_cc_time () volatile {
  uint64 ret;
  __asm__ __volatile__("rdtsc" : "=A" (ret) : :);
  return ret;
}
Run Code Online (Sandbox Code Playgroud)

它适用于 g++,但不适用于 Visual Studio。我怎样才能移植它?检测 VS/g++ 的正确宏是什么?

Vir*_*rne 5

#if defined(_MSC_VER)
// visual c
#elif defined(__GCCE__)
// gcce
#else
// unknown
#endif
Run Code Online (Sandbox Code Playgroud)

我的内联汇编技能很生疏,但它的工作原理是:

__asm
{
// some assembler code
}
Run Code Online (Sandbox Code Playgroud)

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

unsigned __int64 counter;
counter = __rdtsc();
Run Code Online (Sandbox Code Playgroud)

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


Phi*_*han 5

OP 的具体问题放在一边:我找到了一种方法来定义一个适用于两种语法版本的宏:

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

不幸的是,因为预处理器在宏扩展之前去掉换行符,所以你必须用这个宏包围每个汇编语句。

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

    return x;
}
Run Code Online (Sandbox Code Playgroud)

但请注意 GCC 和 clang使用 AT&T/UNIX 汇编语法,但 MSVC 使用 Intel 汇编语法(虽然找不到任何官方来源)。但幸运的是 GCC/clang 也可以配置为使用 Intel 语法。要么使用__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
Run Code Online (Sandbox Code Playgroud)

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