Ú-7 |
Styk mikropočítača s prostredím |
µ |
Obsluha prerušenia |
|
q
|
Rezidentné programy |
|
|
1.
|
Nainštalovanie rezidentného programu |
|
|
2.
|
Realizácia programovej obsluhy preušenia |
|
|
3.
|
Používanie služieb BIOS a DOS |
|
|
4.
|
Použitie vlastného rezidentného zásobníka |
|
|
5.
|
Aktivovanie rezidentného programu |
|
q
|
Kontrolér prerušenia |
|
|
q
|
Demonštrovanie prerušenia |

Ďalšie zaujímavé demo
programy realizovania obsluhy INT
F Drucker.asm - procedura Near, volaná Call
CS:[INT17H] . Obsahuje inštalačný Flag - Aktiv.
F Int24.asm - prepíše pôvodný obslužný program
svojim kratšim.
F Hotkey1.asm - Odstranenie
problému neretrantnosti INT 9h, INT 13H, INT 10H, INT 28H.

Prerušenie (Interrupt) je udalosť
vyvolaná vonkajšim impulzom alebo zopdpovedajúcou programovou
inštrukciou, na základe ktorej procesor preruší práve vykonávaný
program a zavolá rutinu určenú príslušným vektorom prerušenia.
Signál prerušenia z externého zdroja sa
môže k procesoru dostať cez jeden z dvoch vývodov: INTR a NMI.
- NMI - nemaskovateľné prerušenie
sa používa na signalizovanie “katastrofických “ udalostí ako je
napríklad náhly pokles napájacieho napätia alebo chyba parity operačnej
pamäti či zbernice. Tento vývod procesora je teda určený pre
prerušenia, ktoré nie je možné zakázať.
- INTR - maskovateľné prerušenie, resp. vývod tohto zakázateľného prerušenie je
väčšinou
budený ďalšim obvodom - programovateľným kontrolérom prerušenia - PIC
často
typu 8259. Obsluhu tohto prerušenia možno programovo zakázať
vynulovaním bitu IF v príznakovom registri
procesora. Pokiaľ je IF = 0 procesor prerušenie ignoruje. Povinosťou
kontroléra PIC je udržať informáciu o aktívnej požiadavke na prerušenie
do doby keď sa uvoľní bit IF = 1 a procesor môže vo vhodnom okamihu
akceptovať požiadavku na prerušenie tak, že vyšle 2 cykly zbernice
označené INTA (Interrupt Asknowledge ). Počas druhého z nich uloží PIC na dátovú zbernicu číslo vektora
prerušenia,
na základe ktorého je vyslaná adresa príslušnej rutiny z tabuľky
vektorov prerušení. Po začatí obsluhy prerušenia je automaticky
zakázaný príjem ďalšieho prerušenia. V prípade ak sa akceptuje príjem
ďalšich vnorených prerušení možno ich prístup odblokovať programovo
pomocou príznakového bitu IF.
Prerušenia z hľadiska zdroja
požiadavky na prerušenie sú:
- interné INT, tiež
nazývané softwareové SW_INT, ktoré sú generované
programovo, synchronne v poradí s časom vyskytu v danej postupnosti
inštrukcii vykonávaného programu. Sú to vlastne špecializované
obslužné rutiny, ktorých začiatočná adresa je prístupná pomocou
tabuľky vektorov prerušení. Vyznačujú sa tým, že vykonanie je veľmi
rýchle. Tabuľka vektorových prerušení len zjednodušuje volanie
príslušných obslužných procedúr a tiež umožňuje rôznym výrobcom
konštruovať vzájomne kompatibilné počítače. Preto sú nepoužité
preušenia pre obsluhu hardware využívané aj ako rozhranie pre volanie
služieb DOS a BIOS (F). K interním
INT patrí podľa definície firmy Intel aj prvých 32 typov (INT 0 až INT
31), ktoré sú určené pre potrebu samotného procesora v neštandardnej
situácii, napríklad INT 0 pri delení nulou, INT 1 pri krokovaní, INT 2
ako NMI, INT3 ako jednobajtová inštrukcia pre breakpoint, INT 4 pri
pretečení a pod.
- externé INT, tiež
nazývané harwareové HRDW_INT, ktoré sú generované vonkajšimi udalosťami,
asynnchronne voči bežiacemu programu.
Pre každý typ prerušenia je v operačnej
pamäti od fyzickej adresy 0
uložená úplná logická adresa obslužného programu (v poradí najprv
offset
pre IP potom segment pre CS), teda oblasť 256 * 4 byte = 1kB= 400H.
Táto oblasť pamäti sa označuje ako tzv. tabuľka vektorov
prerušení.
Dôležité
služby BIOS: |
|
INT
00H |
-
delenie nulou |
|
INT
01H |
-
krokovanie programu |
|
INT
02H |
- NMI |
|
INT
03H |
-
zastavenie programu - Break point |
|
INT
04H |
-
aritmetické pretečenie |
|
INT
05H |
- kláves
PrintScreen |
|
INT
08H |
- časovač |
|
INT
09H |
-
klávesnica |
|
INT
08H |
- časovač |
|
INT 10H |
-
VideoBIOS |
|
INT
13H |
-
Diskové operácie |
|
INT
14H |
-
Sériové rozhranie |
|
INT
15H |
-
Rozšírenie AT BIOSu |
|
INT
16H |
-
Obsluha buffera klávesnice |
|
INT
17H |
-
Obsluha tlačiarne |
|
INT
1AH |
-
Systémové hodiny |
|
INT
1BH |
- Kláves
Ctrl - Break |
|
INT
1CH |
-
Uživateľský časovač |
|
INT
1DH |
-
Tabuľka videoparametrov |
Prehľad
HW zdrojov INT |
|
Typ IRQ |
Adresa
INT vektora |
Typ INT |
Význam v
PC AT |
|
IRQ0 |
20H |
INT_8 |
HW
časovač (18,2Hz) |
|
IRQ1 |
24H |
INT_9 |
Klávesnica |
|
IRQ2 |
28H |
INT_10
(0AH) |
kaskádne
zapojenie 2PCI |
|
IRQ3 |
2CH |
INT_11
(0BH) |
COM2 |
|
IRQ4 |
30H |
INT_12
(0CH) |
COM1 |
|
IRQ5 |
34H |
INT_13
(0DH) |
LPT2 |
|
IRQ6 |
38H |
INT_14
(0EH) |
Disketa |
|
IRQ7 |
3CH |
INT_15
()FH) |
LPT1 |
|
IRQ8 |
1C0H |
INT_112
(70H) |
Kalendár |
|
IRQ9 |
1C4H |
INT_113
(71H) |
|
|
IRQ10 |
1C8H |
INT_114
(72H) |
|
|
IRQ11 |
1CCH |
INT_115
(73H) |
|
|
IRQ12 |
1D0H |
INT_116
(74H) |
|
|
IRQ13 |
1D4H |
INT_117
(75H) |
Koprocesor |
|
IRQ14 |
1D8H |
INT_118
(76H) |
pevný
disk |
|
IRQ15 |
1DCH |
INT_119
(77H) |
|
Vektory niektorých dôležitých prerušení DOSu: |
|
INT 20H
- Ukončenie programu |
|
|
|
INT 21H
- Služby DOSu |
|
Napríklad: |
|
INT 21H /ah= 31H- Ukonči a zostaň rezidentný |
|
INT 21H /ah= 49H- Uvoľni prodelený blok pamäte |
|
INT 21H /ah= 34H- Adresa príznaku DOS Busy Flag |
|
INT 21H /ah= 35H- Čítaj vektor prerušenia |
|
INT 21H /ah= 25H- Nastav vektor prerušenia |
|
INT 21H /ah= 62H- Čítaj adresu PSP |
|
INT 21H /ah= 50H- Nastav aktuálny PSP |
|
INT 21H /ah= 2FH- Čítaj DTA (DTA v PSP na offsete 80H) |
|
INT 23H
- Break |
|
INT 24H
- Kritická chyba (disková operácia, nepripravenosť zariadenia) |
|
INT 25H
- Čítanie absolutného sektora disku |
|
INT 26H
- Zápis absolutného sektora disku |
|
INT 27H
- Terminate and stay rezident ( TSR ) |
|
INT 28H
- Voľný DOS ( Periodicky generované ak čaká na vstup ) |
|
INT 2FH
- Komunikácia medzi procesmi |

Na demonštráciu adries INT a spôsobu ich
uloženia v pamäti možno použiť napríklad:
F
debbuger
F program DISPLAY.exe.
Program slúži na demonštráciu tabuľky
adries preušení a spôsobu ich uloženia v pamäti. Požaduje zadať číslo
INT pre toto zadané číslo INT zobrazí jeho vektror a aj spôsob zápisu
vektora INT v pamäti (najprv offset LSB, MSB potom segment LSB, MSB
adresy obslužného programu).
u Príklad výpisu adries prerušení pomocou debbugera
(získaná pomocou príkazu debuggera d 0:0). Pre iný PC (iný BIOS) sa môže výpis odlišovať.
Adresa |
Obsah
pamäte |
0000:0000 |
8A 10 16
01 F4 06 70 00-16 00 A0 05 F4 06 70 00 |
0000:0010 |
F4 06 70
00 54 FF 00 F0-4C E1 00 F0 6F EF 00 F0 |
0000:0020 |
5F 02 07 0C DE 01 5F D3-6F EF 00 F0 6F EF 00 F0 |
0000:0030 |
6F EF 00 F0 6F EF
00 F0-B7 00 A0 05 F4 06 70 00 |
0000:0040 |
78 16 85
CC 4D F8 00 F0-41 F8 00 F0 8A 16 85 CC |
0000:0050 |
39 E7 00
F0 65 17 85 CC-2E E8 00 F0 FD 01 07 0C |
0000:0060 |
CC E3 00
F0 55 17 85 CC-6E FE 00 F0 EE 06 70 00 |
0000:0070 |
53 FF 00
F0 A4 F0 00 F0-22 05 00 00 CA 53 00 C0 |
Z tabuľky vidno, že prerušeniu INT 8H,
zodpovedá obsah pamäte 20H - 24H (32D -36D), ktorý tvoria bajty
5F02070C => adresa : 0C07:025F (najprv offset LSB, MSB potom segment
LSB, MSB adresy obslužného programu).Poprípade tiež vidno, že
prerušenia INT 0BH a INT 0CH (pre obsluhu sériových portov) začínajú na
spoločnej adrese F000:EF6F H.

