有人可以帮我理解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最终会做什么?
编辑:添加了原始问题尚不清楚的内容。回顾一下。第一行加载寄存器eax和edx中的时间戳。第二行将eax中的值移位并存储在rdx中。第三行将edx中的值与rdx中的值一起使用,并将其保存在rdx中。第四行将rdx中的值赋给我的变量。最后一行将rdx设置为0。
再次感谢! :)
EDIT2:回答了我的一些问题......
答案 0 :(得分: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");
因为rdtsc
指令返回edx
和eax
的结果,而不是64位机器上的直接64位寄存器(请参阅intel系统的编程手册了解更多信息)信息;它是x86指令),第二个
指令将rdx
寄存器移位到左侧32位,以便edx
位于高32位而不是低32位。
"=a" (msr)
会将eax
的内容移至msr
(%0
),即移至其中的低32位,因此总共有edx
(高{32})和eax
(低32位)到rdx
msr
。
rdx
是一个代表msr
C变量的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));
这一个,只会将eax
的内容提供给msr
。
修改强>
1)“\ n \ t”是生成的程序集看起来更清晰,没有错误,因此您不会最终得到movl $1, %eaxmovl $2, %ebx
之类的内容。
2)末尾的rdx是否等于0?左移这样做,它会删除rdx
中已有的位。
3)实际上是eax和d - edx吗?这是硬编码的吗?是的,有一个表格描述了哪些字符代表哪个寄存器,例如“D”为rdi
,“c”为ecx
,...
答案 1 :(得分:1)
rdtsc
返回一对32位寄存器(EDX和EAX)中的时间戳。第一个片段将它们组合成单个64位寄存器(RDX),映射到msr
变量。
第二段是错误的。我不确定会发生什么:要么根本不编译,要么只更新msr
变量的一部分。