; *************************************************
; * VITESSE.COM      
; * version 1.0 (4 avril 2003)
; * (c) Copyright JP MICHEL 2003
; *************************************************
; * compiler avec  :
; * > ml /Fl VITESSE.ASM
; * > link VITESSE,;
; * > exe2bin VITESSE.EXE VITESSE.COM
; *************************************************
; * ATTENTION !
; *
; * Ce programme fonctionne en mode MS-DOS pur.
; * Il ne fonctionne pas en mode MS-DOS virtuel.
; *************************************************

page 68,132

                             title  VITESSE

;******************************************************************************

code   segment
       assume cs:code , ds:code , es:nothing


              org  100h             ; pour un programme *.com

entree :      jmp  debut


    signature      db  13,10
                   db  'VITESSE.COM      version 1.0',13,10
                   db  '(c) Copyright JP MICHEL 2003',13,10,0

    align 4
    frequence label dword
    freq_bas  dw  ?
    freq_haut dw  ?

    mess1     db  13,10
              db  " Ce programme calcule la fr‚quence du processeur. ",13,10
              db  13,10
              db  " Il ne fonctionne que sur le Pentium. ",13,10
              db  0

    mess2     db  13,10
              db  " Le processeur a une fr‚quence de "
    mess2a    db  "           "
    mess2b    db  " MHz ",13,10
              db  0

;******************************************************************************

debut :       cld                   ; pour tout le programme
              call aide             ; aide demandee ?


; supprime toutes les interruptions sauf le timer IRQ 0

              in   al, 21h          ;
              mov  ah, al           ;
              in   al, 0A1h         ;
              push ax               ; sauvegarde
              mov  al, 0FEh         ;
              out  21h, al          ;
              mov  al, 0FFh         ;
              out  0A1h, al         ;


; compte le nombre de cycles entre 2 appels du timer

.586
              hlt                   ; attente du timer
              rdtsc                 ; nombre de cycles depuis le lancement
              mov  ebx,eax          ; partie basse
              mov  ecx,edx          ; partie haute
              hlt                   ; attente du timer
              rdtsc                 ; nombre de cycles depuis le lancement
              sub  eax,ebx          ; difference basse
              sbb  edx,ecx          ; difference haute


; Calcule la fréquence en MHz

              mov  ecx, 54925       ; timer toutes les 54925 microsecondes
              div  ecx
              inc  eax              ; arrondi par exces
              mov  frequence, eax
.8086


; restauration des interruptions

              pop  ax
              out  0A1h, al
              mov  al, ah
              out  21h, al


; affichage du resultat

              mov  ax,freq_haut
              push ax               ; partie haute
              mov  ax,freq_bas
              push ax               ; partie basse
              mov  di,offset mess2a
              call ecrit_dec
              xor  al,al
              stosb

              mov  dx,offset mess2
              call aff_message
              mov  dx,offset mess2b
              call aff_message

sortie :      mov  ax,4C00h
              int  21h

;******************************************************************************
; Ecriture d'un entier sur 32 bits, justifie a gauche
; l'entier est passe par la pile
; es:di est initialise

ecrit_dec :   push bp               ;
              mov  bp,sp            ;

              mov  cx,10            ; pour la conversion en decimal

              xor  dx,dx            ; dx = 0
              mov  ax,[bp +6]       ; ax = partie haute
              div  cx               ; division de 0:haut par 10
              mov  bx,ax            ; sauvegarde du quotient haut dans bx
              mov  ax,[bp +4]       ; ax = partie basse
              div  cx               ;
              add  dl,'0'           ; conversion ascii du reste
              push dx               ; sauvegarde du reste
              mov  dx,bx            ; dx:ax = quotient
              or   bx,ax            ; quotient nul ?
              je   ecrit_dec1       ; saut si oui

              push dx               ;
              push ax               ; nouveau dividende
              call ecrit_dec        ; appel recursif de la procedure

ecrit_dec1 :  pop  ax               ; recuperons le reste
              stosb                 ; on stocke le chiffre obtenu

              pop  bp               ;
              ret  4                ; on depile le nombre

;******************************************************************************

aide :        mov  si,81h           ; debut de la ligne de commande
              xor  cx,cx            ;
              mov  cl,[si-1]        ; cx = longueur de la ligne de commande
              jcxz aide_3           ; abandon si cx est nul
aide_1 :      lodsb                 ;
              cmp  al,'/'           ;
              jne  aide_2           ;
              mov  al,[si]          ;
              cmp  al,'?'           ;
              je   aide_4           ;
aide_2 :      loop aide_1           ;
aide_3 :      ret

aide_4 :      mov  dx,offset mess1  ; message d'aide
              call aff_message      ;
              jmp  sortie           ;

;******************************************************************************
; entrer avec dx = offset du message , termine par 0

aff_message : call lg_message       ; revient avec cx = longueur du message
              mov  ah,40h           ;
              mov  bx,1             ; sortie standard
              int  21h              ;
              ret

; entrer avec dx = offset du message , termine par 0

aff_erreur :  call lg_message       ; revient avec cx = longueur du message
              mov  ah,40h           ;
              mov  bx,2             ; sortie des erreurs
              int  21h              ;
              ret

lg_message :  mov  si,dx            ;
lg_m1 :       lodsb                 ;
              or   al,al            ;
              jne  lg_m1            ;
              dec  si               ; si pointe le 0
              mov  cx,si            ;
              sub  cx,dx            ; cx = longueur a afficher
              ret

;******************************************************************************
;******************************************************************************

code    ends

        end  entree

;******************************************************************************
