15

免责声明:言语无法描述我对 AT&T 风格语法的厌恶程度

我有一个问题,我希望是由寄存器破坏引起的。如果没有,我有一个更大的问题。

我使用的第一个版本是

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

4

2 回答 2

23

这是将返回 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;
}

最好在 C++ 语句中执行shiftadd合并两个 32 位半部分而不是内联,这允许编译器在它认为合适的时候调度这些指令。

于 2013-02-09T01:19:17.417 回答
1

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

于 2013-02-09T01:10:54.643 回答