; MATRIX CPU FREQENCY MEASUREMENT PROGRAM #5
; Program measures CPU speed and writes in Hz via bios
; ( takes over your computer while measuring )
; 25 measures under windows@accuracy of 72:
;927101637.661349 Hz
;927101637.662103 Hz
;927101637.661463 Hz
;927101637.661342 Hz
;927101637.662203 Hz
;928294818.641165 Hz ;wonder why? cpu freq increased? pit missed? cli not working?
;927101637.661824 Hz
;927101637.662412 Hz
;927101637.661548 Hz
;927101637.662214 Hz
;927101637.662018 Hz
;927101637.661439 Hz
;927101637.662028 Hz
;927101637.661594 Hz
;927101637.661744 Hz
;927101637.661776 Hz
;927101637.661738 Hz
;927101637.662222 Hz
;927101637.661945 Hz
;927101637.661818 Hz
;927101637.661449 Hz
;927101637.662091 Hz
;927101637.661879 Hz
;927101637.662032 Hz
; if you find any mistakes you should tell me
; of course windows may prefer fucking up so prefer accuracy above 100

;accuracy=1820 ; 100 sec
accuracy=72

org 256
use16

cli
call setup_pit_timer

mov cx,24 ; write 5 results

mainloop:
push cx

cli ; windos will not mess with my timings

  call	  read_pit_value
 mov	 bx,ax
 rdtsc
 mov	 [tempdat],eax
 mov	 [tempdat+4],edx
 mov	 cx,accuracy
below:
  call	  read_pit_value
 cmp	 ax,bx
   jl	  below
above:
  call	  read_pit_value
 cmp	 ax,bx
   jg	   above
 loop	 below
 rdtsc
 sti

 sub	 eax,[tempdat]
 sbb	 edx,[tempdat+4]
 mov ecx,accuracy*65536
 div ecx
 push edx ; take remainder
 xor edx,edx
 mov ecx,$1234dd
 mul ecx ; we hope it will not overflow if you have more than 4.29 GHz ask for newer version :)
 mov	 bl,10
  call	  bwritedword

mov ah,0xe
mov al,'.'
int 10h

pop eax ; pop remainder ; resolution will be 1/65536 per accuracy
 mov ecx,$1234dd
 mul ecx
 mov ecx,accuracy*65536
 div ecx
  call	  bwritedword ; write remainder
  call	  bendline

pop cx
loop mainloop

call reset_pit_timer

ret

setup_pit_timer:  ; returns status in al
 mov al,00110100b ; rate generator
 out 43h,al
 xor al,al
 out $40,al
 out $40,al
.waitlatch:
 mov al,11100010b ; get timer 0 status
  out 43h,al
  in al,40h
bt ax,6
jc .waitlatch
ret

reset_pit_timer:
 mov al,00110110b ; rate generator
 out 43h,al
 xor al,al
 out $40,al
 out $40,al
.waitlatch:
 mov al,11100010b ; get timer 0 status
 out 43h,al
 in al,40h
bt ax,6
jc .waitlatch
ret

read_pit_value:
.waitlatch:				     ;
 mov al,11100010b ; get timer 0 status       ;
 out 43h,al				     ;
 in al,40h				     ;
bt ax,6 				     ;
jc .waitlatch				     ;
  mov al,11010010b
  out 43h,al
  in al,40h
  mov ah,al
  in al,40h
  xchg al,ah
ret

bwritedword: ; EAX = number, BL = base
  push eax ebx ecx edx
  and ebx,$ff
  cmp bl,2 ; base can't be less than 2 :)
  jge .start
  mov bl,10	; using bx = 10 instead
  .start:
  xor ecx,ecx	  ; cx = 0
  .new:
  xor edx,edx	  ; dx = 0
  div ebx	 ; number / base
  push dx	; push the remainder
  inc ecx	 ; increase the "digit-count"
  or eax,eax	  ; if the quotient still is not 0, do it once more
  jnz .new
  .loop:
  pop ax	; pop the remainder
cmp al,10
sbb al,69h
das
mov ah,$e
int 10h
  loop .loop
  pop edx ecx ebx eax
ret

bendline: ; ends the line ( adds y loc = 1 x loc = 0 )
push ax bx ; returns:  AX = 0xE0A ; BX = 7
mov bx,7
mov ax,$E0D
int 10h
mov al,$A
int 10h
pop bx ax
ret

tempdat:
