我写了一个程序,它读取英特尔芯片上的 APERF/MPERF 计数器( http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol上的第 2 页-3b-part-2-manual.pdf)。
这些计数器可通过 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