【问题标题】:What is this x86 inline assembly doing?这个 x86 内联汇编在做什么?
【发布时间】:2010-11-19 09:23:00
【问题描述】:

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

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

谢谢!

【问题讨论】:

  • 有趣。我已经很久没有看过这些了,我不确定。您可以指定正在使用的汇编程序。我不知道这是否设置了“x”的内容、地址或两者(!)。如果 x 指向一个内存映射端口,由设备异步更新,因此是“volatile”关键字,我不会感到惊讶。我想,真正做这件事的人很快就会出现。
  • 打赌你希望原来的程序员使用 cmets!
  • 最简单的方法:编译然后反汇编。

标签: c assembly x86 inline-assembly


【解决方案1】:

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

【讨论】:

  • 啊好吧!!并且“=A”(x)语法(我正在使用 gcc4.1)一起使用 %eax 和 %edx - 它可以在 x86_64 架构上工作吗?我想是的,但我对组装了解不多。
  • 是——“A”约束意味着在 i386 和 x86_64 gcc 机器描述中的 EDX:EAX 寄存器对中的 64 位值
  • @MK。和 Chris:不,在 64 位代码中,给定 "=A" 约束的 uint64_t 实际上只会选择 raxrdx 之一,就像您使用 "=ad" 一样。它不会为您将值分成相等的两半 :(This version that ORs together the low and high half 编译为 -m32 和 -m64 的最佳代码,因为在 32 位代码中 OR 优化掉了。
  • @PeterCordes:它曾经在旧版本的 gcc 中工作,但我猜他们在最近的版本中打破了A 约束。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    它正在插入一个 0F 31 操作码,根据this site 是:

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

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

    【讨论】:

      【解决方案4】:

      它是内联 asm for rdtsc,编写了机器代码编码以支持不知道助记符的非常古老的汇编程序。

      不幸的是,它只能在 32 位代码中正常工作,因为 "=A" 不会在 64 位代码中将 64 位操作数分成两半。 (gcc manual even uses rdtsc an an example to illustrate this)

      使用 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 compiler explorer 上查看。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-02
        • 1970-01-01
        • 2019-11-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-05
        • 1970-01-01
        相关资源
        最近更新 更多