2012-09-01 36 views
4

有谁知道可用于测量时间的x86指令吗? 定时器是否导致软件可访问任务切换?x86处理器中的时间源

+1

你想在机器代码级别上做到这一点?有一个硬件中断和访问定时器的一些端口地址。然而,现在我已经15年了解了这一点。 – JohnB

+0

最小PIT例如:https://github.com/cirosantilli/x86-bare-metal-examples/blob/9a24f92f36a45abb3f8c37aafc0c3ee9b15563ab/in_pit.S#L2,最小RTC例如:https://github.com/cirosantilli/x86-bare - 金属-例子/ BLOB/9a24f92f36a45abb3f8c37aafc0c3ee9b15563ab/in_rtc.S –

回答

2

您可以使用rdtsc。只需从当前值中扣除以前的值以计算时差。

将处理器的时间戳计数器(一个 64位MSR)的当前值加载到EDX:EAX寄存器中。将EDX寄存器与MSR的高位32位一起加载 ,并将EAX寄存器与低位32位一起加载 。 (在支持英特尔64 架构的处理器中的每个RAX和RDX的高阶32位被 清零。)

This is a C code which implements this instruction: -

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);; 
} 
+0

注意RDTSC有一些限制可能会影响精度:(1)它不是序列化,并可能会受到CPU流水线的内容。 (2)由于电源管理,Intel Turbo Boost或Thermal Throttling,CPU频率可能会波动。 (3)在多CPU /多核系统中,哪个内核执行了该指令? –

+0

@msemack电流(2016)与'rdtscp'把手壳体处理器(1),显然。 – JAB

9

的方法来测量的时间上的x86平台:

  • 实时时钟 - 您的操作系统的时间和日期的来源。 1秒精度。标准PC中唯一可用于测量绝对时间的时间源。

  • 8254 Counter/Timers - 一种标准的计数器/定时器芯片,自PC诞生以来就已经出现在主板上(现在是芯片组中的功能模块)。这是IRQ0的传统来源,它是在大多数较老的操作系统中执行任务切换的计时器中断。

  • RDTSC汇编指令 - 计数CPU时钟周期。查看答案Anon ymous发布了一些使用细节。几乎是您可以在x86上找到时间源的最高级别的精度。但是,它有一些准确性问题。如果您在装配中书写,也是最方便的选择。

  • RDTSCP汇编指令 - 与RDTSC类似,但是是序列化的,它解决了RDTSC的一些准确性问题。只能在最新的处理器上找到。

  • HPET - 介绍围绕Core Duo时代的个人电脑。旨在取代古老的8254.现代操作系统将使用它作为他们的任务调度中断(Vista和更高版本)

  • 芯片组中的专有计时器 - 某些芯片组内置专用计时器,用于电源管理和多媒体功能。假设您正在处理固定功能嵌入式系统而不是通用PC,您有时可以为这些应用程序指定这些应用程序。

请注意,根据您的操作系统和硬件,并非所有这些选项都可用。如果您正在使用现代操作系统(Windows,Linux)运行,它将根据自己的时间需求控制8254/HPET,因此它们将不可用。

在现代操作系统下,通常最好使用操作系统提供的定时功能。如果您尝试使用它,操作系统开发人员可能已经解决了许多您将自行遇到的问题。 (请注意,操作系统可能提供多种定时功能,请选择适合您应用的功能。)

0

这里是一个FORTRAN调用程序,做它:

汇编指令RDTSC返回一个64位整数这是自今年点 时钟计数CPU的数量。如果您的FORTRAN有64位整数,参数 KOUNT只是声明为INTEGER * 8。否则,声明它是两个32位整数数组* 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 
[email protected]: 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