1) Nainštalovanie
rezidentného programu
Program k obsluhe prerušenia -ISR (Interrupt service routine) od
vonkajšieho zariadenia treba trvale, t.j. rezidentne uložiť do
pamäti tak, aby ho
bolo možné vyvolať aj počas behu iných programov. Užívateľské programy
sú totiž tranzientné - zavedú sa do operačnej pamäti, vykonajú sa a
uvoľnia
pamäť. Program k obsluhe prerušenia ISR pozostáva z inštalačnej a
reinštalačnej časti a z vlastného tela rezidentne uloženého programu.
Základom inštalačnej časti je špecialne zakončenie procedúry - TSR (terminate and stay
resident), uskutočnenej po zavolaní INT21H/ah=31H. Pri
tom je treba ešte špecifikovať dlžku takto rezervovanej rezidentnej
pamäte, v ktorej zostane uložený kód procedúry, poprípade aj oblasť jej
dát. Táto pamäťová oblasť sa rezervuje ako paragrafovo zaokrúhlená
=>
[(dlžka pamäte) /16)+1] paragrafov po 16 bit. Ak kód programu bude
súborom typu .com, tak treba takto zarezervovanú oblasť ešte zväščiť o
oblasť 100H na vytvorenie záhlavia pre PSP (Program Segment Prefix).
Pred ukončením inštalačného programu je
však potrebné ešte uložiť do tabuľky vektorov INT adresu začiatku
nového obslužného programu, ktorý zostane rezidentne uložený v pamäti.
(Pomocou služby INT21H / AH=25H, AL = No_INT sa uloží z
DS:DX nový začiatok obsluhy prerušenia No_INT do tabuľky vektorov INT).
Pred uložením adresy nového obslužného
programu sa obvykle najprv pomocou INT 21H/ AH = 35H / AL =
NoINT zistí adresa vektora pôvodného obslužného programu príslušného INT. Výstup
tejto operácie, ktorý bude uložený v ES:BX sa obvykle uschová do pamäte
na adresu Old_Int_No, aby bolo možno po odinštalovaní rezidentného
programu obnoviť pôvodné podmienky v obsluhe prerušení.

Napríklad pre predefinovanie
obsluhy prerušenia INT_17H možno vykonať nasledovú postupnosť
inštrukcii (podrobnejšie v programe Drucker.asm):
- Najprv zistiť adresu pôvodného
vektora prerušenia. (Po vykonaní INT 21H/ AH = 35H a AL = 17H bude
uložená v registri ES = segment isr_old_int_17a v registri BX = offset
isr_old_int_17).
- Potom pomocou INT21H / AH=25H, AL =
17H uložiť DS:DX nového začiatku obsluhy INT 17H do tabulky vektorov
INT. Ako identifikátor konca rezidentného programu je kvôli
jendnoduchšiemu zápisu použité náveštie isr_end.
|
org
0100H |
;pre
súbor.com |
|
JMP
inicial |
;skok na
začiatok inicializačnej časti |
old_int_17_seg
|
dw ? |
;Adresa
segmentu starého INT_17-ISR |
old_int_17_off
|
dw ? |
;Adresa
offsetu starého INT_17-ISR |
|
;Mohol by byť použitý aj nasledujúci spôsob
deklarovania pamäťového miesta: |
;old_int17
|
DD ? |
|
int_service: |
|
;Tu je
telo obslužnej procedúry INT, |
|
|
;ktorá
zostane rezidentne uložená |
|
|
; tu je
koniec obslužnej procedúry |
isr_end |
label
byte |
|
Install: |
|
|
|
mov ax,
3517H |
|
|
int 21H |
|
|
mov
old_int_17_off, bx |
;úschova
stareho vektora ISR_17 |
|
mov
old_int_17_seg, es |
|
|
|
|
|
; Iný variant uloženia ES:BX do pamäte: na adresu
old_int17H: |
|
;mov
word PTR old_int17H, bx |
|
|
;mov ax,
es |
|
|
;mov
word PTR old_int17H+2, ax |
|
|
;Lea dx,
int_service |
;nový
vektor rezidentného ISR_17 |
|
|
|
|
mov ax,
2517H |
;nastavenie
nového vektora INT |
|
mov dx,
offset int_service |
;(
z DS:DX) na začiatok obsluhy
|
|
int
21H |
|
|
add dx,
0100H |
; rezervovanie
rezidentnej pamäte |
|
mov cl, 4 |
;miesto
pre PSP |
|
Shr dx,
cl |
;delenie
16 |
|
add dx, 1 |
; mohlo
by byť použité aj inc dx |
|
mov ax,
3100H |
;zakončenie
procedúry - TSR |
|
int 21H |
|

2)
Realizácia programovej obsluhy preušenia
Vlastný obslužný program okrem úschovy
obsahov požívaných registrov (PUSH - POP) a ukončenia procedúry obsluhy
pomocou IRET može byť buď naviazaný na činnost určitej obslužnej
rutiny, spravidla BIOS, DOS alebo tvorí nezávislý obslužný program s
orginálnym vektorom prerušenia, teda buď:
- slúži ako samostatný
obslužný
program, napríklad pre určité vonkajšie zariadenie, ktoré má
svoju individuálnu požiadavku IRQ, realizovanú cez spoj k obvodu
PIC-8259A , napríklad ako tlačítko cez príslušný kolík na konektori
zbernice, umožňujúce po stlačení vyvolať žiadosť o prerušenie IRQi.
Predpokladom úspešnej funkcie (okrem povolenia prerušení od vonkajšich
zariadení - IF pomocou inštrukcie STI) je tiež správne nainicializovanie kontroléra PIC 8259A (
inicializácia cez BIOS, vhodná maska pomocou OCW1 do registra IMR). Po
skončení obslužnej procedúry , vyvolanej vonkajšim preušením treba
oznámiť kontroléru PIC 8259A koniec aktivity obsluhy pomocou slova
OCW2.
buď ako nešpecifikovaný koniec EOI (rovnaký pre všetky IRQ a
zakončujúci
naraz všetky žiadosti IRQ) alebo ako koniec len vybranej žiadosti
IRQ_i,
napríklad v prípade vnoreného prerušenia.
- alebo modifikuje pôvodný
obslužný program a nová obsluha je zaradená na začiatok alebo na
koniec “ reťazca “ obslužných rutin, spravidla BIOS alebo DOS.
Príkladom slúži cvak.asm, ktorý modifikuje pôvodný program obsluhy
klávesnice INT_09H o cvaknutie - beep pri stlačení klávesu.
Návrat do pôvodnej procedúry BIOS alebo
DOS možno realizovať 2 spôsobmi, podľa spôsobu zreťazenia obslužných
rutin - novej a pôvodnej:
- nepodmieneným skokom
na
adresu pôvodnej obsluhy napríklad v prípade procedúry cvak.asm - INT
09H, na adresu získanú z tabuľky vektorov prerušení a uloženej na
adrese Old_Int_09H =>:
V tomto prípade zreťazenia
vektorov prerušenia bez návratu sa procedúra BIOS postará aj o
návrat do DOS, resp. do prerušeného uživateľského programu.
- zavolaním obsluhy
BIOS pre INT 09H z novej obslužnej rutiny pomocou Call
=>v prípade procedúry cvak.asm :
|
|
PUSHF |
;kompenzuje
IRET - RET |
|
|
Old_Int_09H |
|
|
|
IRET |
|
V tomto prípade zreťazenia
vektorov prerušenia s návratom do obslužnej procedúry zabezpečí
až IRET návrat do DOS, resp do uživateľského programu. Nakoľko pôvodná
BIOS procedúra je zakončená IRET treba pred inštrukciou CALL správne
nastaviť zásobník. S ohľadom na správne zosúhlasenie obsahu
ukazovateľa zásobníka SP treba vedieť, že:
Pri odlaďovaní procedúry TSR treba mať
na pamäti, že proces po predefinovaní tabulky vektorov INT a
nezadefinovaní nových hodnôt "zamrzne" a preto sa nesmie táto časť
procedúry krokovať ale treba ju rýchlo prebehnúť.

