汇编指令:rdtsc
Assembler instruction: 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 , %%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));
为什么我们需要shift和or操作,最后的rdx是做什么的?
编辑:添加了对原始问题仍不清楚的内容。
- “\n\t”有什么作用?
- “:”是做什么的?
- 定界符output/input/clobbers...
- 最后的rdx是否等于0?
只是回顾一下。第一行将时间戳加载到寄存器 eax 和 edx 中。第二行将 eax 中的值移位并存储在 rdx 中。第三行将 edx 中的值与 rdx 中的值进行 OR 运算,并将其保存在 rdx 中。第四行将 rdx 中的值分配给我的变量。最后一行将 rdx 设置为 0.
- 为什么前三行没有“:”?
- 它们是模板。第一行带有“:”的是输出,第二行是可选输入,第三行是可选的 clobbers(更改的寄存器)列表。
- a 实际上是 eax 和 d - edx 吗?这是硬编码的吗?
再次感谢! :)
EDIT2:回答了我的一些问题...
rdtsc
returns 一对 32 位寄存器(EDX 和 EAX)中的时间戳。第一个片段将它们组合成单个 64 位寄存器 (RDX),该寄存器映射到 msr
变量。
第二个片段是错误的。我不确定会发生什么:要么根本不编译,要么只更新 msr
变量的一部分。
uint64_t msr;
asm volatile ( "rdtsc\n\t" // Returns the time in EDX:EAX.
"shl , %%rdx\n\t" // Shift the upper bits left.
"or %%rdx, %0" // 'Or' in the lower bits.
: "=a" (msr)
:
: "rdx");
因为 rdtsc
指令 returns 它的结果是 edx
和 eax
,而不是 64 位机器上的直接 64 位寄存器(参见intel 系统的编程手册了解更多信息;它是一条 x86 指令),第二
指令将 rdx
寄存器向左移动 32 位,以便 edx
位于高 32 位而不是低 32 位。
"=a" (msr)
会将 eax
的内容移动到 msr
(%0
),即移动到它的低 32 位,所以总共有 edx
(高 32 位)和 eax
(低 32 位)到 rdx
即 msr
.
rdx
是一个 clobber,它将代表 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" 是为了使生成的程序集看起来更清晰 error-free,这样你就不会得到像 movl , %eaxmovl , %ebx
这样的东西
2)末尾的rdx是否等于0?左移就是这样做的,它去掉了已经在rdx
.
中的位
3) a实际上是eax和d - edx吗?这是hard-coded吗?是的,有一个table描述什么字符代表什么寄存器,例如"D" 将是 rdi
,"c" 将是 ecx
,...
谁能帮我理解 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
中给出的汇编程序它是这样的:
uint64_t msr;
asm volatile ( "rdtsc\n\t" // Returns the time in EDX:EAX.
"shl , %%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));
为什么我们需要shift和or操作,最后的rdx是做什么的?
编辑:添加了对原始问题仍不清楚的内容。
- “\n\t”有什么作用?
- “:”是做什么的?
- 定界符output/input/clobbers...
- 最后的rdx是否等于0?
只是回顾一下。第一行将时间戳加载到寄存器 eax 和 edx 中。第二行将 eax 中的值移位并存储在 rdx 中。第三行将 edx 中的值与 rdx 中的值进行 OR 运算,并将其保存在 rdx 中。第四行将 rdx 中的值分配给我的变量。最后一行将 rdx 设置为 0.
- 为什么前三行没有“:”?
- 它们是模板。第一行带有“:”的是输出,第二行是可选输入,第三行是可选的 clobbers(更改的寄存器)列表。
- a 实际上是 eax 和 d - edx 吗?这是硬编码的吗?
再次感谢! :)
EDIT2:回答了我的一些问题...
rdtsc
returns 一对 32 位寄存器(EDX 和 EAX)中的时间戳。第一个片段将它们组合成单个 64 位寄存器 (RDX),该寄存器映射到 msr
变量。
第二个片段是错误的。我不确定会发生什么:要么根本不编译,要么只更新 msr
变量的一部分。
uint64_t msr;
asm volatile ( "rdtsc\n\t" // Returns the time in EDX:EAX.
"shl , %%rdx\n\t" // Shift the upper bits left.
"or %%rdx, %0" // 'Or' in the lower bits.
: "=a" (msr)
:
: "rdx");
因为 rdtsc
指令 returns 它的结果是 edx
和 eax
,而不是 64 位机器上的直接 64 位寄存器(参见intel 系统的编程手册了解更多信息;它是一条 x86 指令),第二
指令将 rdx
寄存器向左移动 32 位,以便 edx
位于高 32 位而不是低 32 位。
"=a" (msr)
会将 eax
的内容移动到 msr
(%0
),即移动到它的低 32 位,所以总共有 edx
(高 32 位)和 eax
(低 32 位)到 rdx
即 msr
.
rdx
是一个 clobber,它将代表 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" 是为了使生成的程序集看起来更清晰 error-free,这样你就不会得到像 movl , %eaxmovl , %ebx
这样的东西
2)末尾的rdx是否等于0?左移就是这样做的,它去掉了已经在rdx
.
中的位
3) a实际上是eax和d - edx吗?这是hard-coded吗?是的,有一个table描述什么字符代表什么寄存器,例如"D" 将是 rdi
,"c" 将是 ecx
,...