Z pogranicza

Timer systemowy

  • 2008-03-06 12:34
  • 3 komentarze
  • 866 odsłon
  • Oceń ten tekst jako pierwszy
Timer systemowy zawarty w każdym komputerze PC, generuje standardowo  18,2 razy na sekunde
przerwanie programowe 1CH. Aby je praktycznie wykorzystać (np: w grze), musimy się pod nie
podpiąć zamieniając oryginalny adres procedury przerwania 1CH na adres naszej procedurki.
Aby to zrobić możemy użyć funkcji DOS'a: 25H i 35H. Pierwsza z nich umożliwia zapis wektora
(adresu) procedury przerwania w tablicy przerwań, druga umożliwa odczyt tego adresu.
Ponieważ po zakończeniu programu który przejąłby przerwanie, ustawione przez niego procedury
przerwan nadal działają (co doprowadza do zawieszenia komputera), musimy pod koniec pracy
programu przywrócic adres oryginalnej procedury obsługi przerwania 1CH. Dlatego też ogólny
schemat działania programu wygląda następująco:
1) pobierz adres oryginalnej procedury obsługi przerwania 1CH
2) podepnij nową procedure
3) wykonuj program
4) przywróc starą procedure

Uwaga ! Jeżeli w procedurze obsługi dowolnego przerwania zamierzasz korzystać ze zmiennych
dostępnych dla całego programu wtedy musisz sie do nich odwołać przez rejestr CS, np:
MOV BYTE [CS:zmienna],10

To będzie na tyle teori, oto przykładowy kod (NASM). Program po uruchomieniu będzie wkołko
wyświetlał napis Timer co taki sam odcinek czasu.

;-------
        CPU 186
        BITS 16
 
 
        ORG 100H
        JMP main
 
 
timer_int:                                            ; procedura obslugi przerwania 1CH
        STI
        MOV BYTE [CS:can_print],1                     ; ustaw zmienna can_print na 1
        CLI
        IRET
 
 
install_timer:
        MOV AX,351CH                                  ; pobierz adres starej procedury
        INT 21H                                       ; przerwania 1CH i wrzuc go do
        MOV [CS:old_timer_int],BX                     ; zmiennej old_timer_int (ES:BX)
        MOV [CS:old_timer_int + 2],ES
        MOV AX,251CH                                  ; ustaw nowa procedure
        MOV DX,timer_int                              ; laduj jej adres do DS:DX
        PUSH DS
        PUSH CS
        POP DS
        INT 21H
        POP DS
        RET
 
 
remove_timer:
        MOV AX,251CH                                  ; przywroc stara procedure
        LDS DX,[CS:old_timer_int]
        INT 21H
        RET
 
 
main:
        CALL install_timer                            ; instaluj timer
main_loop:
        CMP BYTE [can_print],1                         ; jezeli can_print = 1
        JNE main_loop                                  ; to wyswietl napis "Timer"
        MOV BYTE [can_print],0
        PUSH DS
        PUSH CS
        POP DS
        MOV DX,timer_text
        MOV AH,09H
        INT 21H
        POP DS
        JMP main_loop
exit:
        CALL remove_timer                             ; usun timer (tu nie dojdzie nigdy)
        MOV AX,4C00H
        INT 21H
 
 
old_timer_int                          DD 0
timer_text                             DB 'Timer',10,13,'$'
can_print                              DB 0
;-------

3 komentarze

lukasz1235 2008-03-06 12:34

Dodałem kolorowanie składni :-)

AklimX 2004-07-28 08:23

a co jeśli podczas wykonywania programu wystąpi błąd krytyczny i się on wyłączy. Czy wtedy system zawiesi się całkiem, czy przywróci może właściwe "ustawienia" timera ??

cepa 2004-07-28 12:45

to zalezy pewnie od tego co będzie zawierała procedurka timera, jak nie bedzie operowac na duzych zmiennych itp, to pewnie nic sie nie stanie, a w przeciwnym wypadku to reset i po klopocie , zreszta problem dotyczy tylko czystego dosa :P