免责声明:单词无法描述我多少厌恶AT& T风格的语法
我有一个问题,我希望是由寄存器clobbering引起的。如果没有,我有一个更大的问题。
我使用的第一个版本是
static unsigned long long rdtscp(void)
{
unsigned int hi, lo;
__asm__ __volatile__("rdtscp" : "=a"(lo), "=d"(hi));
return (unsigned long long)lo | ((unsigned long long)hi << 32);
}
我注意到这个版本中没有'破坏'的东西。这是否是一个我不知道的问题...我想这取决于编译器是否内联函数。使用此版本会导致我的问题并不总是可重复的。
我找到的下一个版本是
static unsigned long long rdtscp(void)
{
unsigned long long tsc;
__asm__ __volatile__(
"rdtscp;"
"shl $32, %%rdx;"
"or %%rdx, %%rax"
: "=a"(tsc)
:
: "%rcx", "%rdx");
return tsc;
}
这令人安心,看起来很官方,但就像我说的那样,我的问题并不总是可以重现的,所以我只是试图排除一个可能的问题原因。
我相信第一个版本的原因是它覆盖了以前持有函数参数的寄存器。
什么是正确的...版本1,或版本2,或两者兼有?
答案 0 :(得分:19)
这是将返回TSC并将辅助32位存储到引用参数中的C ++代码
static inline uint64_t rdtscp( uint32_t & aux )
{
uint64_t rax,rdx;
asm volatile ( "rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : : );
return (rdx << 32) + rax;
}
最好让shift
和add
在C ++语句中合并两个32位的一半而不是内联,这样编译器就可以按照它认为合适的方式安排这些指令。
答案 1 :(得分:1)
根据this,此操作破坏了EDX和ECX。您需要将这些寄存器标记为破坏,这是第二个寄存器。顺便说一句,这是你获得上述代码的链接还是在其他地方找到的链接?它还显示了一些其他时间变化,它非常整洁。