Cvak.asm - príklad modifikácie pôvodnej obsluhy INT 09H
Tento príklad demonštruje typ v pamäti
rezidentne uloženého programu , ktorý modifikuje pôvodnú obsluhu
prerušenia INT 09H tak, že doplní procedúru NewKeyInt pred začiatok
svojej pôvodnej obsluhy INT 09H a tým spôsobí, že po stlačení klávesu
sa ozve - beep. V procedúre sú uvedené dve rôzne možnosti realizácie
návratu k pôvodnej obslužnej rutine - obsluhy BIOS klávesnice. O
rezidentné uloženie procedúry NewKeyInt do pamäti sa stará
inicializačná časť rutiny Zac_Prg.
|
.MODEL
small |
|
.STACK
100h |
|
.DATA |
|
.CODE |
|
|
Begin: |
Jmp
ZAC_PRG |
|
|
|
;-------------------------------------- |
OldKeyInt
|
Dd
?
;Sem uloží pôvodnu adresu obsluhy INT |
|
;-------------------------------------- |
|
;procedúra
ISR, ktorá zostane rezidente v pamäti |
PROC
|
NewKeyInt
Far |
|
pushf
;1 časť => generovanie beep |
|
push ax |
|
in al,
60h
;PA - stav klavesnice |
|
cmp al,
80h ;či stlačený
kláves |
|
jnc
NoPress ;ak nebol
stlačený tak skok |
|
in al,
61h |
|
or al, 3 |
|
out 61h,
al ;uvoľni
ovladanie reproduktora |
|
mov al,
0b6h ;defin timer #2 |
|
out 43h,
al ;do cwrt |
|
xor al,
al |
|
out 42h,
al |
|
inc
al
;deliac pomer 400h |
|
inc al |
|
inc al |
|
inc al |
|
out 42h,
al |
|
mov ax,
3000h ;dlžka tónu |
@@loop: |
|
|
dec ax |
|
jnz
@@loop |
|
in al,
61h
;zablokovanie reproduktora |
|
and al,
0FCH |
|
out 61h,
al |
NoPress: |
|
|
pop ax |
|
Popf |
|
;---------------------
;koniec časti generujúcej beep |
|
|
|
;1) jeden variant zakončenia programu skok na povod sbr |
|
Jmp
CS:[OldKeyInt] |
|
|
|
;2) iny variant vykonania obslužnej rutiny call obsluhy s
navratom |
|
;pushf |
|
;call
cs:[OldKeyInt] |
|
;IRET |
|
;----------------------------------- |
|
|
Sprava
|
DB
"TSR je nainštalovany",13,10,"$" |
|
|
ZAC_PRG: |
|
|
mov ax,
cs ;Data
adresované cez Code seg |
|
mov ds,
ax ; =>
cs=ds |
|
|
|
mov ax,
3509h ;Zistí adresu pôvod isr int 9 |
|
int
21h
;vystup adr ES:BX |
|
mov word
PTR OldKeyInt, bx |
|
;uloženie adresy pôvod isr int 9 |
|
mov ax,
es |
|
mov word
PTR [OldKeyInt+2], ax |
|
mov dx,
offset NewKeyInt |
|
;nainštaluje novú adresu isr |
|
mov ax,
2509h ;DS:DX ale ds=cs |
|
int
21h |
|
|
|
mov ah,
9
;DOS vystup retazca s $ => Spravy |
|
mov dx,
offset Sprava |
|
int 21h |
|
mov
dx,offset ZAC_PRG |
|
add dx,
100h ;pre .com pridat
PSP!! |
|
mov cl,
4
;(dlžka oblasti +100)/16+1 |
|
shr dx,
cl |
|
inc
dx
;+1 zaokruhlenie |
|
mov ax,
3100h ;rezidentné ukončenie |
|
int 21h |
Endp
|
|
|
END |

3)
Používanie služieb BIOS a DOS
MSDOS bol vyvinutý ako
jednouživateľský operačný systém podporujúci len beh jedného programu.
Pod jeho správou ukladá každý program svoje dáta až do svojho ukončenia
ako globálne premenné. MSDOS však nie je tzv. reentrantný,
takže všeobecne neumožňuje súčastne vykonávanie viacerých programov.
Pri súčastnom vykonávaní hlavného programu a rezidentného programu môže
v ľubovolný moment vzniknúť sitácia, že systémové funkcie oboch
programov sa uložia na rovnaké miesto v pamäti.

Na minimalizovanie vzniku komplikácii so
zosynchronizovaním operácii pri súčastnom výskyte systémových programov
generovaných DOS (int21H/ ah>0CH) a rezidentným programom sa používa
1 bajtový príznak činnosti DOSu flag - INDOS, ktorý má
počas systemovej operácie DOS nenulovú hodnotu a tým umožňuje TSR
posúdiť či môže procedúra prebehnúť alebo treba počkať s jej vykonaním.
Adresu (ES:BX) interného
prepinača INDOS možno zistiť pomocou INT21H/ ah=34H.
Napríklad:
INDOS
|
DD
0
;adresa flagu v TSR data segmente |
|
;------------------------------------------ |
|
mov
ah,34H
;Zistenie adresy INDOS flagu |
|
int 21H |
|
mov word
PTR [INDOS],bx |
|
;uloženie adresy offsetu do pointera |
|
mov word
PTR [INDOS+2].es |
|
;uloženie adresy segmentu do pointera |
|
;------------------------------------------ |
|
push
ds
;Test INDOS flagu |
|
lds
bx,[INDOS] |
|
cmp
[bx], 0 |
|
pop ds |
|
jz
Volanie |
|
iret
;Ak INDOS flag <> 0 |
Volanie: |
;ďalšia obsluha ak bol INDOS aktívny |

Podobne pri súčastnom používaní služieb BIOS
a obslužných rezidentných procedúr môžu vznikať podobné komplikácie z
dôvodov nereentrantnosti ako pri službách DOS. Pri vnorených
systémových volaniach, napríklad pri volaní INT 10H, INT13H, INT 1CH a
pod. nemožno však využiť flag-INDOS. Na minimalizovanie problémov
nereentrantnosti v prípade volania obsluhy BIOS v programoch typu .com
možno na odlíšenie systémových činností použiť podobný postup ako pri
DOS obsluhe - pomocou zavedenia jednoduchého obslužného programu (v
dalšom príklade pomenovanom Handler), ktorým sa rozšíri pôvodná
obslužná rutina systémového prerušenia o nastavenie špecialneho
jednobitového flagu (nazvaného v ďalšom príklade Flag ) na hodnotu
1
pri aktívnom volaní BOIS a na hodnotu 0, keď môže túto službu použiť
rezidentný program. Takýto rezidentný program modifikujúci pôvodnú
obslužnú rutinu prerušenia by mohol vyzerať nasledovne:
Flag
|
DB
0
;Indikátor v oblasti dát |
Old_Int
|
DD
0
;Sem uloží adresu pôvodn. handlera |
|
;------------------------------------------------ |
Handler
|
proc far |
|
mov
cs:[Flag],
1
;Zablokuje ostatné volania |
|
Push |
|
call
cs:[Old_Int]
;Pôvodná systémová obsluha |
|
mov
cs:[Flag],
0
;BIOS už nie je aktívny |
|
ret2 |
Handler
|
endp |
|
;-------------------------------------------- |
|
;Tvar
časti kódu Handlera, ktorý nastavuje novú adresu upravenej systémovej
služby BIOS INT10H by mohol mať podobu: |
|
push cs |
|
pop
ds
;Priradenie segmentov pre .com |
|
mov
ax,3510H
;Zistenie adresy Handlera |
|
int 21H |
|
mov word
PTR [Old_Int], bx
;Uloženie adr Old Handlera |
|
mov word
PTR [Old_Int+2], es |
|
mov
ax,2510H
;Nastavenie adresy New Handlera |
|
mov
dx,offset Handler |
|
int 21H |
|
;------------------------------------------- |
Tvar časti kódu rezidentného programu,
ktorý pred použitím systémovej služby BIOS, napríklad vykonaním obsluhy
INT10H testuje obsah prepinača Flag by mohol mať podobu:
|
|
Cmp |
cs:[Flag],
1 |
;Test či
je INT10H aktívny |
|
|
Jnz |
Dalej |
|
|
|
Iret |
|
|
|
Dalej: |
|
|
;Tu
pokračuje obsluha |

4)
Použitie vlastného rezidentného zásobníka
Pri prerušní používa obslužná rutina
zásobník prerušenej aplikácie a preto by sa zásobník mal čo
najhospodárnejšie používať. V prípade nutnosti možno uložiť obsah
pôvodného zásobníka niekde do rezervovanej oblasti a založiť si vlastný
rezidentný zásobník. Napríklad na úschovu zásobníka o 128 byte
možno použiť nasledovnú postupnosť kódov:
;--------------------------------------------------- |
N_zasobnik DB 128
dup
(0)
;rezervovanie pamäti |
Old_SS DW
0
;Starý segment Stack |
Old_SP DW
0
;Starý pointer na Stack |
;-------------------------------------------Uloženie
zásobníka |
cli
;Zablokovanie vonkajšich INT, |
mov
[Old_SS],ss
;vnútorné neblokované |
mov
[Old_SP],sp
;úschova SS a SP |
cld
;DF=0 => spracovanie od dola |
push ds |
mov
si,sp
;offset zdroja prenosu v SP |
mov ds,
[Old_SS]
;segment zdroja v SS |
pop
es
;prenos SS:SP->DS:SI |
mov di, offset
N_zasobnik |
mov
cx,64H
;128 = 64*2 byte |
rep
movsw
;prenos ds:si -> es:si |
sti
;uvolnenie vonkajšich INT |
;--------------------------------------------Obnova
zásobníka pred IRET |
Cli |
mov di, [Old_SP] |
mov es,
[Old_SS]
;naspäť DS:SI ->ES:DI |
mov si, offset
N_zasobnik |
mov cx, 64H |
rep movsw |
mov ss,
[Old_SS]
;starý SS |
mov sp,
[Old_SP]
;starý SP |
sti
;povolenie INT |
;----------------------------------------------------- |

