Timer systemowy
cepa
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:
- pobierz adres oryginalnej procedury obsługi przerwania 1CH
- podepnij nową procedure
- wykonuj program
- 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
;-------
Dodałem kolorowanie składni :-)
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 ??
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