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++ ?
它适用于g ++,但不适用于Visual Studio。我该如何移植它?检测VS / g ++的正确宏是什么?
4 个解决方案
#1
#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:
但是要使用rdtsc,你可以使用内在函数:
unsigned __int64 counter;
counter = __rdtsc();
#2
There's a _MSC_VER macro in VC++ that is described as "Microsoft specific" in MSDN and presumably is not defined when code is compiled on other compilers. You can use #ifdef to determine what compiler it is and compile different code for gcc and VC++.
VC ++中有一个_MSC_VER宏,在MSDN中被描述为“特定于Microsoft”,并且可能在代码在其他编译器上编译时未定义。您可以使用#ifdef来确定它是什么编译器,并为gcc和VC ++编译不同的代码。
#ifdef _MSC_VER
//VC++ version
#else
//gcc version
#endif
#3
Using the RDTSC
instruction directly has some severe drawbacks:
直接使用RDTSC指令有一些严重的缺点:
- 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.
TSC不保证在所有CPU上同步,因此如果您的线程/进程从一个CPU核心迁移到另一个CPU核心,TSC可能会向前或向后“扭曲”,除非您使用线程/进程关联来防止迁移。
TSC不能保证以恒定速率前进,特别是在具有电源管理或“C1时钟斜坡”功能的PC上。对于多个CPU,这可能会增加偏斜(例如,如果您有一个正在旋转的线程而另一个正在休眠,则一个TSC可能比另一个更快地前进)。
直接访问TSC不允许您利用HPET。
Using an OS timer interface is better, but still may have some of the same drawbacks depending on the implementation:
使用OS定时器接口更好,但仍可能有一些相同的缺点,具体取决于实现:
- Linux:
clock_gettime()
- Windows:
QueryPerformanceCounter()
Also note that Microsoft Visual C++ doesn't support inline assembly when targeting 64-bit processors, hence the __rdtsc()
intrinsic that Virne pointed out.
另请注意,Microsoft Visual C ++在针对64位处理器时不支持内联汇编,因此Virne指出__rdtsc()内在函数。
#4
The specific problem OP had aside: I found a way to define a macro that works for both syntax versions:
OP没有具体问题:我找到了一种定义适用于两种语法版本的宏的方法:
#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:
但请注意,GCC和clang使用AT&T / UNIX程序集synax,但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
Or you can also compile with GCC/clang using the -masm=intel
flag, which switches the syntax globally.
或者您也可以使用-masm = intel标志使用GCC / clang进行编译,该标志会全局切换语法。
#1
#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:
但是要使用rdtsc,你可以使用内在函数:
unsigned __int64 counter;
counter = __rdtsc();
#2
There's a _MSC_VER macro in VC++ that is described as "Microsoft specific" in MSDN and presumably is not defined when code is compiled on other compilers. You can use #ifdef to determine what compiler it is and compile different code for gcc and VC++.
VC ++中有一个_MSC_VER宏,在MSDN中被描述为“特定于Microsoft”,并且可能在代码在其他编译器上编译时未定义。您可以使用#ifdef来确定它是什么编译器,并为gcc和VC ++编译不同的代码。
#ifdef _MSC_VER
//VC++ version
#else
//gcc version
#endif
#3
Using the RDTSC
instruction directly has some severe drawbacks:
直接使用RDTSC指令有一些严重的缺点:
- 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.
TSC不保证在所有CPU上同步,因此如果您的线程/进程从一个CPU核心迁移到另一个CPU核心,TSC可能会向前或向后“扭曲”,除非您使用线程/进程关联来防止迁移。
TSC不能保证以恒定速率前进,特别是在具有电源管理或“C1时钟斜坡”功能的PC上。对于多个CPU,这可能会增加偏斜(例如,如果您有一个正在旋转的线程而另一个正在休眠,则一个TSC可能比另一个更快地前进)。
直接访问TSC不允许您利用HPET。
Using an OS timer interface is better, but still may have some of the same drawbacks depending on the implementation:
使用OS定时器接口更好,但仍可能有一些相同的缺点,具体取决于实现:
- Linux:
clock_gettime()
- Windows:
QueryPerformanceCounter()
Also note that Microsoft Visual C++ doesn't support inline assembly when targeting 64-bit processors, hence the __rdtsc()
intrinsic that Virne pointed out.
另请注意,Microsoft Visual C ++在针对64位处理器时不支持内联汇编,因此Virne指出__rdtsc()内在函数。
#4
The specific problem OP had aside: I found a way to define a macro that works for both syntax versions:
OP没有具体问题:我找到了一种定义适用于两种语法版本的宏的方法:
#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:
但请注意,GCC和clang使用AT&T / UNIX程序集synax,但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
Or you can also compile with GCC/clang using the -masm=intel
flag, which switches the syntax globally.
或者您也可以使用-masm = intel标志使用GCC / clang进行编译,该标志会全局切换语法。