5)
Aktivovanie rezidentného programu
Rezidentný program sa aktivizuje na
pozadí iného uživateľského programu. Najčastejšie používané spôsoby na
vyvolanie činnosti spojenej s obslužným programom trvale uloženým v
pamäti, sú odovzdanie riadenia rezidentnému programu:
- Pomocou klávesu alebo kombinácie
klávesov tzv. aktivačných klávesov - hotkey, najčastejšie v spojení s BIOS volaním INT 09H (buď
pred volaním pôvodného vektora INT 09H, keď ako hotkey slúži priamo
scan kód klávesu alebo po návrate z pôvodnej obsluhy INT 09H, s
využitím BIOSom dosadenej ASCII hodnoty hotkey), poprípade s naväznými
službami INT 15H/ ah=4FH alebo až volaním INT 16H, ktoré obsluhuje
buffer klávesnice. Obsluhu INT 15H/ ah=4FH volá INT 09H na záver svojej
rutiny, aby rozlíšila scan kódy preraďovcích (sivých) klávesov na
základe príznaku CF. Ak je CF=0 tak je kód klávesu ignorovaný inač je
za Scan kód dosadený obsah AL z výstupu tejto operácie. Toto umožňuje
napríklad “zatajiť” stisk určitého klávesu alebo prekódovať fyzicky
klávesnicu. Je to teda jedno z miest, kde možno vložiť identifikáciu
hotkey. Podobnú službu vykonáva “voľný DOS” INT 28H, ktorý je
generovaný jadrom DOS v prípade, že tento čaká na vstup znaku z
konzoly. Pokiaľ je uživateľ v DOS v promte a nepíše vykonáva systém
nekonečný cyklus dvoch krokov: test buffera a ak je v bufferi znak
vyberie ho a spracuje ináč INT 28H.
Inú možnosť volania programovej
obsluhy pomocou klávesu umožnuje INT_15H/ah=85H. Táto služba poskytuje
informáciu o stlačení aktivačného klávesu Hotkey = SysReq (al=0) alebo
o pustení klávesu (al=1). V prípade chyby je prenosový príznak CF=1.
- Pomocou periodicky volaných služieb
BIOS, napríklad prerušenia INT 08H (ktoré je hardwarovo (IRQ 0)
generované) časovačom približne každých 55 ms, alebo ako užívateľský
variant časovača INT 1CH, ktorý je generovaný v rámci obsluhy INT 08H a
väčšinou neobsahuje rezidentný program ale len inštrukciu IRET;
- Na základe potreby vonkajšich
zariadení.
Handl09.asm - aktivovanie INT pomocou klávesu
Príklad procedúry používajúcej hotkey
ALT+M (ktorého kód je 0032H), na aktivovanie obslužnej rutiny,
uloženej od náveštia Volanie. Na začiatku procedúry sa pomocou pôvodnej
obsluhy BIOS Old_Int = INT 09H číta znak z klávesnice a pomocou
semafóru Aktiv je ošetrná nereentrantnosť BIOS volaní tak, že systémová
obsluha od rezidentného programu sa vykoná len pri stave semafóru Aktiv
= 0. Pri testovaní aktivačného klávesu sa využíva poznatok, že buffer
do ktorého sa ukladajú ASCII kódy klávesov je dlhý max. 20 znakov, je
alokovaný na adrese tabuľky BIOS parametrov od 0:41EH až 0:43DH, tak že
na adrese 0:41AH sa ukladá relatívny posuv adresy pre nasledujúci
ukladaný znak a že na adrese 0:41CH sa nachádza relatívne posunutie
posledného prečítaného znaku uloženého do buffera t.j. scan kód resp. 0
a kód klávesu. Pokiaľ teda nebol stlačený žiadny kláves je obsah (41CH)
= (41AH) a buffer je prázdny.
|
;----------------------------------------------------- |
Aktiv
|
DB
0
;semafór pre rezident. prg |
Old_Int
|
DD 0 |
|
;----------------------------------------------------- |
Handl09
|
proc far |
|
Pushf |
|
call cs:[Old_Int]
;Pôvodný INT handler |
|
cmp cs:[Aktiv], 0 ;Je už
aktívny BIOS INT09? |
|
jz dalej |
|
Iret |
|
dalej:
cli
;zablokovanie vonkajšich INT |
|
push ax |
|
push bx |
|
push dx |
|
push ds |
|
mov ax,
40H
;Segment Bios tabulky |
|
mov ds, ax |
|
mov dx, word PTR ds:[001CH] |
|
mov bx, word PTR ds:[001AH] |
|
cmp dx,
bx
;Je buffer prázdy ? |
|
jz Von |
|
mov ax,
[bx]
;kód klávesu z buffera |
|
mov ds:[001AH], dx ;Vymaze |
|
cmp ax,
3200H ; Je
to Hotkey ? |
|
jz Volanie |
Von: |
pop
ds
;ukončenie |
|
pop dx |
|
pop bx |
|
pop ax |
|
Iret |
Volanie: |
;obsluha ak bol Hotkey aktívny |
|
;---------------------------------------------------- |

Solídne rezidentné programy potrebujú
mať možnosť komunikácie s ostatnými programami. Minimálnou požiadavkou
je, aby program rozpoznal či je už uložený v pamäti a dokázal sa
odinštalovať, napríklad pri opakovanom spustení. Pokiaľ rezidentný
program nemá v sebe zabudovanú reinštalačnú časť treba na jeho
odstránenie z pamäti resetovať počítač.

Na uvoľnenie pamäte možno použiť INT 21H/ ah=49H, v ktorom
je v segmente ES ako vstup zadefinovaná adresa segmentu, pomocou
ktorého je adresovaná pamäť, ktorá sa má uvoľniť. Výstup tejto obsluhy
DOS je príznak prenosu CF. Ak je CF = 0 bolo odinštalovanie úspešné, v
opačnom prípade pri CF = 1 nastala chyba, napríklad uvedný
program nebol v poradí ako posledne nainštalovaný. Zo spôsobu
generovania prefixu PSP súboru .com je známe, že na offsete 002CH tohto
bloku pamäte je uložená segmentová adresa prostredia DOS, z ktorého bol
pôvodne inštalovaný rezidentný program.

Rezidentný program môže komunikovaťs
ostatnými programami buď pomocou iného vhodného vektora prerušenia
alebo pomocou prečítania správy dohovoreného tvaru, ktorá je pre
rezidentný program uložená na určité, k tomu vyhradené, miesto v
pamäti. Rezidentný program musí potom toto miesto periodicky
kontrolovať a preberať si uložené imformácie. V bloku štandardných
premených BIOS je pre tieto účely rezervovaných 16 byte od adresy
0:4F0H. Nevýhodou je však, že v BIOS nikdy nebola presne definovaná
konvencia pre využívanie tejto oblasti pre medziprogramovú komunikáciu.

Na rozpoznanie či je už program
aktívny v pamäti môže
slúžiť určitý identifikačný reťazec, prislúchajúci k handleru, slúžiaci
ako semafor. Napríklad nasledujúca postupnosť kódov najprv zistí a
uloží do registra ES segment adresy obsluhy INT09H, čím umožní
zosúladiť adresy identifukačného reťazca VZOR v rezidentnom a
inštalačnom programe. V prípade, že reťazce sú rovnaké tak bol už
predtým program rezidentne uložený do
pamäte a nie je
ho treba znova inštalovať (skok na náveštie hotovo), resp. bude
odinštalovaný. V opačnom prípade prebehne jeho inštalácia do pamäte
(skok na náveštie ďalej).
|
;----------------------------------------------------- |
VZOR
|
“DB “Vzor reťazca XY” |
|
;identifikačný reťazec |
|
;ktorý je súčasťou TSR a tiež |
|
;súčasťou inštalačného programu |
|
;tu je vlastná rezidentná obsluha |
instl: |
push cs |
|
pop
ds
;Nastavenie Data seg pre .com |
|
mov
ax,3509H ;Zistiť
segment obsluhy INT09H |
|
int
21H
;v ES je segment rezident obsluhy |
|
|
|
mov si, offset VZOR ;či bol reťazec nainštalovaný |
|
mov
di,si
;rovnaká adresa offsetu zdroj a cieľ |
|
mov
cx,7
;počet slov v reťazci |
|
repe
cmpsw
;porovnanie DS:SI s ES:DI |
|
jnz
dalej
;=> bude sa ukladať ako rezident |
hotovo: |
;už je uložený rezidentne v pamäti |
|
push es |
|
mov es,es:[002CH] ;adresa DOS prostredia z PSP |
|
mov
ah,49H
;uvoľní pamäť prostredia |
|
int 21H |
|
jc
chyba2
;hlásenie o chybe pri odinštalovaní |
|
pop es |
|
mov
ah,49H
;uvoľní pamäť rezidentného programu |
|
int 21H |
|
jc
chyba3
;hlásenie o chybe pri odinštalovaní |
|
mov ah, 4CH |
|
int
21H
;ukončenie programu |
|
;-------------------------------------------------- |

 |
Obr. 7-1. Kontrolér
prerušenia PIC 8259A v systéme s PC. |
Programovateľný obvod PIC(Priority Interrupt
Controller) tzv. kontrolér prerušenia, obyčajne realizovaný
obvodom 8259A, umožňuje spracovať až 8 žiadostí IRQi o
prerušenie, prideľovať a meniť im prioritu a zakazovať a povoľovať
jednotlivé prerušenia. Výstup z PIC ako už bolo spomenuté je pripojený
k vývodu pre maskovateľné prerušenie procesora INTR. Pre programátora
predstavuje ďalšiu vrstvu prerušovacieho systému, ktorá mu umožňuje
selektívne zakázať niektoré externé prerušenia, pokiaľ by nepostačovali
inštrukcie STI a CLI procesora. V PC XT sa používa jeden obvod PIC typu
8259, v PC AT sú zapojené dva v kaskáde, takže umožňujú až 15 rôznych
žiadostí o prerušenie.
Jeho pripojenie na zbernicu počítača je
podobné ako pripojenie podobných obvodov typu PPI-8255, PIT-8253 a pod.
S obvodom prvého Master PIC možno komunikovať cez porty 20H, 21H a s
obvodom druhého Slave PIC cez porty A0H, A1H. Žiadosti o prerušenie IRQi
nevyvolávajú priamo prerušenie na vývode INTR procesora, ale
možu byť v PIC-8259A rôznym spôsobom blokované (maskované) a
vyhodnocované podľa naprogramovanej priority. V PC sa používa spôsob
keď IRQ_0H (HW časovač 18,2Hz) má najvyššiu prioritu a volá vektorovú
adresu INT_8H, klávesnicový IRQ_1H vyvoláva prerušenie INT_9H pre
obsluhu klávesnice, asynchronná komunikácia cez COM2 (resp.COM1) sa
uskutočňuje s pomocou IRQ_3 (resp.IRQ_4) a vyvoláva INT_0BH (resp.
INT_0CH ) a pod. Niektoré požiadavky IRQ sú voľné a poskytujú tak
možnosť pre obsluhu ďalšich vonkajšich zariadení. Požiadavka IRQ_02H
slúži na kaskádové pripojenie druhého obvodu PIC.

|
Obr. 7-2. Vnútorná
štruktúra kontroléra prerušenia PIC 8259A. |

