有人知道可以用哪些x86指令来测量时间吗?引发任务切换的计时器是否可被软件访问?
有人知道可以用哪些x86指令来测量时间吗?引发任务切换的计时器是否可被软件访问?
在x86平台上测量时间的方法:
实时时钟 - 操作系统中时间和日期的来源。精确到1秒。标准PC中唯一可以用于测量绝对时间的时间源。
8254计数器/定时器 - 一种标准计数器/定时器芯片,自PC产生以来一直存在于主板上(现在是芯片组内的一个功能块)。这是IRQ0的传统来源,它在大多数旧操作系统中执行任务切换。
RDTSC汇编指令 - 计算CPU时钟周期数。详情请见Anon ymous发布的答案。这是x86上可找到的最高级别的时间源。但是,它在准确性方面有一些注意事项。如果您正在写汇编语言,这也是最方便的选项。
RDTSCP汇编指令 - 类似于RDTSC,但是是串行化的,这解决了RDTSC的一些准确性问题。只能在最新的处理器上找到。
HPET - 在Core Duo时代的PC上引入。旨在替代老旧的8254。现代操作系统将使用它作为任务调度中断(Vista及更高版本)。
芯片组中的专有定时器 - 一些芯片组内置有用于电源管理和多媒体功能的特殊定时器。如果您正在处理固定功能嵌入式系统而不是通用PC,则有时可以占用这些定时器。
请注意,这些选项并非都适用于您,具体取决于您的操作系统和硬件。如果您正在运行现代操作系统(Windows、Linux),它将控制8254/HPET以满足其自身的定时需求,因此它们对您来说将不可用。
在现代操作系统下,最好使用操作系统提供的定时功能。如果您尝试自己编写定时功能,您可能会遇到许多问题,而操作系统开发人员已经解决了这些问题。(注意,操作系统可能提供多个定时功能。请选择适合您应用程序的那一个。)
rdtsc
指令。只需将当前值减去先前值即可计算时间差。unsigned long long int rdtsc(void)
{
unsigned long long int x;
unsigned a, d;
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
}
rdtscp
的处理器可以处理情况(1)。 - JAB这里有一个可调用FORTRAN例程:
汇编指令 RDTSC 返回一个64位整数,该整数表示自某个时刻以来CPU时钟计数的数量。如果你的FORTRAN拥有64位整数,则参数KOUNT只需声明为INTEGER*8。否则,将其声明为两个32位INTEGER*4数组。
因此,在您的FORTRAN程序中,您可以这样写:
CALL TIMERR(KOUNT)
在开始时,保存KOUNT的值,然后在结束时重复。然后减去这两个64位值以确定经过的时间。 通常我只会减去两个较低的字,因为我计时的时间通常少于2^32个系统时钟
它也可以从C中调用,但我不会说C。
; C This assembler routine looks to FORTRAN like this:
; SUBROUTINE TIMERR(KOUNT)
; INTEGER*4 KOUNT(2); or INTEGER*8 KOUNT
; ...get a 64-but system time value into KOUNT......
; RETURN
; END
;
.Code
_TIMERR@4: RDTSC
Push Eax
Push Ecx
Push Edx
Mov Ecx, [Esp + 16]
Mov [Ecx], Eax
Mov [Ecx + 4], Edx
Pop Edx
Pop Ecx
Pop Eax
Ret 4