8

我遇到了这段代码,需要了解它在做什么。它似乎只是在声明两个字节然后什么都不做......

uint64_t x;
__asm__ __volatile__ (".byte 0x0f, 0x31" : "=A" (x));

谢谢!

4

4 回答 4

12

这是直接在代码流中生成两个字节(0F 31)。这是一条 RDTSC 指令,它将时间戳计数器读入 EDX:EAX,然后通过输出约束“=A”(x) 将其复制到变量“x”中

于 2009-08-13T17:26:44.277 回答
4

0F 31 是 RDTSC(读取时间戳计数器)指令的 x86 操作码;它将读取的值放入 EDX 和 EAX 寄存器。

__ asm__ 指令不只是声明两个字节,而是将内联汇编放入 C 代码中。据推测,程序有一种方法可以在之后立即使用这些寄存器中的值。

http://en.wikipedia.org/wiki/Time_Stamp_Counter

于 2009-08-13T17:27:08.567 回答
2

它正在插入一个 0F 31 操作码,根据本网站,它是:

0F 31   P1+   f2   RDTSC EAX EDX IA32_T...        Read Time-Stamp Counter 

然后它将结果存储在x变量中

于 2009-08-13T17:29:36.440 回答
1

它是 inline asm forrdtsc,写出机器代码编码以支持不知道助记符的真正古老的汇编程序。

不幸的是,它只能在 32 位代码中正常工作,因为"=A"在 64 位代码中不会将 64 位操作数分成两半。(gcc 手册甚至使用rdtsc了一个例子来说明这一点

编写此代码(使用 gcc -m32 或 -m64 编译为最佳代码)的安全方法是:

#include <stdint.h>
uint64_t timestamp_safe(void)
{
  unsigned long tsc_low, tsc_high;   // not uint32_t: saves a zero-extend for -m64 (but not x32 :/)
  asm volatile("rdtsc"  : "=d"(tsc_high), "=a" (tsc_low));
  return ((uint64_t)tsc_high << 32) | tsc_low;
}

在 32 位代码中,它只是rdtsc/ ret,但在 64 位代码中,它会进行必要的移位/或将两半都放入rax返回值。

在Godbolt 编译器资源管理器上查看它。

于 2016-06-27T17:01:03.387 回答