Ú-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.



µ 
Obsluha prerušenia

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.



µ 
Rezidentné programy

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 =>:


    JMP 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:

    IRET = RET + POPF.

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
                              ;-------------------------------------------------- 







µ 
Kontrolér prerušenia

 

dbg_7-1
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.
 

dbg_7-2
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


 


[Návrat]