calosc zadania ma tu polegac na przyspieszeniu wywolywania przerwania sprzetowego IRQ0 (przerwanie programowe INT 08h). z tego co wyczytałem jest ono wywoływane co 55ms i za każdym razem przy okazji wywołuje ono INT 1Ch. To by oznaczało że musimy przyspieszyc IRQ0 55 razy i podczas wywołań liczyć ile razy już się wykonało: jeżeli mniej niz 55 razy to musimy samodzielnie wywołać INT 1Ch a jeśli wykonało się 55 razy to musimy wywołać oryginalną procedure IRQ0 (które za nas wywoła INT 1Ch podczas tego 55-ego razu).
Aby przyspieszyc IRQ0 musimy przeprogramowac PIT który to jest tworem odpowiedzialnym za ustalenie czestości generowania IRQ0 (tj.to przez niego musimy przyspieszac). Dostep do tegóż mamy przez porty 43h i 40h
oto źródło za pomocą którego możemy przeprogramować PIT i IRQ0 (tj.: oto gotowiec ;) ). Programik jest stworzony pod NASM i do kompilacji do pliku .COM
Kopiuj
[org 100h]
push cs ;tak na zas kopiujemy cs do ds jakby system tego nie zrobil
pop ds
jmp entry_point
data:
faster dw 55 ;ile razy przyspieszamy PIT
ctimes dw 0 ;ilosc naliczonych wywolan naszego IRQ0
oldIRQ0 dd 0 ;pierwotny adres IRQ0
;;nasza nowa procedura IRQ0
newIRQ0:
pushf ;zabezpieczmy FLAGS i AX na stosie - bedziemy uzywac tych rejestrow wiec dobrze by bylo zeby nie zniszczyc ich zawartosci
push ax
nIRQ0_IRQ: ;wlasciwa procedura przerwania
inc word [ctimes]
mov ax, [ctimes]
xor ax, [faster] ;szybsza forma cmp (jesli sprawdzamy warunek rownosci '=' to nie marnujmy czasu na cmp i uzyjmy szybszego a rownie skutecznego xor)
jnz nIRQ0_end ;jesli nie rowne to do wyjscia z naszego IRQ0
mov word [ctimes], 0 ;wyzerujmy licznik wywolan
;posprzatajmy po sobie
pop ax
popf
;wywolajmy domyslna procedure IRQ0
;(uzylem rozwiazania ktore zapewni nam, ze domyslne IRQ0 juz zakonczy procedure obslugi przerwania zamiast wracac do naszej)
push dword [oldIRQ0]
retf ;skocz do oryginajnego IRQ0 - oryginalne IRQ0 juz tu nie wroci (cos na wzor jmp far ktorego jednak nie wszystkie kompilatory lubia tak jak zauwazylem)
nIRQ0_end:
int 1Ch ;wywolajmy INT 1Ch
;powiedzmy kontrolerowi PIC ze zakonczylismy obsluge przerwania IRQ0
mov al, 20h
out 20h, al
;posprzatajmy po sobie
pop ax
popf
iret ;koniec przerwania
entry_point:
;zainstalujmy nasze przerwanie IRQ0 (po drodze robiac kopie obecnego)
mov ax, 0
mov es, ax
mov di, 8 ;numer przerwania INT 08h, ktore chcemy podmienic
shl di, 2
mov eax, [es:di] ;32-bitowe rejestry ale adresowanie 16-bitowe
mov [oldIRQ0], eax ;zabezpieczamy stary wektor przerwania IRQ0
;stworzmy w eax nasz wektor przerwania
mov ax, cs
shl eax, 16
lea ax, [newIRQ0]
cli ;blokada przerwan (bardzo wazne gdyz poki nie przeprogramujemy PIT nasze przerwanie bedzie zle dzialalo!!!)
mov [es:di], eax ;wstawiamy nasz wektor przerwania
;mamy przerwanie, teraz przeprogramujmy PIT
mov dx, 1
mov ax, 0
div word [faster]
push ax
mov al, 0x34
out 0x43, al ;zaznaczmy ze chcemy przeprogramowac PIT
pop ax
out 0x40, ax ;ustawmy nowa wartosc dla PIT
sti ;PIT dziala juz tak jak chcemy wiec odblokujmy przerwania
main: ;nasz wlasciwy program (tu mozna robic juz co chcemy cieszac sie z predkosci - ja zrobilem po prostu czekanie na dowolny klawisz)
mov ax, 0x1000
int 0x16
kill: ;koniec programu - trzeba przywrocic PIT i IRQ0 do stanu pierwotnego
;przywracamy IRQ0
mov ax, 0
mov es, ax
mov di, 8
shl di, 2
mov eax, [oldIRQ0]
cli ;blokada przerwan na czas przelaczania PIT
mov [es:di], eax ;wstawiamy stary wektor przerwania
;przywracamy PIT
mov al, 0x34
out 0x43, al
mov ax, 0
out 0x40, ax
sti ;odblokowac przerwania
;i zakonczyc program
mov ax, 0x4C00
int 0x21