网页快照好东西~ 找回帖子 《小心使用RDTSC》
小心使用RDTSC(很老的知识了 不过偶刚知道 有切身体会啊)前几天下载了Aogo老大的正则表达式库第二版 想学习学习 可一运行就出错~~~
整数溢出 就是被除数太大了 为什么呀
经过分析应该是这里
sub eax,[dwTSC]
sbb edx,[dwTSC+4]
被减数比减数小(众人曰 还用分析吗~~~)
可是 为什么啊 难道时间倒流 后面的时间戳比前面的小 于是写了个程序测试一下
;MASMPlus 代码模板 - 控制台程序
.686
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc
includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
.data
szRDTSCFmt db 'RDTSC: %08X%08XH',0dh,0ah,0
.data?
buffer db MAX_PATH dup(?)
dwTickCount dd ?
dwTSC dd ?
dd ?
.CODE
START:
;invoke StdIn,addr buffer,sizeof buffer
invoke GetTickCount ;TSC 初始值
mov dwTickCount,eax
RDTSC
mov [dwTSC],eax
mov [dwTSC+4],edx
invoke wsprintf,offset buffer,offset szRDTSCFmt,[dwTSC+4],[dwTSC]
invoke StdOut,offset buffer
.while TRUE
invoke Sleep,100h
invoke GetTickCount
push eax
sub eax,dwTickCount
pop dwTickCount
push eax ;压经过的毫秒数
RDTSC
push edx
push eax
sub eax,[dwTSC]
sbb edx,[dwTSC+4]
pop DWORD ptr [dwTSC]
pop DWORD ptr [dwTSC+4]
push eax
push edx
invoke wsprintf,offset buffer,offset szRDTSCFmt,[dwTSC+4],[dwTSC]
invoke StdOut,offset buffer
pop edx
pop eax
mov ecx,1000000
div ecx ;除以1Mhz=1000000hz
.if edx >= 500000 ;四舍五入
inc eax
.endif
mov ecx,1000
mul ecx ;1秒=1000毫秒
pop ecx ;pop出经过的毫秒数
div ecx
invoke wsprintf,addr buffer,CTXT('CPU: %dMHz',0ah,0dh),eax
invoke StdOut,offset buffer
.endw
;暂停显示,回车键关闭
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
end START
只是把Aogo老大的程序掏出一块 变成命令行的 加上循环~~~
也是出错 而且无规律可循 还有 似乎在用调试器单步时就不出错了~~~~
怪哉 怪哉 难道是cpu有问题
RDTSC: 0000234F19F9C494H
CPU: 1924MHz
RDTSC: 0000234F12AAADB0H
又在虚拟机里试 那个是个2003 也是同样错误~~~
于是百度一下 才发现这里大有玄机
原来是双核搞的鬼
核心数量 2
线程数量 2 (最大 2)
名称 Intel Mobile Core 2 Duo T7200
这里 多核cpu调用RDTSC会出现同步问题 会出现时间倒流的情况
解决方法是打一个微软的补丁KB896256 不过好像AMD的也支持的不太好 具体上微软的网站上找吧
其他相关的可以上网上找 偶就不多说了
写这个东西的目的 还是希望大家少用或不用RDTSC 应该用QueryPerformanceCounter 或 QueryPerformanceFrequency 这样就不会有时间倒流的问题了
呵呵 其实这都是老东西了 不过偶敢用双核的机子 才刚刚有这些体验
不过 随着双核的普及 这些问题也得多考虑啊
当然 如果硬要那个程序正常运行 只要设置它的亲缘性 就是任务管理器里的关系设置 就行了
编程的解决方法 看《Windows核心编程》第7章 线程的调度、优先级和亲缘性