Činnosť obvodu PIC sa ovplyvňuje
programovaním jeho registra masiek prerušení IMR, registra požiadaviek
na prerušenie IRR a stavového registra obsluhy prerušení ISR.
- IMR - register masiek
požiadaviek
IRQ ( Interrupt mask register) sa používa na maskovanie t.j.
povolenie alebo zákaz jednotlivých požiadaviek na prerušenie IRQi.
Hodnota 1 na príslušnej pozícii slova OCW1 blokuje príslušný vstup
IRQi. a hodnota 0 ho povoľuje.
- IRR - register požiadaviek IRQ
(Interrupt request register). Požiadavky na prerušenie IRQ_i sa
privádzajú cez vstupy IR0 až IR7 do registra IRR (IR0 má najvyššiu
prioritu, IR7 najnižšiu). Až po vhodnom odmaskovani a pri vhodnej
priorite požiadavky može sa stať táto požiadavka podnetom vyvolanie
prerušenia - INT.
- Priority coder (resolver) -
logika
vyhodnocovania priorít porovnáva obsah registrov IMR a IRR a
vyberá žiadosť IRQ_i s najvyššou prioritou a zavedie ju do
stavového registra požiadaviek na obsluhu prerušení ISR.
- ISR - stavový register
požiadaviek na obsluhu prerušení (In service register). Až obsah
tohto registra vyhodnocuje mikroprocesor ako žiadosť o INT. Jeho
príslušný bit indikuje, či je zodpovedajúce prerušenie obsluhované
alebo nie (Hodnota 0 oznamuje, že nie je práve obsluhované).
Inicializácia registrov IRR, IMR a ISR
obvodu 8259 po zapnutí počítača sa vykonáva zápisom inicializačných
slov ICW. V PC je štandardná inicializácia záležitorťou BIOSu.

Ü Inicializačné slovo ICW (Initialization command word )
- ICW1 =13H (na adresu
20H/A0H) umožňuje zadať akým spôsobom budú ovládané registre PIC t.j.
či budú citlivé k hrane alebo k úrovni amplitúdy impulzu. Implicitné
nastavenie z BIOSu je k hrane. Ak sa použije nastavenie k úrovni, tak
treba pred EOI deaktivovať vstup požiadavky.
- ICW2 = 08H (na adresu
21H/A1H) deklaruje posuv požiadavky IRQi na prerušenie
INT(i+8)
- ICW3 (na adresu
21H/A1H) definuje ku ktorému bitu Master PIC je pripojený ďalší Slave
PIC.
- ICW4 =09H - (na adresu 21H/A1H) definuje typ konca prerušenia,
napríklad automatický EOI, normálny celkový EOI, špecifikovaný EOI a
pod.
Ü Operačné riadiace slovo OCW (Operation command word)
Počas prevádzky možno komunikovať s
obvodom PIC pomocou tzv. operačných riadiacich slov OCW.
Pre testovanie stavu registrov ISR a IRR sa používa úsporný spôsob
založený na vyslaní určitého kódu masky, špecifikujúceho register a z
následného prečítania stavu tohto registra z rovnakej adresy pomocou
riadiaceho slova OCW3. Operačné riadiace slovo :
- OCW1 - ( zaslané na
adresu 21H/A1H ) sa používa na zápis masky prerušení, v ktorej hodnota
bitu Mi=1 blokuje a hodnota bitu Mi=0 povoľuje
vstup požiadavky IRQ.
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
M7 |
M6 |
M5 |
M4 |
M3 |
M2 |
M1 |
M0 |
- OCW2 - (zaslané na
adresu 20H/A0H ) zaisťuje odhlásenie konca prerušenia a rotáciu priorít
prerušenia. Napríklad pre nešpecifikované EOI OCW2=20H, pre
špecifikované S_EOI pre IRQ3 je OCW2= 63H.
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
R |
SL |
EOI |
0 |
0 |
L2 |
L1 |
L0 |
|
0 |
0 |
1 |
=>EOI |
0 |
0 |
0 |
=>IRQ0 |
|
0 |
1 |
1 |
=>S_EOI
s Li |
0 |
0 |
1 |
=>IRQ1 |
|
1 |
X |
X |
=>ostatné kombinácie sa v PC nepoužívajú |
- OCW3 - (zaslané na
adresu 20H/A0H ) umožňuje čítať stav registra IRR ( OCW2 = 0AH ), alebo
registra ISR ( OCW2 = 0BH), resp.zmeniť spôsob testovania (polling -
dotazovacia metóda ).
|
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
0 |
ESMM |
SMM |
0 |
1 |
P |
RR |
SR |
|
|
Špecialna maska |
|
|
|
0 |
1 |
01=>IRR |
|
|
|
|
|
|
|
1 |
1 |
11=>ISR |
|
|
|
|
|
|
P=1 |
=> poling |

Procesor na konci vykonávania každej
inštrukcie testuje obsah registra ISR a v prípade akceptovania
požiadavky na preušenie vyšle signál akceptovania žiadosti INTA (2 impulzy INTA).
Po prijatí prvého impulzu INTA (ak bola nastavená vhodná maska v
registri IMR) sa v registri ISR nastaví do úrovne "1" bit prislúchajúci
IRQ s najväčšou prioritou a vynuluje sa obsah ISR z ostatných
požiadaviek IRQ. Počas druhého impulzu INTA vyšle obvod 8259A na
zbernicu dát vektor INT (1 byte), ktorý sa v CPU vynásobí 4 (pomocou
posuvu obsahu registra) a slúži ako ukazovateľ na slovo adresy CS:IP v
tabuľke vektorových preušení.

Po skončení obslužnej procedúry INT
treba oznámiť PIC 8259A koniec obslužného programu pomocou slova OCW2
buď ako
- nešpecifikovaný koniec
prerušenia
EOI (rovnaký pre všetky IRQ a zakončujúci naraz všetky IRQ, alebo
ako
- špecifikovaný koniec prerušenia
S_EOI (spolu skódom čísla IRQ), ktorý (napríklad v prípade
vnoreného
prerušenia) ukončí len obslúženú požiadavku IRQ_i ).
EOI vynuluje príslušný bit v registri ISR,
ktorého obsluha sa práve skončila.
Nešpecifikovaný koniec prerušenia EOI
zabezpečí slovo OCW2=20H, ktoré je implicitné v PC - IBM. Pri
špecifikovanom konci S_EOI sa v slove OCW2 definuje bit, ukončeného
prerušenia. Napríklad pre IRQ_3 je jeho kód S_EOI=63H. Zápis EOI je
vlastne oznam pre PIC-8259A, že nastal koniec obslužneho programu a že
od tohto okamihu sa odbloková prístup ku kontroléru pre všetky
požiadavky IRQ nižšej priority. (Porovnaj tvar EOI v t59_1a.asm a v
t59_1b.asm.)

q Demonštrovanie prerušenia
V obvode 8259A možno programovo
zadefinovať spôsob spúšťania registrov obvodu 8259A a to buď pomocou
amplitúdovej úrovne alebo dynamicky - hranou impulzu. V PC IBM sa
používa prevážne posledný spôsob. Má to však za dôsledok, že súčasťou
prerušovacieho systému nejakého zariadenia musí byť aj ďalší preklápací
obvod FF_int (obrázok 7-3) na zapamätanie jeho požiadavky IRQi,
napríklad ak má nízku prioritu, v dôsledku čoho požiadavka nemôže byť
okamžite obslúžená. Súčasťou obslužného programu musí byť teda aj
deaktivácia tohto preklápacieho obvodu po skončení obsluhy.
 |
Obr. 7-3. Zapojenie
prípravku na generovanie ručnej žiadosti IRQ3. Z hľadiska
uvedených príkladov sú dôležité signály MSKINT (na 3PC2) a nulovanie
(na 3PC0, resp. hotkey tlačítko TLCTK_INT pri MH7474). Fumkciu
preklápacieho obvod FF_int na zapamätanie požiadavky IRQ3
vykonáva časť obvodu MH7474, ktorá je pripojená na kolík 15 konektora
k2. |
Napríklad v prípade prípavku (obr. 7-3)
na generovania ručného IRQ3, buď pomocou hotkey tlačítka
TLCTK_INT alebo programovo skokom amplitúdy H-L na bite 0 portu 3PC, je
nulovaný preklápací obvod FF_int na demonštrovanie generovania žiadosti
IRQ3. Takže po inicializácii portov, aby sa mohol generovať
v ďalšom záporný skok amplitúdy, musí byť nastavená úroveň 3PC0="H".
Požiadavky IRQiz ostatných konektorov paralelných rozhraní
0PORT, 1PORT, 2PORT prípravku možno v danom zapojení zablokovať pomocou
signálu MSKINT="L" na bite 2 portu 3PC. Potrebná inicializačná
procedúra Ini pozostáva teda z nasledovných príkazov:
|
Ini1: |
mov |
dx,
3PORT_CWR |
|
|
|
mov |
al,
88H |
;riadiace
slovo PA, PB, PCd-in, PCh-out |
|
|
mov |
dx, al |
|
|
|
mov |
al, 0 |
|
|
|
out |
dx, al |
;3PC0=
L-H |
|
|
mov |
al, 1 |
|
|
|
out |
dx, al |
|
|
|
mov |
al, 04H |
;3PC2=
MSK_INT=0 |
|
|
out |
dx, al |
|

Procedúra T59_1.asm
slúži na demonštráciu žiadosti o prerušenie IRQ_03H z vonkajšieho
tlačítka. Za predpokladu, že sa nepoužívajú prerušenia k rozhraniam
COM1 a COM2 je prechodne na demonštračné účely možno použiť takýto
postup predefinovania INT_0BH, ktorý táto žiadosť volá. Serióznejšie s
ohľadom na kompatibilitu počítača by bolo možné použiť niektorý z
voľných žiadostí IRQ, napríklad IRQ_12H, volajúci INT 74H s adresou
vektora prerušenia 1D0H.
V danom príklade sa IRQ generuje ručne
tlačítkom pri skokovej zmene stavu výstupu FF_int z úrovne "L" na
úroveň "H" t.j. zo stavu, keď indikačná LED na výstupe svieti na stav
keď zhasne. Ak je prerušenie povolené (príznak IF = 1, nastavený
pomocou inštrukcie STI ) treba ešte odmaskovať prístup žiadosti IRQ3
pomocou masky, ktorá nastaví v registri IMR bit M4
= 0 a ostatné bity ponechá
zamaskované Mi = 1 ( maska_03H
= invert 08H = F7H) pomocou
postupnosti inštrukcii mask:
|
mask: |
mov dx,
IMR |
;IMR ma
adr. 20H |
|
|
in al,dx |
;stav
masky |
|
|
and
al,maska |
;maska=0F7H |
|
|
out
dx,al |
;zapis
masky |
|
|
sti |
;uvolnenie
prerušenia IF |
Aby vôbec bolo možné ovládať preklápací
obvod FF_int treba zabezpečiť, aby na jeho vstupoch S (na obr. 7-3
označený PRE) a R (na obr. 7-3 označený CLR) boli úrovne "H". V
danom zapojení prípravku to znamená inicializovať port 3PORT, ak už
dovtedy nebol inicializovaný a nastaviť jeho bit 3PC0="H", resp.
prekontrolovať aj ďalší maskovací vstup MSK_INT na bite 3PC2="L", ktorý
blokuje všetky požiadavky IRQi z konektorov zariadení
eventuelne pripojených k portom 0PORT až 2PORT. V uvedenom príklade sa
používa len jedno ručné tlačítko ako zdroj požiadavky na prerušenie,
bez možnosti vzniku IRQi od iných zariadení, takže nevzniká
potreba ďalšej podrobnejšej identifikácie zdroja IRQi z
konektorov portov 0PORT - 2PORT, napríklad pomocou metódy dotazov na
stav bitov 3PC4, 3PC5 a 3PC6, čím by bolo možno rozšíriť obsluhu o
ďalšie obslužné procedúry.
Uvedené zapojenie preklápacieho obvodu
FF_int umožňuje po skončení obslužnej procedúry programovo vynulovať
preklápací obvod FF_int (cez 3PC0 na obrázku 7-3) a tým ho aj
prednastaviť do vhodnej polohy pre ďalšie zopakovanie demonštrácie (s
ohľadom na požadovanú dynamickú zmenu "L"-"H" signálu IRQ3).

