有人可以帮助我了解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”有什么作用?
“:”做什么?


分隔符输出/输入/分隔符...

最后的rdx等于0吗?


只是回顾一下。第一行将时间戳加载到寄存器eax和edx中。第二行将值转换为eax并存储在rdx中。第三行将edx中的值与rdx中的值进行运算,然后将其保存在rdx中。第四行将rdx中的值分配给我的变量。最后一行将rdx设置为0。


为什么前三行没有“:”?


它们是模板。输出第一行带有“:”,第二行是可选输入,第三行是Clobbers(已更改的寄存器)的可选列表。

实际上是eax和d-edx吗?这是硬编码的吗?


再次感谢! :)

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

最佳答案

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位)到rdxmsr中。
rdx是一个表示msr C变量的内容。

类似于在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,...

08-16 09:46