home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / ALIB40.ZIP / ALIB4B.ZIP / TIMER.ASM < prev    next >
Encoding:
Assembly Source File  |  1997-12-20  |  11.3 KB  |  485 lines

  1. ;**************************** TIMER.ASM *********************************
  2. PAGE  70,132
  3. comment 
  4.                              TIMER
  5.                              -----
  6.  
  7.      Purpose:
  8.      --------
  9.  
  10.      TIMER is a sample program to show how the timer funcitons can
  11.      be used.  The unmodified program will time the execution of
  12.      programs, but it can be modified to time code segments.
  13.  
  14.      Using TIMER
  15.      ----------
  16.  
  17.      To time a program, type "TIMER <program name>"<Enter>
  18.      TIMER will execute the program and display the elapsed
  19.      time when the program exits.
  20.  
  21.      Compiling
  22.      ---------
  23.  
  24.      The commands needed to build TIMER.EXE using MASM are:
  25.         masm TIMER;
  26.         link TIMER,TIMER,,alib.lib;
  27. 
  28.  
  29. ;----------------------------------------------------------------------------
  30. .xlist
  31.     include  mac.inc
  32.     include  common.inc
  33.     extrn    library_setup:far
  34.     extrn    library_terminate:far    
  35.     extrn    spawn_dos:far    
  36. ;    extrn    calibrate_timer:far
  37. ;    extrn    start_timer:far
  38. ;    extrn    read_timer:far
  39. ;    extrn    convert_timer:far
  40. ;    extrn    display_timer:far
  41. .list
  42.     
  43. ;------------------------------------------------------------------------------
  44. code        segment para public 'CODE'
  45.         assume    cs:code, ds:code
  46. ;-----------------------------------------------------------------------------
  47.  
  48. stacksize    equ    1024
  49.     db    stacksize dup (0)
  50. stack_    label    word
  51. ;
  52. pspseg        dw    0        ;program segment prefix
  53. ;-----------------------------------------------------------------------------
  54. start:    cli
  55.     mov    cs:pspseg,es    ;save PSP segment
  56.     mov    ax,cs        ;get CODE segment
  57.     mov    ss,ax
  58.     mov    ds,ax
  59.     mov    es,ax
  60.     mov    sp,offset stack_
  61.     sti
  62.     
  63. ; next, release memory beyond the end of the program
  64. ; The  definition for ZSEG marks the
  65. ; end of the program's code, data and stack area.
  66. ; When linking be sure ZSEG is at the end of the program.
  67.  
  68.     mov    ax,zseg
  69.  
  70.     mov    bx,cs:pspseg        ;
  71.     mov    es,bx
  72.     sub    bx,ax
  73.     neg    bx            ; size of program in paragraphs
  74.     mov    ah,4Ah            ; resize memory block
  75.     int    21h
  76.  
  77.     mov    ax,cs
  78.     mov    es,ax
  79. ;
  80. ; check if enough memory free to run program
  81. ;
  82.     mov    ax,pspseg        ;pass psp segment to setup
  83.     mov    bx,0            ;number of floating point variables
  84.     call    library_setup
  85. ;
  86. ; We want to call SPAWN_DOS which is not compatable with the memory
  87. ; manager, so we will remove it from memory.  We needed to call
  88. ; library setup origionally, to setup the library data area.
  89. ;
  90.     mov    ax,1
  91.     call    library_terminate
  92.  
  93.     call    calibrate_timer
  94.     call    start_timer
  95. ;
  96. ; note: for code timing it will be necessary to comment out the "jcxz"
  97. ;       instruction above, then place code below.
  98. ;
  99. ; **** place code to be timed here ****    
  100.  
  101. ;        mov    cx,100
  102. ;loopx:
  103. ;        mov    al,0ffh
  104. ;        mov    si,offset temp
  105. ;
  106. ;    push   ax
  107. ;    aam                      ;convert byte to bcd
  108. ;    push   ax
  109. ;    mov    ah,al
  110. ;    aam
  111. ;    or     ax,3030h          ;add in ascii
  112. ;    mov    byte ptr [si],ah
  113. ;    mov    byte ptr [si+1],al
  114. ;    pop    ax
  115. ;    or     al,30h
  116. ;    mov    byte ptr [si+2],al
  117. ;    pop    ax
  118. ;    loop    loopx
  119. ;    jmp    continue
  120.  
  121. ; SI buff addr, 
  122. ;
  123. ; The following code can be used if timing a program.  Example:
  124. ;                             Timer program.exe
  125. ; It should be removed if doing code timing and a look used as
  126. ; is shown above.
  127. ;
  128.     mov    ax,cs:pspseg
  129.     mov    ds,ax
  130.     mov    es,ax
  131.     mov    si,81h
  132.     call    spawn_dos        ;execute program to be timed
  133.  
  134. continue:
  135. ; **** end of code to be timed ****
  136.  
  137.     call    read_timer
  138.     call    convert_timer
  139.     call    display_timer        
  140.  
  141. exit2:    mov    ax,4C00h
  142.     int    21h
  143. ;---------------------------
  144.             
  145. code        ends
  146.     
  147. ;-------------------------------------------------------------------------
  148. ;
  149. ; This segment definition is needed so linker will put the LIBSEG here
  150. ; before the ZSEG.  We want ZSEG to be last so memory allocation will
  151. ; work correctly.
  152. ;
  153. LIBSEG           segment byte public 'LIB'
  154. LIBSEG    ENDS
  155.     PAGE    66,132
  156. ;******************************** TIME7.ASM  *********************************
  157. LIBSEG           segment byte public "LIB"
  158.         assume cs:LIBSEG , ds:LIBSEG
  159. ;----------------------------------------------------------------------------
  160.     include    mac.inc
  161.     extrn    word_to_dec_stdout:far
  162.     extrn    dword_to_dec_stdout:far
  163.     extrn    stdout_string:far
  164.     extrn    quad_multiply1:far
  165.     extrn    quad_divide:far
  166. ;
  167. ; General information.  This collection of timer functions use the
  168. ; 8243 timer.  The 8253 has three timers, and timer 0 is used to
  169. ; keep the system clock (attached to interrupt 8) current.  We will
  170. ; also use timer 0.  The timer 0 is accessed at port 43h (commands) and
  171. ; port 40h (data).  One timer tick is roughly 840 nano secods.
  172. ;             
  173. timer_low    equ    046ch
  174. timer_mode    equ    43h
  175. timer0        equ    40h
  176.  
  177. comment 
  178. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MISC   )
  179. ;START_TIMER - start high resolution timer
  180. ;  inputs:  none
  181. ;  output:  none
  182. ; note:  the maximum time which can be measured is one hour.  code
  183. ;        fragments can be timed accuratly up to 55ms.  Programs
  184. ;        can be timed for longer periods, but interrupts have to
  185. ;        be enabled.  It is usually best to disable interrupts
  186. ;        while timing short code fragments.  For program timing
  187. ;        the reported time will include the time required to
  188. ;        service interrupts.
  189. ;
  190. ; note:  The timer functions are usually called in the following order
  191. ;           call  calibrate_timer
  192. ;           call  start_timer
  193. ;           (timed program or code here)
  194. ;           call  read_timer
  195. ;           call  convert_timer
  196. ;           call  display_timer
  197. ;
  198. ; note:  See sample program TIMER.ASM for usage hints.
  199. ;* * * * * * * * * * * * * *
  200. 
  201.     public    start_timer
  202. start_timer    proc    far
  203.     apush    ax,dx,ds
  204.     pushf
  205.     cli
  206. ;
  207. ; initialize the 8253 to count down max count of 65536 by setting zero
  208. ;
  209.     mov    al,00110100b        ;select mode
  210.     out    timer_mode,al        ;request mode
  211.     call    delay
  212.     sub    ax,ax            ;starting count
  213.     out    timer0,al
  214.     call    delay
  215.     out    timer0,al
  216. ;
  217. ; wait for timer tick before starting
  218. ;
  219.     sti
  220.     call    delay
  221.     in    al,timer0
  222.     mov    ah,al
  223. twait:    call    delay
  224.     in    al,timer0
  225.     cmp    al,ah
  226.     je    twait
  227.     call    delay
  228. ;
  229. ;wait for interrupt
  230. ;
  231.     sub    dx,dx
  232.     mov    ds,dx            ;point at seg 0
  233.     mov    dx,word ptr ds:[timer_low]
  234. ilop:    mov    ax,word ptr ds:[timer_low]
  235.     cmp    ax,dx
  236.     je    ilop
  237. ;
  238. ; restart the timer back at count of zero again.
  239. ;
  240.     mov    al,00110100b        ;select mode
  241.     out    timer_mode,al        ;request mode
  242.     call    delay
  243.     sub    ax,ax            ;starting count
  244.     out    timer0,al
  245.     call    delay
  246.     out    timer0,al
  247. ;
  248. ; get the current bios time of day
  249. ;
  250.     mov    ax,word ptr ds:[timer_low]
  251.     mov    cs:interrupt_count,ax
  252.     popf
  253.     apop    ds,dx,ax
  254.     retf
  255. start_timer    endp
  256.  
  257. delay:    jmp    d1
  258. d1:    jmp    d2
  259. d2:    jmp    d3
  260. d3:    jmp    d4
  261. d4:    nop
  262.     push    ax
  263.     pop    ax
  264.     jmp    d5
  265. d5:    push    ax
  266.     pop    ax
  267.     jmp    d6
  268. d6:    push    ax
  269.     pop    ax
  270.        ret
  271.  
  272. comment 
  273. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MISC   )
  274. ;read_timer - read high resolution timer
  275. ;  inputs:  none
  276. ;  output:  dx,ax = total 8253 timer ticks at rate of 1,193,182 per second
  277. ;           
  278. ;* * * * * * * * * * * * * *
  279. 
  280.     public    read_timer
  281. read_timer    proc    far
  282.     apush    ds,es
  283.     pushf
  284.     cli
  285.     mov    ax,cs
  286.     mov    ds,ax
  287.     xor    ax,ax
  288.     mov    es,ax
  289. ;
  290. ; stop timer by setting mode to zero
  291. ;
  292.     out    timer_mode,al    ;timer interrupts off
  293.     call    delay
  294.     in    al,timer0
  295.     call    delay
  296.     mov    ah,al
  297.     in    al,timer0
  298.     xchg    ah,al
  299.     neg    ax
  300.     mov    timer_count,ax    ;ax now has 16 bit timer count
  301. ;
  302. ; read interrupt count from bios
  303. ;
  304.     mov    ax,es:[timer_low]
  305.     sub    ax,interrupt_count
  306.     mov    interrupt_count,ax
  307. ;
  308. ; restart the timer by resetting default value of control word
  309. ;
  310.     mov    al,00110110b    ;binary,mode 3,timer 0
  311.     out    timer_mode,al
  312.     mov    al,0
  313.     call    delay
  314.     out    timer0,al
  315.     call    delay
  316.     out    timer0,al
  317. ;
  318. ; return values to caller
  319. ;
  320.     mov    ax,timer_count
  321.     mov    dx,interrupt_count
  322.  
  323.     sub    ax,calibrate
  324.     sbb    dx,0            ;calibrate timer value
  325.     popf
  326. exit:    apop    es,ds
  327.     retf
  328. read_timer    endp
  329.  
  330. comment 
  331. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MISC   )
  332. ;CONVERT_TIMER - convert timer ticks to seconds and microseconds
  333. ;  inputs:  dx,ax = total 8253 timer ticks at rate of 1,193,182 per second
  334. ;  output:  ax = seconds
  335. ;           cx,bx = microseconds
  336. ;
  337. ;* * * * * * * * * * * * * *
  338. 
  339.     public    CONVERT_TIMER
  340. CONVERT_TIMER    proc    far
  341.     apush    si,ds
  342.     mov    si,cs
  343.     mov    ds,si
  344.  
  345.     mov    cx,word ptr timer_convert+2
  346.     mov    bx,word ptr timer_convert
  347.     call    quad_multiply1        ;result to dx,cx,bx,ax
  348.     mov    si,word ptr hundred_thousand+2
  349.     mov    di,word ptr hundred_thousand
  350.     call    quad_divide        ;result dx,ax  remainder cx,bx
  351.  
  352. ;
  353. ; dx,ax now contains the total number of micro seconds, cx,bx = remainder
  354. ;
  355.     cmp    cx,1
  356.     je    round_up
  357.     cmp    bx,0c350h        ;(100000/2)
  358.     jb    compute_seconds
  359. round_up:
  360.     add    ax,1
  361.     adc    dx,0            ;round up 1
  362.  
  363. compute_seconds:
  364.     mov    bx,dx
  365.     xor    dx,dx
  366.     xor    cx,cx
  367.     mov    si,word ptr million+2
  368.     mov    di,word ptr million
  369.     call    quad_divide        ;compute seconds & microseconds
  370. ;
  371. ; dx,ax = seconds   cx,bx = microseconds
  372. ;
  373.     apop    ds,si
  374.     retf        
  375.  
  376. CONVERT_TIMER    endp
  377.  
  378. comment 
  379. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MISC   )
  380. ;DISPLAY_TIMER - display timer values to stdout
  381. ;  inputs:   ax = seconds
  382. ;          cx,bx = microseconds
  383. ;  output:  none
  384. ;           
  385. ;* * * * * * * * * * * * * *
  386. 
  387.     public    display_timer
  388. DISPLAY_TIMER    proc    far
  389.     apush    si,ds
  390.  
  391.     mov    si,cs
  392.     mov    ds,si
  393.     mov    seconds,ax
  394.     mov    word ptr microseconds+2,cx
  395.     mov    word ptr microseconds,bx
  396.  
  397.     mov    si,offset msg1
  398.     call    stdout_string            ;display 'Elapsed time ="
  399.     
  400.     mov    ax,seconds
  401.     call    word_to_dec_stdout        ;seconds
  402.     mov    si,offset message_sec
  403.     call    stdout_string
  404.     
  405.     mov    ax,word ptr microseconds
  406.     mov    dx,word ptr microseconds+2
  407.     call    dword_to_dec_stdout
  408.     mov    si,offset message_micro
  409.     call    stdout_string
  410.     apop    ds,si
  411.     retf
  412. DISPLAY_TIMER    endp
  413. comment 
  414. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MISC   )
  415. ;CALIBRATE_TIMER - calibrate timer
  416. ;  inputs:  none
  417. ;  output:  none
  418. ; note:  This function computes the overhead needed to call
  419. ;        START_TIMER and read_timer on current computer and
  420. ;        calibrates the time calculation so that it will
  421. ;        compute zero if nothing is being timed.           
  422. ;
  423. ; note:  This function only needs to be called once.  It saves
  424. ;        a calibration factor which is used by read_timer as
  425. ;        long as read_timer is in memory.
  426. ;* * * * * * * * * * * * * *
  427. 
  428.  
  429.     public    calibrate_timer
  430. calibrate_timer    proc    far
  431.     apush    ax,bx,cx,dx
  432.     mov    cs:calibrate,0
  433.     mov    cs:seconds,0
  434.     mov    cx,8
  435. ct_lp1:    push    cx
  436.            call    start_timer
  437.     call    read_timer
  438.     add    cs:seconds,ax
  439.     pop    cx
  440.     loop    ct_lp1
  441.  
  442.     mov    ax,cs:seconds
  443.     mov    cl,3
  444.     shr    ax,cl
  445.     mov    cs:calibrate,ax
  446.     
  447.     mov    cx,5000
  448. ct_lp:    call    delay
  449.     loop    ct_lp
  450.     apop    dx,cx,bx,ax
  451.     retf
  452. calibrate_timer    endp
  453. ;--------------------------------------------------------------------------
  454.  
  455. timer_count    dw    0    ;read from 8253
  456. interrupt_count    dw    0    ;read from BIOS
  457.  
  458. microseconds    dd    0    ;total microseconds
  459. seconds        dw    0    ;total seconds
  460.  
  461. calibrate    dw    0    ;calibration factor from read_timer
  462.  
  463. timer_convert    dd    83809    ;838.096 nsec per tick
  464. hundred_thousand dd    100000
  465. million        dd    1000000
  466.  
  467. msg1        db    0dh,0ah,0dh,0ah,'Elapsed time = ',0
  468. message_sec    db    ' (seconds)   ',0
  469. message_micro    db    ' (Micro seconds)',0dh,0ah,0
  470.  
  471.  
  472. LIBSEG    ENDS
  473. ;;    end
  474.  
  475. ;-------------------------------------------------------------------------
  476. ; zseg must be at the end of the program for memory allocation from
  477. ; DOS.
  478. ;
  479. zseg    segment    para public 'ZZ'
  480. zseg    ends
  481.         end    start
  482.