哪个内联汇编代码对于rdtscp是正确的?

时间:2013-02-09 01:01:07

标签: gcc assembly x86-64 inline-assembly

免责声明:单词无法描述我多少厌恶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,或两者兼有?

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

最好让shiftadd在C ++语句中合并两个32位的一半而不是内联,这样编译器就可以按照它认为合适的方式安排这些指令。

答案 1 :(得分:1)

根据this,此操作破坏了EDX和ECX。您需要将这些寄存器标记为破坏,这是第二个寄存器。顺便说一句,这是你获得上述代码的链接还是在其他地方找到的链接?它还显示了一些其他时间变化,它非常整洁。