c - 硬件处理器计数器重置不正确

标签 c assembly x86 msr

我编写了一个程序,用于读取 Intel 芯片上的 APERF/MPERF 计数器(http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf 上的第 2 页)。

这些计数器可通过 readmsr/writemsr 指令进行读取/写入,目前我只是通过 Windows 7 中的设备驱动程序定期读取它们。计数器为 64 位,并且大约随着每个处理器时钟而递增,所以你会期望它们在很长一段时间内溢出,但是当我读取计数器时,它们的值会跳跃,就像它们被另一个程序重置一样。

有什么方法可以追踪哪些程序会重置计数器?是否还有其他原因导致读取不正确的值?我正在使用的相关程序集和相应的C函数附在下面。 rdmsr 的 64 位结果保存到 eax:edx 中,因此为了确保我没有丢失 r_x 寄存器中的任何数字,我多次运行该命令来检查所有数字。

C:

long long test1, test2, test3, test4;
test1 = TST1();
test2 = TST2();
test3 = TST3();
test4 = TST4();
status = RtlStringCbPrintfA(buffer, sizeof(buffer), "Value: %llu %llu %llu %llu\n", test1, test2, test3, test4);

组装:

;;;;;;;;;;;;;;;;;;;
PUBLIC TST1 
TST1 proc
    mov ecx, 231 ; 0xE7
    rdmsr
    ret ; returns rax
TST1 endp

;;;;;;;;;;;;;;;;;;;
PUBLIC TST2 
TST2 proc
    mov ecx, 231 ; 0xE7
    rdmsr
    mov rax, rbx
    ret ; returns rax
TST2 endp

;;;;;;;;;;;;;;;;;;;
PUBLIC TST3 
TST3 proc
    mov ecx, 231 ; 0xE7
    rdmsr
    mov rax, rcx
    ret ; returns rax
TST3 endp

;;;;;;;;;;;;;;;;;;;
PUBLIC TST4 
TST4  proc
    mov ecx, 231 ; 0xE7
    rdmsr
    mov rax, rdx
    ret ; returns rax
TST4 endp

打印出来的结果如下所示,但唯一改变的寄存器是rax寄存器,并且它不会单调增加(可以跳跃):

Value: 312664 37 231 0
Value: 252576 37 231 0
Value: 1051857 37 231 0

最佳答案

我无法弄清楚是什么重置了我的计数器,但我能够确定频率。英特尔文档指出,当一个计数器溢出时,另一个计数器也会溢出。因此,即使计数器不断重置,aperf 和 mperf 的比率仍然代表处理器的频率。

关于c - 硬件处理器计数器重置不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11398912/

相关文章:

对 float 和字符串的输出感到困惑

c - 如何让 autoconf 有条件地使用系统扩展?

c - 覆盖 C 中的返回地址(缓冲区溢出)

linux - 了解汇编代码

基于 c 中的 EBP 从堆栈帧调用函数及其参数

c - 如何使用 C 获取 XML 文件中的根目录

assembly - 如何在arm asm上编写PC相对寻址?

assembly - 扩展编译器以获得自己的汇编输出

linux - 术语 "user space"和 "kernel space"是指物理内存吗?

windows - 试图找出 MASM 语法