Na demonštrovanie funkcie vnútorných
registrov obvodu 8259 slúžia procedúry T59_1c a
T59_1d, ako modifikované varianty základného programu
T59_1_a.asm.
- Procedúra T59_1d.asm umožňuje
zaregistrovať zmenu obsahu registra IMR po a pred zamaskovaním žiadosti
IRQ3, ktorá sa vyskytuje na bite 3 registra IRR. Pred
zamaskovaním mohol byť obsah registra IMR napríklad 1011 1000 =
B8H a po zamaskovaní (bit =1 maskuje neželané žiadosti) B0H,
nakoľko pri odmaskovaní je aktívna úroveň L. V závislosti od stavu
preklápacieho obvodu FF_int, zachytávajúceho žiadosť o prerušenie z
hotkey tlačítka, bude rôzny obsah registra IRR. Napríklad IRR=0 ak
nebola prítomná žiadna žiadosť o prerušenie a IRR=08H, v prípade
aktívnej žiadosti IRQ3.
- Procedúra T59_1c.asm umožňuje
zaregistrovať zmenu obsahu registra IMR a ako dôsledok hotkey tlačítkom
vyvolaného prerušenia zaregistrovať aj stav registra ISR = 08H.
ÜT59_1_a.asm
- demonštácia hardwareovej
žiadosti o prerušenie s nešpecifikovaným ukončením .
Rezidentne uložený program ISRIRQ3, ktorý
možno aktivovať pomocou hotkey int_tlačitka, žiadosti IRQ_03H a
následného INT 0BH. Tento obslužný program prepíše pôvodnú obsluhu
sériového rozhrania. Jeho činnosť je demonštračná: po aktivovaní
hotkey-tlačítkom (z úrovne svieti LED na úroveň nesvieti LED) sa vypíše
na obrazovku oznam spolu so signálom beep. Ako oznam pre PIC o ukončení
obsluhy používa nešpecifikovaný koniec prerušenia EOI
(deklaruje sa v slove CW2).
|
|
|
; T59_1_a.asm ------------------------------- |
SA8259M
|
equ
0020H
;adresa pre OCW2/ OCW3 |
AIMR59M
|
AIMR59M equ
0021H ;adresa pre reg IMR s OCW1 |
VIRQ3
|
equ
0BH
;IRQ3 volá int 0BH |
MSKIRQ3
|
equ
0f7h
;odmaskovat 08h=irq3 |
EOI
|
equ
20H
;Koniec prerušenia |
IRR_L
|
equ
0AH
;maska OCW3 na čitanie IRR |
ISR_L
|
equ
0BH
;maska OCW3 na citanie ISR |
CWR3
|
equ
70FH
;riad register portu int_tlacitka |
|
;---------------------------------------------- |
CODE
|
SEGMENT |
ASSUME
|
DS:CODE,CS:CODE |
VIRQ
|
DD
?
;sem uloží pôvodý interrupt vektor |
|
;---------------------------------------------- |
ISRIRQ3
|
proc
far
;rezidentný demo program |
|
push ax |
|
push bx |
|
push cx |
|
push dx |
|
push ds |
|
push es |
|
push si |
|
push
cs
;Zosúhlasenie Data a Code segm. |
|
pop ds |
|
mov ah,
09h
;úvodný oznam |
|
lea dx,
sprava |
|
int
21h |
|
mov bx,
10
;trvanie beep |
|
call beep |
|
mov al,
EOI ;Koniec
INT pre PIC |
|
mov dx,
SA8259M |
|
out dx, al |
|
mov dx,
CWR3
;vynulovat preklap obvod int_tlctk |
|
mov al,
0
;=PC0=0 |
|
out dx, al |
|
inc al |
|
out dx,
al
;=PC0=1 |
|
pop si |
|
pop es |
|
pop ds |
|
pop dx |
|
pop cx |
|
pop bx |
|
pop ax |
|
;
pushf
;resp. jmp CS:virq |
|
; call cs:VIRQ |
|
;
sti
;uvolnenie IF pre INT |
|
IRET |
|
|
sprava
|
db "Ahoj
!!!",13,10,"$" |
|
|
bbb: |
mov al,
0B6h
;Beep |
|
out 43h,
al |
|
mov ax,
0533h
;533h=1333d pre 1kHz |
|
out 42h,
al |
|
mov al,
ah |
|
out 42h,
al |
|
in al,
61h |
|
mov ah,
al |
|
or al,
03h |
|
out 61h,
al |
|
sub cx,
cx |
sl: |
loop
sl |
|
dec bl |
|
jnz sl |
|
mov al, ah |
|
out 61h,
al |
|
ret |
ISRIRQ3
|
endp |
|
;----------------------------------------------------- |
|
|
Insta l
|
proc near |
|
mov ax,
cs
;CODE oblasť = DATA oblasť |
|
mov ds,
ax |
|
mov ah,
35H
;zisti adr vektIRQ3 =int0BH |
|
mov al,
VIRQ3
;do ES:BX |
|
int 21H |
|
mov word
PTR VIRQ, bx ;uloží offset OldInt |
|
mov ax,
es
; uloží segment OldInt |
|
mov word
PTR VIRQ+2, ax |
|
lea dx,
ISRIRQ3
; Nastavi nový Int vektor |
|
mov ah,
25H
;DS:DX nova int adresa |
|
mov al,
VIRQ3 |
|
int 21H |
|
mov dx,
AIMR59M
;odmaskovat IRQ3 do IMR |
|
in al, dx |
|
and al,
MSKIRQ3 |
|
out dx, al |
|
mov dx,
CWR3
;nast portu pre int_tlctk |
|
mov al,
88h
;PA,PB,PCd-out, PCh-in |
|
out dx, al |
|
mov al,
1
;nast PC0=1 = 'H' pre tlačítko |
|
out dx, al |
|
mov al,
04h
;zablok int od konektorov |
|
out dx,
al
;= PC2=0 |
|
sti
;set IF |
|
;-----------------------------
- ukoncenie a zostan rezidentny------------- |
|
mov dx,
offset
Instal
;[(end-start)+15]/16+10H-PSP |
|
add dx,
15
;+1 |
|
mov cl,
4
;/16 |
|
shr dx, cl |
|
add dx,
10h
;+100H=PSP |
|
mov ax,
3100h |
|
int
21h
;int 21/ah=31 |
instal
|
endp |
CODE
|
ENDS |
|
END instal |

