QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4397|回复: 2
打印 上一主题 下一主题

[转帖]在VC++通过汇编实现获取代码运行时间

[复制链接]
字体大小: 正常 放大
xShandow        

43

主题

1

听众

385

积分

升级  28.33%

该用户从未签到

国际赛参赛者

新人进步奖

跳转到指定楼层
1#
发表于 2004-9-9 11:14 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
如何获得程序或者一段代码运行的时间?你可能说有专门的程序测试工具,确实,不过你也可以在程序中嵌入汇编代码来实现。8 w1 \8 e' ~) q4 R/ v% @
     在Pentium的指令系统中有一条指令可以获得CPU内部64位计数器的值,我们可以通过代码两次获取该计数器的值而获得程序或代码运行的时钟周期数,进而通  X) D: Q5 m; \. Y
<>过你的cpu的频率算出一个时钟周期的时间,从而算出程序运行的确切时间。
, G  b( X2 K/ ^    我们通过指令TDSIC来获得cpu内部计数器的值,指令TDSIC返回值放在EDX:EAX中,其中EDX中存放64位寄存器中高32位的值,EAX存放第32位的值.</P>- Y7 [& e  d8 ?0 ?
<>下面看看实现的代码:
: {( u  f* r! V  e* ~/ q=============================================================================================0 L2 o/ p+ e* Z/ B4 ?6 ~/ b4 j( Q9 D
//用汇编实现获取一段代码运行的时间</P>
6 D7 V. c( p) F. C<>#include&lt;iostream&gt;</P>
) S% V& w6 R7 d! p<>using namespace std;</P># h, x, ^# l6 P: \
<>void GetClockNumber (long high, long low);4 f* y7 X) |. P& K, o, y
void GetRunTime();
& J. @4 l% ~. w  G% H0 ^" a
( l6 C' a+ U7 [+ P7 ~, \3 [int main()
0 }' Q  U- q- n: p8 U2 |{       5 g" o" D$ w% L7 x
7 }, z' S, g! i' k; @
long HighStart,LowStart,HighEnd,LowEnd;
+ Z6 t2 f) F$ ~2 w. B; Q5 F long numhigh,numlow;% Q6 s; H: M* U) U
//获取代码运行开始时cpu内部计数器的值
  d8 V! K2 |0 q __asm              * e; u. A- f6 _) r
{8 {3 c1 `% J2 l' \! C: Q& ^! f7 Q
  RDTSC ' O$ W5 ^" B* h0 }
  mov HighStart, edx
. H6 p5 [7 S7 D; e& z# |  mov LowStart, eax
1 x+ W+ p" D7 y. H6 ]+ d }! `6 J$ B# D& W' b
for(int i= 0; i&lt;100000; i++ )* i8 P6 L" \! [. R. E, t
{
/ t  R2 z$ Q) S* f" p; ]             for(int i= 0; i&lt;100000; i++ )/ V8 {- i' v7 I. [8 I9 y
      {
2 Y, B, h. [; ?$ q2 r       6 C- g, e  U3 o& K( }
      }
$ l: J( {/ N. V* U3 a }" L( p6 b! P$ F; W9 q
//获取代码结束时cpu内部计数器的值,并减去初值
- C, g* e4 [  h( m        __asm# Z; U) n) C* N: {: j$ u7 D5 G3 p0 b6 C
{. w; _. D; L8 Q5 k. ^4 l/ d5 @
  RDTSC) w! T; Z. e) q. c$ B
  mov HighEnd, edx
* B+ g; ?( T# B( `  Mov LowEnd,  eax( Z+ d+ |2 {; p! L' g
  ;获取两次计数器值得差, V. h. M! J! y  h2 O5 Y* v
  sub eax,  LowStart6 {8 l, L/ l. |5 F4 G
  cmp    eax,  0       ; 如果低32的差为负则求返,因为第二次取得永远比第一次的大
( C* A7 l! r. P" `7 i1 R  jg     L1) U1 X  z: k1 w$ A8 V* Z
  neg     eax
6 f5 D% h: n' L  jmp     L2
/ d& ^: h# b" o            L1: mov numlow,  eax
9 d; U2 d5 r% C9 r, c' D8 H; k            L2: sbb edx,  HighStart
# j# o. b! `$ X$ @& D  mov numhigh, edx. J* E0 b$ A- M7 h9 F
  $ {+ I/ e) x5 v6 D' n! p
}
% N! q: d) s! o; k+ L5 x        //把两个计数器值之差放在一个64位的整形变量中4 B* w) `8 Z0 }) ^
        //先把高32位左移32位放在64的整形变量中,然后再加上低32位, d+ i; k2 e5 t& F5 Y
__int64  timer =(numhigh&lt;&lt;32) + numlow;. F7 g+ ^! b( u. F" L
         //输出代码段运行的时钟周期数
+ c; G' G- x6 D# ~6 e         //以频率1.1Gcpu为例,如果换计算机把其中的1.1改乘其它即可,因为相信大家的cpu都应该在1G以上  ^_^ . P7 M- _) \+ j1 c, D! {; H
cout&lt;&lt; (double) (timer /1.1/1000000000) &lt;&lt; endl;+ v* I: k0 K5 v2 j+ p
return 0;
  l& P+ |4 U8 g6 g9 i# }# c}</P>4 `- O" K! O+ W
<>     这样通过一条简单的汇编指令就可以获得程序或一段代码的大概时间,不过并不能得到运行的确切时间,因为即使去掉中间的循环,程序也会有个运行时间,</P>! n2 T1 L- ~, Q- J$ S  |% ~
<>因为在第一次取得计数器的值后,有两条汇编指令mov HighStart, edx       mov LowStart, eax这两条指令当然也有运行时间 ,当然你可以减去这两条指令的运</P>/ B+ u; _7 V3 ~; m& G
<>行时间(在1.1G的机子上是3e-8s),这样会更精确一点。^_^/ B7 F! V$ R/ Q/ }
    如果你要确切知道程序的运行时间,专业的测试软件肯定会更好一点,不过好像一般没有必要获取除非专门的要求的程序。不过能DIY一个也是不错的,不管有</P>3 C' H" H6 \; b* z) a; C
<>没有,最起码你可以学到在VC++中如何嵌入汇编代码以及如何使用32位的寄存器,其实和16位的寄存器一样使用,将来64的也应该一样,只不过位数不同罢了。
2 d" K0 s6 F0 W0 e1 b3 b; \- A^_^</P>
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
413009449        

0

主题

4

听众

43

积分

升级  40%

该用户从未签到

回复

使用道具 举报

黄窗帘        

0

主题

4

听众

28

积分

升级  24.21%

该用户从未签到

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-9-1 14:53 , Processed in 0.489253 second(s), 63 queries .

回顶部