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

Question!

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++ ?



Answers

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.

By : Ps0ke


Using the RDTSC instruction directly has some severe drawbacks:

  • The TSC isn't guaranteed to be synchronized on all CPUs, so if your thread/process migrates from one CPU core to another the TSC may appear to "warp" forward or backward in time unless you use thread/process affinity to prevent migration.
  • The TSC isn't guaranteed to advance at a constant rate, particularly on PCs that have power management or "C1 clock ramping" enabled. With multiple CPUs, this may increase the skew (for example, if you have one thread that is spinning and another that is sleeping, one TSC may advance faster than the other).
  • Accessing the TSC directly doesn't allow you to take advantage of HPET.

Using an OS timer interface is better, but still may have some of the same drawbacks depending on the implementation:

Also note that Microsoft Visual C++ doesn't support inline assembly when targeting 64-bit processors, hence the __rdtsc() intrinsic that Virne pointed out.

By : bk1e


#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

By : Virne


This video can help you solving your question :)
By: admin