ÜT59_1_b.asm
- demonštácia hardwareovej
žiadosti o prerušenie so špecifikovaným ukončením .
Tento obslužný program je prakticky zhodný
s t59_1a.asm - rezidentne uložený program ISRIRQ3, ktorý možno
aktivovať pomocou int_tlačitka, žiadosti IRQ_03H a následného INT
0BH. Rozdiel je len v použití špecifikovaného konca
prerušenia S_EOI k žiadosti IRQ_3 , namiesto EOI (deklaruje sa
v
slove CW2) => ak by táto procedúra slúžila na obsluhu jedného z
viacerých vnorených prerušení ukončila by sa len táto obslužná
procedúra bez ukončenia obslúh ostatných.prerušení..
|
; T59_1_b.asm :-------------------------------- |
SA8259M
|
equ
0020H
;adresa pre OCW2/ OCW3 |
AIMR59M
|
equ
0021H
;adresa pre reg IMR s. OCW1 |
VIRQ3
|
equ
0BH
;IRQ3 volá int 0BH |
MSKIRQ3
|
equ
0f7h
;odmaskovat 08h=irq3 |
S_EOI
|
equ
63H
;Koniec prerušenia pre IRQ_3 |
IRR_L
|
equ
0AH
;maska OCW3 na čitanie IRR |
ISR_L
|
equ
0BH
;maska OCW3 na citanie ISR |
CWR3
|
equ
70FH
;riad register portu int_tlacitka |
|
;------------------------------------------ |
CODE
|
SEGMENT |
ASSUME
|
DS:CODE,CS:CODE |
VIRQ
|
DD
?
;sem uloží pôvodý int vektor |
|
;-------------------------------------- |
|
|
ISRIRQ3
|
proc
far
;rezidentný demo program |
|
push ax |
|
push bx |
|
push cx |
|
push dx |
|
push ds |
|
push es |
|
push si |
|
push
cs
;Zosúhlasenie Data a Code seg |
|
pop ds |
|
mov ah,
09h
;úvodný oznam |
|
lea dx,
sprava |
|
int
21h |
|
mov bx,
10
;trvanie beep |
|
call beep |
|
mov al,
S_EOI ;Koniec
INT pre PIC špecifikovaný |
|
mov dx,
SA8259M |
|
out dx, al |
|
mov dx,
CWR3
;vynulovat preklap obvod int_tlctk |
|
mov al,
0
;=PC0=0 |
|
out dx, al |
|
inc al |
|
out dx,
al
;=PC0=1 |
|
pop si |
|
pop es |
|
pop ds |
|
pop dx |
|
pop cx |
|
pop bx |
|
pop ax |
|
;
pushf
;resp. jmp CS:virq |
|
; call
cs:VIRQ |
|
;
sti
;uvolnenie IF pre INT |
|
IRET |
|
|
sprava
|
db "Ahoj
!!!",13,10,"$" |
|
|
bbb: |
mov al,
0B6h
;Beep |
|
out 43h,
al |
|
mov ax,
0533h
;533h=1333d pre 1kHz |
|
out 42h,
al |
|
mov al,
ah |
|
out 42h,
al |
|
in al,
61h |
|
mov ah,
al |
|
or al,
03h |
|
out 61h,
al |
|
sub cx,
cx |
sl: |
loop
sl |
|
dec bl |
|
jnz sl |
|
mov al,
ah |
|
out 61h,
al |
|
ret |
ISRIRQ3
|
endp |
|
;----------------------------------------------- |
Instal
|
proc near |
|
mov ax,
cs
;CODE oblasť = DATA oblasť |
|
mov ds,
ax |
|
mov ah,
35H
;zisti adr vektIRQ3 =int0BH |
|
mov al,
VIRQ3
;do ES:BX |
|
int 21H |
|
mov word
PTR VIRQ, bx ;uloží offset OldInt |
|
mov ax,
es
; uloží segment OldInt |
|
mov word
PTR VIRQ+2, ax |
|
lea dx,
ISRIRQ3
; Nastavi nový Int vektor |
|
mov ah,
25H
;DS:DX nova int adresa |
|
mov al,
VIRQ3 |
|
int 21H |
|
mov dx,
AIMR59M
;odmaskovat IRQ3 do IMR |
|
in al, dx |
|
and al,
MSKIRQ3 |
|
out dx, al |
|
mov dx,
CWR3
;nast portu pre int_tlctk |
|
mov al,
88h
;PA,PB,PCd-out, PCh-in |
|
out dx, al |
|
mov al,
1
;nast PC0=1 = 'H' pre tlačítko |
|
out dx, al |
|
mov al,
04h
;zablok int od konektorov |
|
out dx,
al
;= PC2=0 |
|
sti ;set IF |
|
;---------------------------------
- ukoncenie a zostan rezidentny --- |
|
mov dx,
offset
Instal
;[(end-start)+15]/16+10H-PSP |
|
add dx,
15
;+1 |
|
mov cl,
4
;/16 |
|
shr dx, cl |
|
add dx,
10h
;+100H=PSP |
|
mov ax,
3100h |
|
int
21h
;int 21/ah=31 |
|
instal endp |
CODE
|
ENDS |
|
END instal |
|
;-------------------------------------------- |

ÜT59_1c.asm
- kontrola obsahu registrov
8259 pri rezidentne uloženej obsluhe ISR.
Demonštrácia vplyvu požiadavky IRQ3, ktorá
je pripojená na PIC 8259. Na začiatku sa generuje beep + oznam o stave
registra IMR pred a po zamaskovaní a potom sa časť programu uloží
rezidentne do pamäte. Po stlačení hotkey tlačítka na prednom paneli
interfejsu (zo stavu nesvieti LED) sa aktivuje rezidentne uložená
procedúra a vypíše obsah registrov IMR, IRR, a ISR. (Súčasne sa
generuje impulz, ktorý skončí svietenie LED a vynuluje tiež preklápací
obvod FF_int aktivácie tlačítka, ktorý slúži na zapamätanie HRDW
vyvolaného prerušenia). Základom rezidentnej časti je subrutina KSL,
ktorá po stlačení int_tlacitka a zistení stavu registrov obvodu 8259
zobrazí ich stav. (Najprv kód uloží do vhodnej bunky pamäte a potom ako
súčasť spravy zobrazí pomocou štandardej služby DOS). Spôsob
čítania registrov je nasledovný: najprv sa vyšle kód masky v slove OCW3
pre píslušný register a potom z tej istej adresy sa číta informaciu.o
stave príslušného registra. Na konverziu binárneho tvaru číslic na tvar
ASCII sa využíva subrutina hxasc.
|
;
T59_1c.asm - H l a v n y p r o g r a m ------- |
SA8259M
|
equ
0020H
;Adresa. OCW2/OCW3 |
AIMR59M
|
equ
0021H
; Adresa IMR a OCW1 |
VIRQ3
|
equ
0BH
;IRQ3 vyvolá int 0BH |
MSKIRQ3
|
equ
0F7h
;odmaskovat 08h=irq3 |
EOI
|
equ
20H
;END OF INTERRUPT |
|
IRR_L equ
0AH
;maska OCW3 na citanie IRR |
|
ISR_L equ
0BH
;maska OCW3 na citanie ISR |
|
CWR3 equ
70FH
;riad reg portu int_tlacitka |
|
;------------------------------------------------------------------------ |
CODE
|
SEGMENT |
ASSUME
|
DS:CODE,
CS:CODE |
VIRQ
|
DD
?
;uloženie pôvodného int vektora |
|
;-------
Obslužný TSR program ---------------------------- |
ISRIRQ3
|
PROC
far |
|
PUSH AX |
|
PUSH BX |
|
PUSH CX |
|
PUSH DX |
|
PUSH DS |
|
PUSH ES |
|
PUSH SI |
|
PUSH
CS
;DS nast v sulade sCS |
|
POP DS |
|
;----------------------------------------- |
|
mov cx,
800h ;CLS |
|
mov dx,
1530h |
|
mov ax,
0600h |
|
mov bh,
07h |
|
int 10h |
|
;--------------------------------------- |
|
mov dx,
0a0ah
;poloha kurzora |
|
mov ah, 2 |
|
int 10h |
|
mov ah, 09h |
|
lea
dx,spravas
;oznam sbr |
|
int
21h |
|
;---------------------------------------- |
|
mov dx,
AIMR59M
;Stav IMR |
|
in al,dx |
|
and
al,MSKIRQ3
;inv08H = odmask IRQ3 |
|
call KSL |
|
mov
sprav6,ax |
|
mov ah,09h |
|
lea
dx,sprav5 |
|
int
21h
;vypis IMR=xx |
|
;--------------------------------------- |
|
mov
dx,SA8259M
;stav IRR |
|
mov al,IRR_L |
|
call KSL |
|
mov
sprav2,ax |
|
mov ah,09h |
|
lea
dx,sprav1 |
|
int
21h
;vypis IRR=xx |
|
;---------------------------------------- |
|
mov
dx,SA8259M
;Stav ISR |
|
mov al,ISR_L |
|
call KSL |
|
mov
sprav4,ax |
|
mov ah,09h |
|
lea
dx,sprav3 |
|
int
21h
;stav ISR=xx |
|
;------------------------- |
|
mov bx,10 |
|
call beep |
|
;------------------------- |
|
MOV
AL,EOI
;END OF INTERRUPT |
|
MOV
DX,SA8259M |
|
OUT DX,AL |
|
;---------------------------------------- |
|
mov
dx,CWR3
;vynulovat FF_int_tlctk |
|
mov
al,0
;=PC0=0 |
|
out dx,al |
|
inc al |
|
out
dx,al
;=PC0=1 |
|
;-------------------------------------------- |
|
POP SI |
|
POP ES |
|
POP DS |
|
POP DX |
|
POP CX |
|
POP BX |
|
POP AX |
|
;
PUSHF
;resp. jmp CS:virq |
|
; CALL
CS:VIRQ |
|
sti
;uvolnenie IF pre INT |
|
IRET |
|
;-------------------------
CS ako Data segment ------------------------ |
sprava
|
db "PortC
pre tlacitko_int bol inicializovany " |
|
db 13,10,"$" |
spravas
|
db
"******** Test registrov PIC 8259A **********" |
|
db 13,10,"=
vsnimnut si ISR=08=IRQ3 ",13,10,13,10,24 |
sprav1
|
db "IRR=" |
sprav2
|
dw ? |
|
db 13,10,"$" |
sprav3
|
db "ISR=" |
sprav4
|
dw ? |
|
db 13,10,"$" |
sprav5
|
db "IMR=" |
sprav6
|
dw ? |
|
db 13,10,"$" |
sprava7
|
db
"------------- Stav pred maskou -------------",13,10,"$" |
sprava8
|
db
"------------- Stav po maske -------------",13,10,"$" |
ISRIRQ3
|
endp |
|
;------------------------------------------------------------ |
beep
|
proc
near |
bbb: |
MOV AL, 0B6h |
|
OUT 43h, AL |
|
MOV AX,
0533h
;533h=1333d pre 1kHz |
|
OUT 42h,
AL |
|
MOV AL,
AH |
|
OUT 42h, AL |
|
IN AL,
61h |
|
MOV AH,
AL |
|
OR AL,
03h |
|
OUT 61h,
AL |
|
SUB CX,
CX |
sl: |
LOOP
sl |
|
DEC BL |
|
JNZ sl |
|
MOV AL,
AH |
|
OUT 61h, AL |
|
RET |
beep
|
endp |
|
;--------------------------------------------- |
|
|
KSL
|
proc
near ;DX= adrOCW3=AIMR8259=20h |
|
out dx,
al
;AL=reg, napríklad IRR ,ISR |
|
nop
;prekonv do ASCII |
|
nop
;ustálenie |
|
Nop |
|
in al, dx |
KSL1: |
mov ah, al |
|
and al, 0FH |
|
and ah, 0F0H |
|
mov cl, 4 |
|
shr ah,
cl
;AH=0X - horny digit, AL=0X dolny dig |
|
call hxasc |
|
mov
cl,al |
|
mov al, ah |
|
call hxasc |
|
mov ah, al |
|
mov ah,
cl
;výsledok v AX |
|
ret |
hxasc: |
cmp al,
10
;čislice na ASCII |
|
jc
hxas1
;=A - F |
|
add al,
7
;znakove čislice |
hxas1: |
add al,
30h |
|
Ret |
KSL
|
endp |
|
;====
Inštalačná časť =============== |
Instal
|
proc near |
|
MOV AX,
CS
;CODE = DATA oblasti |
|
MOV DS,
AX |
|
MOV AH,
35H
;zisti adr vektIRQ3=intB |
|
MOV AL,
VIRQ3
;do ES:BX |
|
INT
21H
;INT-VEKTOR |
|
MOV WORD
PTR
VIRQ,BX
;BX returns OFFSET |
|
MOV AX,
ES
;ES returns SEGMENT |
|
MOV WORD
PTR VIRQ+2,AX |
|
|
|
MOV AX,
CS
;DS a ES zosúladiť |
|
MOV DS,
AX
;kvôli nastaveniu novej intsbr |
|
MOV ES, AX |
|
|
|
LEA DX,
ISRIRQ3
; Nastavi novy Int vektor |
|
MOV AH,
25H
;DS:DX nova int adresa |
|
MOV AL,
VIRQ3 |
|
INT 21H |
|
;--------------------------------------- |
|
mov dx,
CWR3
;nast portu pre int_tlctk |
|
mov al,
88h
;PA,PB,PCd-out, PCh-in |
|
out dx, al |
|
mov al,
1
;nast PC0=1 = 'H'FF_tlc |
|
out dx, al |
|
mov al,
04h
;zablok int od konektorov |
|
out dx,
al
;= PC2=0 |
|
mov ah, 09h |
|
lea dx,
sprava
;že PC inicializ |
|
int
21h |
|
;--------------------------------------- |
|
mov ah, 09h |
|
lea dx,
sprava7 |
|
int
21h
;stav pred maskou |
|
mov dx,
AIMR59M
;odmaskovat IRQ3 do IMR |
|
in al, dx |
|
call KSL1 |
|
mov sprav6,
ax |
|
mov ah, 09h |
|
lea dx,
sprav5 |
|
int
21h
;vypis IMR=xx |
|
;---------------------------------------- |
|
mov ah, 09h |
|
lea dx,
sprava8 |
|
int
21h
;stav po maske |
|
mov dx,
AIMR59M
;Stav IMR |
|
in al, dx |
|
and al,
MSKIRQ3 |
|
call
KSL
;poslat masku |
|
mov sprav6,
ax |
|
mov ah, 09h |
|
lea dx,
sprav5 |
|
int
21h
;vypis IMR=xx |
|
sti ;set IF |
|
;-------------------------
ukoncenie a zostan rezidentny |
|
mov
dx,offset
Instal
;[(end-start)+15]/16+10H-PSP |
|
add dx,
15
;+1 |
|
mov cl,
4
;/16 |
|
shr dx, cl |
|
add dx,
10h
;+100H=PSP |
|
mov ax,
3100h |
|
int
21h
;int 21/ah=31 |
Instal
|
endp |
CODE
|
ENDS |
|
END instal |

