2013-02-09 89 views
10

免责声明:无法用言语形容我有多讨厌AT & T型语法哪个内联汇编代码对于rdtscp是正确的?

我有,我希望是由寄存器重挫造成的问题。如果不是,我有一个更大的问题。

我使用的第一个版本是

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或两者兼而有之?

+7

分享你对语法的讨厌。当我到达这一点时,我寻找编译器的内部函数,或者只是把函数放在一个.s文件中,然后自己将它们组合起来...... – 2013-02-09 01:04:55

+0

@MichaelDorgan不幸的是VC++提供了一个可爱的内在的gcc。 – James 2013-02-09 01:07:10

+8

+1只是'憎恨AT&T风格的语法' – 2013-02-09 09:05:28

回答

18

这里的C++代码,将返回TSC和存储辅助32位为参考参数

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; 
} 

这是更好地做shiftadd在C++中的语句合并这两个32位的一半,而比inline,这允许编译器安排这些指令,因为它认为合适。

+0

这不也是clobber ECX吗?如果不是,我会删除我的答案,并称你的好。 – 2013-02-09 01:21:48

+2

是的,“= c”规范告诉编译器ECX将保存输出,这意味着它被破坏 – amdn 2013-02-09 01:22:50

+0

谢谢。第一个版本并没有将'ecx'标记为被破坏。该寄存器初始地保存了一个参数值,该参数值在一个条件中使用,如果失败,该条件称为“std :: terminate()”。当这种情况发生时,情况显然是在检查错误的东西! – James 2013-02-09 16:25:09

1

根据this,此操作使EDX和ECX变得臃肿。你需要将这些寄存器标记为第二个所做的操作。顺便说一句,这是你有上面的代码的链接,或者你在别处找到它吗?它也显示了一些其他的时间变化,以及相当整洁。

+0

错误的指令。它是'rdtscp',而不是'rdtsc',并且任何输出已知会被破坏,因此不需要列出。问题是'rdtscp' *也会销毁ecx,版本2标记为破坏版本,但版本1不会。 – ughoavgfhw 2013-02-09 01:13:56

+0

因此,我们为他提供了一个答案。我会清理它... – 2013-02-09 01:14:54

+0

在这里留下这个为其他SO链接可能有用 - 虽然上面的答案更好。 – 2013-02-09 01:25:15

2

我认为你可以非常安全地参考this document,不仅要验证,而且要更深入地分析一下RDTSCRDTSCP的准确性。

我希望这会有所帮助。