4

Could someone help me understand the assembler given in https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

It goes like this:

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");

How is it different from:

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

Why do we need shift and or operations and what does rdx at the end do?

EDIT: added what is still unclear to the original question.

  • What does "\n\t" do?
  • What do ":" do?
    • delimiters output/input/clobbers...
  • Is rdx at the end equal to 0?

Just to recap. First line loads the timestamp in registers eax and edx. Second line shifts the value in eax and stores in rdx. Third line ors the value in edx with the value in rdx and saves it in rdx. Fourth line assigns the value in rdx to my variable. The last line sets rdx to 0.

  • Why are the first three lines without ":"?
    • They are a template. First line with ":" is output, second is optional input and third one is optional list of clobbers (changed registers).
  • Is a actually eax and d - edx? Is this hard-coded?

Thanks again! :)

EDIT2: Answered some of my questions...

4

2 回答 2

8
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 位寄存器(有关更多信息,请参阅英特尔系统的编程手册;它是 x86 指令),第二条指令将rdx寄存器向左移动 32位,因此edx它将位于高 32 位而不是低 32 位。
"=a" (msr)会将 的内容eax移入msr(the %0),即移入它的低 32 位,因此总共有edx(高 32 位) 和eax(低 32 位)rdx其中是msr.
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;
}

和:

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

这个,只会给你eaxinto的内容msr

编辑:

1) "\n\t" 是为了让生成的程序集看起来更清晰和无错误,这样你就不会得到类似movl $1, %eaxmovl $2, %ebx
2)最后的 rdx 是否等于 0?左移执行此操作,它删除已经存在的位rdx
3)实际上是eax和d - edx吗?这是硬编码吗?是的,有一个表格描述了哪些字符代表什么寄存器,例如“D”将是rdi,“c”将是ecx......

于 2016-01-15T11:59:18.303 回答
1

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

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

于 2016-01-15T11:57:26.407 回答