汇编程序指令:rdtsc

Let*_*eta 4 x86 assembly gcc 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");
Run Code Online (Sandbox Code Playgroud)

它与以下内容有何不同:

uint64_t msr;
asm volatile ( "rdtsc\n\t"
               : "=a" (msr));
Run Code Online (Sandbox Code Playgroud)

为什么我们需要转移和/或操作以及rdx到底有什么作用?

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

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

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

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

再次感谢!:)

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

小智 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");
Run Code Online (Sandbox Code Playgroud)

因为rdtsc指令返回它的结果在edxeax,代替64位机器上的一个直的64位寄存器(请参阅Intel系统的编程手册的详细信息;它是一个x86指令),则第二指令将rdx寄存器到左侧32这样的位edx将位于高32位而不是低32位.
"=a" (msr)将移动的内容的eaxmsr(的%0),即,进入它的低32位,所以在总你有edx(较高的32位)和eax(低32位)转换成rdxmsr.
rdx是一个代表msrC变量的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;
}
Run Code Online (Sandbox Code Playgroud)

和:

uint64_t msr;
asm volatile ( "rdtsc\n\t"
               : "=a" (msr));
Run Code Online (Sandbox Code Playgroud)

这一次,只会给你的内容eax进入msr.

编辑:

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