汇编程序指令:rdtsc

时间:2016-01-15 11:47:09

标签: gcc assembly x86 timestamp rdtsc

有人可以帮我理解https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

中给出的汇编程序

它是这样的:

uint64_t msr;
asm volatile ( "rdtsc\n\t"    // Returns the time in EDX:EAX.
               "shl $32, %%rdx\n\t"  // Shift the upper bits left.
               "or %%rdx, %0"        // 'Or' in the lower bits.
               : "=a" (msr)
               :
               : "rdx");

与以下内容有何不同:

uint64_t msr;
asm volatile ( "rdtsc\n\t"
               : "=a" (msr));

为什么我们需要转移和/或操作以及rdx最终会做什么?

编辑:添加了原始问题尚不清楚的内容。

  • " \ n \ t"办?
  • 做什么":"做?
    • 分隔符输出/输入/ clobbers ...
  • 末尾的rdx是否等于0?

回顾一下。第一行加载寄存器eax和edx中的时间戳。第二行将eax中的值移位并存储在rdx中。第三行将edx中的值与rdx中的值一起使用,并将其保存在rdx中。第四行将rdx中的值赋给我的变量。最后一行将rdx设置为0。

  • 为什么前三行没有":"?
    • 他们是模板。第一行是":"输出,第二个是可选输入,第三个是可选的列表(更改的寄存器)。
  • 实际上是eax和d - edx吗?这是硬编码吗?

再次感谢! :)

EDIT2:回答了我的一些问题......

2 个答案:

答案 0 :(得分:7)

uint64_t msr;
asm volatile ( "rdtsc\n\t"    // Returns the time in EDX:EAX.
               "shl $32, %%rdx\n\t"  // Shift the upper bits left.
               "or %%rdx, %0"        // 'Or' in the lower bits.
               : "=a" (msr)
               :
               : "rdx");

因为rdtsc指令返回edxeax的结果,而不是64位机器上的直接64位寄存器(请参阅intel系统的编程手册了解更多信息)信息;它是x86指令),第二个 指令将rdx寄存器移位到左侧32位,以便edx位于高32位而不是低32位。
"=a" (msr)会将eax的内容移至msr%0),即移至其中的低32位,因此总共有edx(高{32})和eax(低32位)到rdx msr
rdx是一个代表msr C变量的clobber。

类似于在C中执行以下操作:

static inline uint64_t rdtsc(void)
{
    uint32_t eax, edx;
    asm volatile("rdtsc\n\t", "=a" (eax), "=d" (edx));
    return (uint64_t)eax | (uint64_t)edx << 32;
}

uint64_t msr;
asm volatile ( "rdtsc\n\t"
               : "=a" (msr));

这一个,只会将eax的内容提供给msr

修改

1)“\ n \ t”是生成的程序集看起来更清晰,没有错误,因此您不会最终得到movl $1, %eaxmovl $2, %ebx之类的内容。 2)末尾的rdx是否等于0?左移这样做,它会删除rdx中已有的位。
3)实际上是eax和d - edx吗?这是硬编码的吗?是的,有一个表格描述了哪些字符代表哪个寄存器,例如“D”为rdi,“c”为ecx,...

答案 1 :(得分:1)

rdtsc返回一对32位寄存器(EDX和EAX)中的时间戳。第一个片段将它们组合成单个64位寄存器(RDX),映射到msr变量。

第二段是错误的。我不确定会发生什么:要么根本不编译,要么只更新msr变量的一部分。