Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a cross-platform c++ inline assembly language?

I hacked a following code:

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

It works on g++ but not on Visual Studio. How can I port it ? What are the right macros to detect VS / g++ ?

like image 547
Łukasz Lew Avatar asked Apr 21 '09 09:04

Łukasz Lew


2 Answers

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

My inline assembler skills are rusty, but it works like:

__asm
{
// some assembler code
}

But to just use rdtsc you can just use intrinsics:

unsigned __int64 counter;
counter = __rdtsc();

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

like image 155
Virne Avatar answered Sep 21 '22 07:09

Virne


The specific problem OP had aside: I found a way to define a macro that works for both syntax versions:

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

Unfortunately, because the preprocessor strips newlines before macro expansion, you have to surround each assembly statement with this macro.

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

    return x;
}

But please be aware that GCC and clang use AT&T/UNIX assembly synax but MSVC usees Intel assembly syntax (couldn't find any official source though). But fortunately GCC/clang can be configured to use Intel syntax, too. Either use __asm__(".intel_syntax noprefix");/ __asm__(".att_syntax prefix"); (be sure to reset the changes as it will affect all assembly generated from that point on, even the one generated by the compiler from the C source). This would leave us with a macro like this:

#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

Or you can also compile with GCC/clang using the -masm=intel flag, which switches the syntax globally.

like image 31
Philipp Stephan Avatar answered Sep 22 '22 07:09

Philipp Stephan