ÜT59_1d.asm
- kontrola obsahu registrov
8259 pri rôznych stavoch preklápacieho obvodu FF_int.
Demonštráciacia vplyvu požiadavky IRQ3 na
stav registrov obvodu 8259. Je to nerezidentne uložená obdoba
T59_1c.asm, aby bolo možné sledovať obsah registrov IMR, IRR, a ISR v
závislosti od stavoch preklápacieho obvodu FF_int a teda od výskytu
žiadosti IRQ3. Na začiatku sa testuje či už bol nainicializovaný port
ku ktorému je pripojený preklápací obvod FF_int, ktorý slúži na
vyvolanie prerušenia a v prípade potreby sa port inicializuje. Po
inicializovaní portu sa totiž preklápací obvod FF_int vždy nastaví do
rovnakého stavu a nie je možné nezávisle po stlačení hotkey tlačítka na
prednom paneli interfejsu generovať prechod L-H alebo H-L impulzu
žiadajúceho o prerušenie. Program teda možno spustiť pri rôznych
stavoch preklápacieho obvodu FF_int a tak zistiť obsah registrov IMR,
IRR, a ISR
|
;-
T59_1d.asm ------ H l a v n y p r o g r a m ------------ |
SA8259M
|
equ
0020H
;Adresa. OCW2/OCW3 |
AIMR59M
|
equ
0021H
; Adresa IMR a OCW1 |
VIRQ3
|
equ
0BH
;IRQ3 vyvolá int 0BH |
MSKIRQ3
|
equ
0F7h
;odmaskovat 08h=irq3 |
EOI
|
equ
20H
;END OF INTERRUPT |
IRR_L
|
equ
0AH
;maska OCW3 na citanie IRR |
ISR_L
|
equ
0BH
;maska OCW3 na citanie ISR |
CWR3
|
equ
70FH
;riad reg portu int_tlacitka |
|
;------------------------------------------------------ |
CODE
|
SEGMENT |
ASSUME
|
DS:CODE,
CS:CODE |
Tst_reg
|
proc near |
|
MOV AX,
CS
;CODE = DATA oblasti |
|
MOV DS,
AX |
|
MOV ES, AX |
|
mov ah, 09h |
|
lea dx,
spravai
;oznam o inicializovaní PortuC |
|
int
21h |
|
mov ah, 0 |
|
int 16h |
|
cmp al, 1BH |
|
jne pokrac |
|
;----------------------------- |
|
mov dx,
CWR3
;nast portu pre int_tlctk |
|
mov al,
88h
;PA,PB,PCd-out, PCh-in |
|
out dx, al |
|
mov al,
1
;nast PC0=1 = 'H'FF_tlc |
|
out dx, al |
|
mov al,
04h
;zablok int od konektorov |
|
out dx,
al
;= PC2=0 |
|
mov ah, 09h |
|
lea dx,
sprvaii
;oznam nainicilz PC |
|
int
21h |
|
;----------------------------- |
pokrac: |
|
|
mov
cx,0
;CLS |
|
mov dx,
2479h |
|
mov ax,
0600h |
|
mov bh, 07h |
|
int
10h |
|
;----------------------------- |
|
mov dx,
050ah
;poloha kurzora |
|
mov ah, 02 |
|
int 10h |
|
;----------------------------- |
|
mov ah, 09h |
|
lea dx,
sprava |
|
int
21h |
|
mov ah, 09h |
|
lea dx,
sprava7 |
|
int
21h
;stav pred maskou |
|
;----------------------------- |
|
mov dx,
AIMR59M
;Stav IMR |
|
in al, dx |
|
call KSL1 |
|
mov sprav6,
ax |
|
mov ah, 09h |
|
lea dx,
sprav5 |
|
int
21h
;vypis IMR=xx |
|
mov ah, 09h |
|
lea dx,
sprava8 |
|
int
21h
;stav po maske |
|
;---------------------------- |
|
mov dx,
AIMR59M
;Stav IMR |
|
in al, dx |
|
and al,
0F7H
;odmask =bit3=0 |
|
call KSL1 |
|
mov sprav6,
ax |
|
mov ah, 09h |
|
lea dx,
sprav5 |
|
int
21h
;vypis IMR=xx |
|
;---------------------------------------- |
|
mov dx,
SA8259M
;stav IRR |
|
mov al,
IRR_L |
|
call KSL |
|
mov sprav2,
ax |
|
mov ah, 09h |
|
lea dx,
sprav1 |
|
int
21h
;vypis IRR=xx |
|
;---------------------------------------- |
|
mov dx,
SA8259M
;Stav ISR |
|
mov al,
ISR_L |
|
call KSL |
|
mov sprav4,
ax |
|
mov ah, 09h |
|
lea dx,
sprav3 |
|
int
21h
;stav ISR=xx |
|
;------------------------- |
|
mov bx, 10 |
|
call beep |
|
;------------------------- |
|
mov ax,
4c00H |
|
int 21H |
Tst_reg
|
endp |
|
;---------------------------------------------------- |
spravai
|
db "Ak
chces inicializovat portC pre tlacitko_IRQ3" |
|
db " -
stlac ESC. ",13,10,"Ak bol PC uz inicializo" |
|
db "vany
tak mozno sledovat stav jeho registrov" |
|
db
13,10,"pri roznych urovniach IRQ3 z tlc_int",13,10,"$" |
sprvaii
|
db
13,10,"Register CWR pre PortC tlac_int " |
|
db
"nainicializovany",13,10,"$" |
sprava
|
db "Test
registrov PIC 8259A ",13,10,"$" |
sprav1
|
db "IRR=" |
sprav2
|
dw ? |
|
db 13,10,"$" |
sprav3
|
db "ISR=" |
sprav4
|
dw ? |
|
db 13,10,"$" |
sprav5
|
db "IMR=" |
sprav6
|
dw ? |
|
db 13,10,"$" |
sprava7
|
db
"------------- Stav pred maskou -------------",13,10,"$" |
sprava8
|
db
"------------- Stav po maske -------------",13,10,"$" |
|
;----------------------------------------------------- |
beep
|
proc
near |
bbb: |
MOV AL,
0B6h |
|
OUT 43h,
AL |
|
MOV AX,
0533h
;533h=1333d pre 1kHz |
|
OUT 42h,
AL |
|
MOV AL,
AH |
|
OUT 42h,
AL |
|
IN AL,
61h |
|
MOV AH,
AL |
|
OR AL,
03h |
|
OUT 61h,
AL |
|
SUB CX,
CX |
sl: |
LOOP
sl |
|
DEC BL |
|
JNZ sl |
|
MOV AL,
AH |
|
OUT 61h,
AL |
|
RET |
beep
|
endp |
|
;------------------------------------------------------ |
KSL
|
proc
near ;DX= adrOCW3=AIMR8259=20h |
|
out dx,
al
;AL=reg, napríklad IRR ,ISR |
|
nop
;prekonv do ASCII |
|
nop
;ustálenie |
|
Nop |
|
in al, dx |
KSL1: |
mov ah, al |
|
and al, 0FH |
|
and ah, 0F0H |
|
mov cl, 4 |
|
shr ah,
cl
;AH=0X - horna cisl., AL=0X dolna |
|
call hxasc |
|
mov
cl,al |
|
mov al, ah |
|
call hxasc |
|
mov ah, al |
|
mov ah,
cl
;výsledok v AX |
|
ret |
hxasc: |
cmp al,
10
;čislice na ASCII |
|
jc
hxas1
;=A - F |
|
add al,
7
;znakove čislice |
hxas1: |
add al, 30h |
|
Ret |
KSL
|
endp |
|
;---------------------------------------------------- |
CODE
|
ENDS |
|
END Tst_reg |

|