  Ŀ
                                                                            
                                                                            
             KESMELERE (INTERRUPT'LAR)                                      
                                            Ŀ   
                                                            Kaan Aslan    
  ͺ C ve Sistem Prog. Dernei ;
                       Bakan 
                                             ;



          Bu ay sizlere biraz kesmelerden (interrupt'lardan),
           biraz da bellekte kalan programlardan (TSR) bahsetmek
            istiyorum.      ncelikle... Kesme (interrupt) nedir ?


 KESME NEDR ?
  Kesme, mikroilemcinin (CPU) o anda icra ettii programdan baka bir ii
  yapmas iin tekrar geri dnmek zere uzaklamasdr. Sk verilen bir
  rnekle aklarsak: Ders alyorsunuz, telefon alyor. almay geici
  olarak brakp telefona kouyorsunuz. Arkadanzla konutuktan sonra tekrar
  masanza geerek kaldnz yerden almaya devam ediyorsunuz.

  Mikroilemciler de tpk bu rnekte olduu gibi almaktadr. Kesme
  geldiinde mikroilemci bulunduu yeri ynda (stack) saklar; bellekte
  baka bir yerde olan kesme ilemini icra eder ve kald yerden programn
  icrasna devam eder. Kesme komutunun sembolik gsterimi aadaki gibidir.

        INT num

  num, 0'dan 255'e kadar deiebilen bir rakamdr. (Toplam 256 tane kesme
  ilemi olabilecei anlamna geliyor).

        rnein : INT 10h gibi.


  Kesme ilemlerini iyi bir ekilde anlamak iin bir kesme geldiinde
  mikroilemcinin (Tabii 8086 ailesinden bahsediyoruz) nasl davrandn
  mutlaka bilmelisiniz. Kesme komutu tek bir makina koduna karlk
  gelmektedir, ancak mikroilemci bu komuttan sonra bir dizi ilem yapar.
  Bunlar srasyla :

    1) Bayrak yazmacn yna atar (PUSHF). (Neden ?)
    2) Kesme ve adm bayraklar temizlenir. (Interrupt and trap flag, CLI)
    3) CS ve IP yazmalar yna atlr. Bu ilem programn icrasna geri
       dnebilmek iin mutlaka gereklidir.
    4) IP ve CS keme vektrnde belirlenmi olan deerleri alr. Bu ilem
       kesmenin icrasnn bellekteki yerini belirlemek iin gereklidir.
    5) Mikroilemci elde ettii ardese dallanarak kesme icrasna balar.


  (Yukardaki ilemleri CALL komutuyla karlatrnz.)


  Genellikle anlamakta glk ekilen noktalar unlardr:

  * INT tek bir makina dili komutudur. INT komutundan sonra mikroilemcinin
    davranna ilikin admlar makina kodlar deillerdir. Mikroilemci bu
    admlar INT komutunun iinde kendiliinden yapar.

  * Bellein ilk 1024 bayt' toplam 256 kesme iin balang adreslerini
    ierir. Mikroilemci kesme karsnda nereye gideceini bu ilk 1024
    bayt'a bakarak anlar.
    (imdi yle dnebilirsiniz. yi de, iletim sistemi yklenirken birok
    kesmeye ihtiya duyacaktr. Peki bu ilk 1024 bayt'a kim ilkdeerlerini
    veriyor?).
    Bellekteki bu ilk 1024 bayt'a kesme vektr diyoruz. Neden mi 1024
    bayt? Toplam 256 kesme yok mu? Bu kesmelerin tm bellek haritasndaki yeri
    2 byte segment ve 2 bayt offset (toplam 4 bayt) ile belirlendiine gre:
    4 * 256 = 1024'tr. Yani aslnda kesme vektr birer FAR gsterici
    gibidir.

  * Kesme vektr mikroilemcinin tasarmna ilikindir. DOS'un bir
    fonksiyonu deildir.

  * Bir kesme geldiinde mikroilemci baka bir kesmenin bunun zerine
    gelmemesi iin kesme bayran temizler. Fakat kesmelerin bir ou bu
    bayra tekrar 1 konumuna getirmektedir. (STI)

  Bir kesme bitince yndaki deerlerin ters ilemle geri alnmas gerekir.
  Kesmeyi sonlandran komut IRET komutudur. Bu komut srasyla :

    1) IP ve CS yndan geri alnr (POP IP, POP CS). Bu ilem ile programda
       kalnan yere geri dnlm olunuyor.
    2) Bayrak yazmac yndan geri alnr. (POPF)
    3) Kesme ve adm bayraklar geri yklenirler. (STI).

  (Yukardaki ilemleri RET ve RETF komutlaryla karlatrnz).



 KESME LEMLER KAA AYRILIR ?

  Kesme ilemlerini birok ynden snflayabiliriz. Mikroilemci
  asndan bakarsak:

    a) sel kesmeler  (Internal interrupts)
    b) Dsal kesmeler (External interrupts)

  sel kesmeler, mikroilemcinin kendisi tarafndan oluturulan kesmelerdir.
  rnein sfra blme durumlarnda kullanlan kesme (divide by zero) bu
  trdendir. Dsal kesmeler, mikroilemciye gre dardan gelmektedir.


  Kesmeler kaynaklar dikkate alndnda:

    a) Yazlm kesmeleri (Software interrupts)
    b) Donanm kesmeleri (Hardware interrupts)

  eklinde ikiye ayrlabilirler. Yazlm kesmeleri program akndan
  gelmektedir. Yani kesmeyi bir programc istemitir ve yazmtr. Oysa
  donanm kesmeleri mikroilemcinin kesme bacann dardan uyarlmasyla
  olumaktadrlar. (Bu tr kesmelerin en nlleri zamanlayc ve klavye
  kesmeleridir. Timer 8h, Keyboard 9h).

  Yine kesmeleri aciliyet derecelerine gre:

    a) Maskelenebilen kesmeler
    b) Maskelenemeyen kesmeler

  Olmak zere iki snfa ayrabiliriz. Maskelenebilen kesmeler, kesme
  bayrann temizlenmesiyle engellenebilen kesmelerdir. Oysa maskelenemeyen
  kesmeler, ne olursa olsun ilem grrler. lk rnee dnersek ders alan
  bir ocuk iin telefon maskelenebilen bir kesmedir. Oysa unutmu olduu
  musluun kapatlmas maskelenemez bir kesmedir. (Eer suyu kapatmazsa evi su
  basacaktr).

  Ve son olarak PC'lerimiz iin kesmeleri:

    a) DOS kesmeleri
    b) BIOS kesmeleri

  olmak zere iki gruba ayrabiliriz. DOS kesmeleri, DOS'un yklenmesiyle
  birlikte bellee yerletirilirler. Oysa BIOS kesmeleri, PC'nizin
  ierisindeki yalnz okunabilen bellekte bulunurlar. Neden mi? nk buradaki
  kesmeler ok temel ilemleri yerine getirirler. Bunlara nasl olsa ihtiya
  duyulacana gre bilgisayarnza monte etmiler. Her alta disketten
  yklenmelerine gerek var m?

  (yi bir sistem programc adaynn makinann donanmn ve iletim
  sisteminin inceliklerini bilmesi gerekir. Bu tr sorularn stne
  gitmelisiniz. Hereyin aslnda ok ak bir nedeni vardr...).



 C'DE KESMELER

  Evet... Gel gelelim kesmelerle C'nin ilikisine. C de tpk bir
  fonksiyon gibi bir kesme yazabilirsiniz. Aslnda sizin iin bir ey
  deimeyecektir. Kesmeyi siz fonksiyonmu gibi yazacaksnz. Fakat
  derleyici bu kesme fonksiyonu iin CALL yerine INT komutunu retecektir.
  Yine ayn ekilde bu kesme fonksiyonundan geri dnerken derleyici RET ya da
  RETF deil IRET komutunu kullanacak. C'de kesmeler, 'interrupt' anahtar
  kelimesinin fonksiyon isminin nne getirilmesiyle oluturulabilir (Hemen
  unu belirtmeliyim interrupt deitiricisi ANSI standartlarnda tanml
  deildir. Bir de anahtar kelime nedir onu aklamalym. Anahtar kelime
  dilin semantik yapsnn belirlenmesinde kullanlan ve deiken ismi olarak
  kullanlamayacak olan kelimelerdir; rnein 'for' kelimesi C'de dng deyimi
  olarak kullanlmaktadr. Ayrca bir deiken ismi olarak kullanlamaz).

    rnein : void interrupt deneme(void)


  C'de int86 gibi fonksiyonlarla herhangi bir kesmeyi icra edebilirsiniz.
  Fakat bu konunun onunla pek ilgisi yok. Siz yukardaki ekilde bir kesmeyi
  tasarlyorsunuz, onu yalnzca armyorsunuz.



 BELLEKTE KALAN PROGRAMLAR (TSR)

  Bellekte kalan (memory resident) programlar DOS'un belki de en fazla
  renilmek istenen ynlerinden biridir. Aslnda bir programn bellekte
  srekli kalmas ya da kalmamas yalnzca programdan k kesmesine
  baldr. C'de yazdnz programlardan DOS'a dnmeniz normal INT 20 gibi
  kesmelerle yaplmaktadr. INT 20 kontrol DOS'a devrettikten sonra bellei
  de boaltr. Oysa 27h DOS kesmesi ve 21h DOS kesmesinin 31h fonksiyonu DOS'a
  dnme ilemiyle birlikte bellei boaltmaz. Bylece bu kesmeler ile DOS'a
  dnlen programlar bellekte kalma zelliini de kazanm olurlar. Bu
  kesmeler ile yazlm, bellekte kalan programlara TSR programlar da
  denilmektedir.
  (TSR, ngilizce Terminate and Stay Resident kelimelerinin ba harflerinden
  yaplm bir ksaltmadr.)


  31h DOS fonksiyonunun fonksiyon haline getirilmi ekli ktphanelerinizde
  bulunan 'keep' fonksiyonudur. keep fonksiyonunun bildirimi aadaki gibidir
  (Noktadan sonra bilerek kk harfle balyorum. Her ne kadar yazm
  kurallarna gre noktadan sonra byk harf ile balamak gerekirse de C'de
  byk harf, kk harf farketmektedir. Noktadan sonra byk harfle balam
  olsaydm, belki Trke retmenlerini sevindidirdim ama C'leri mutlaka
  kzdrrdm).


    void keep (unsigned char status, unsigned size)

  Birinci parametre olan status sizin exit kodunuzdur. kinci parametre ise
  bellekte kalacak programnz iin ne kadar paragraflk bir bellek blgesinin
  ayrlacan soran unsigned bir deer (Bu deer en fazla ka olabilir?).
  Memory resident programlar ok dikkatli yazlmaldrlar. nk eer yanl
  yazlrlarsa memory resident olmalar bir yana memory'yi rezil eden bir
  zellie de sahip olabilirler.



 Bellekte kalan programlar nasl almaya balarlar?

  Bunlar donanm kesmelerine balanmak suretiyle aktive edilerek
  almaktadrlar. nk DOS altnda bir ka hile dnda tekli alma
  dzeni verdr. Yani sizin bellekte kalan programnz alacaksa dier
  programlar kesintiye urayacaktr.



 Bellekte Kalan Programlar Nasl Aktive Edilirler?

  Bellekte kalan programlarn en fazla kulland iki kesme 8h zamanlama ve 9h
  klavye kesmeleridir.



  8h Zamanlama Kesmesi (Timer interrupt):
  
  Bu kesme donanm yoluyla sistem saatinin almas iin periyodik olarak
  saniyede 18.2 kere arlmaktadr. Birok TSR program zamanlama kesmesini
  kendi amalar dorultusunda kullanmaktadr. Zamanlama kesmesi sistem iin
  nemli olduundan programclar bu kesmeyi tamamen devre d brakmazlar.
  Yalnzca kendi program kodlarn bu kesmenin ba yaparlar.



  9h Klavye Kesmesi:
  
  Bu kesme klavyenizden her tua bastnzda ve elinizi geri ektiinizde
  klavye ilemcisi tarafndan mikroilemciye bildirilir. Yani klavye kesmesi
  periyodik olarak arlmaz, yalnzca klavyeye dokunduunuzda arlr.
  Olaylar zetle yle gelimektedir :

  Bir tua dokunursunuz. Klavye ilemcisi bunu tespit eder ve CPU'ya donanm
  yoluyla 9h kesmesini iletir. 9h kesmesi klavyede baslan karakterlerin ASCII
  ve SCAN kodlarn alarak bunlar 1054 nolu bellek gznden balayacak
  ekilde yerletirir. Bu blgeye klavye tampon blgesi denilmektedir. Klavye
  tampon blgesi balangc, kesme vektrnden sonra olan (1024) iki tane
  index sayesinde kontrol edilmektedir. Birinci indekse Ba Gsterici denir
  (head pointer). Ba Gstericisi, klavye tampon blgesinin balangcn
  gstermektedir. kinci index U Gstericisidir (tail pointer). Bu gsterici
  de klavye tampon blgesinin sonunu gstermektedir. Klavye tamponu Ba ve U
  Gstericilerinin arasnda kalan blgedir. Yalnz bu iki gstericinin
  ierisinde 1024'ten balayacak ekilde indeks deerlerini grrsnz.
  Aadaki ifadedeki Ba ve U Gstericilerin tanmlanmasn inceleyiniz.

    char far *head = (char far *) 1050;    // head pointer
    char far *tail = (char far *) 1052;    // tail pointer

  rnein klavye tampon blgsinin en gerisindeki elemana erimek iin;

    head += *head - 30 + 4 + 1;

  ifadesi kullanlabilir (ASCII kodu iin). Artk *head tampondaki ilk
  karakterdir.

  Klavye tampon blgesi 15 karakteri iine alacak geniliktedir. 15 karakterin
  ASCII ve SCAN kodlar dikkate alnrsa bu 30 bayt anlamna gelir. Ancak
  tampon blgesinin sonuna ENTER tuunun kodlar da yazlr. Klavye tampon
  blgesi dngsel bir yapdadr. Yani 30 bayt'lk blgenin sonuna
  gelindiinde tekrar baa dnlr. Ba ve u gstericiler ayn deerde iseler
  tampon botur.


  Sonu olarak INT 9 unu yapar:

  * Klavyede baslan tuun ASCII ve SCAN kodlarn alr. Bunu klavye tampon
    blgesinde Ba Gstericinin gsterdii yere yerletirir.

  * U Gstericinin deerini iki artrr ve tampona toplam bir karakter
    yerletirilmi olur.

  * Eer tamponun sonuna gelindiyse tekrar baa geer.


  Programlarn ve DOS'un srekli klavyeden deer beklediini dnmelisiniz.
  rnein DOS bir i yapmazken srekli olarak tampona bakar, tamponda
  grdklerini DOS imlecinin yanna getirir. Programlarda kullancdan
  karakter bekleyen fonksiyonlar ne yapmaktadr? Onlar da;

    * Ba gstericinin gsterdii karakteri allar.
    * Ba gstericiyi bir sonraki pozisyona ilerletirler.

  Yani tamponun dolmas iin ok az sebep vardr. Aslnda oraya karakter
  karakter yazlr ve okunurlar. Nadir durumlarda tamponda birikme meydana
  gelir.

  Aada klavye tamponundan ba gstericinin gsterdii yerdeki karakterin
  ASCII ve SCAN kodunu alan, ondan sonra da tamponu boaltan bir fonksiyon
  gryorsunuz.


 int get_last_buffer(void)
 {
        int far *t2 = (int far *) 1050;
        char far *t = (char far *) 1050;

        if (*t != *(t+2))     // tampon bo mu?
  {
                t += *t - 30 + 4;
                *(t2+1) = *t2;
                return *(int far *) t;
  }
                return 0   // tampon bo

 }



  TSR programlar ite srekli tampona bakarlar, klavyeden istenilen karakter
  baslmsa aktive edilirler. Bunun iin INT 9 yerine kesme vektrne kendi
  kesmemizi yerletirmeliyiz. Kendi kesmemiz ise nce orijinal INT 9'u
  armal daha sonra da bizim isteimizi yapmal.


 void interrupt (*timer_int)();
 void interrupt (*keyb)();
 void interrupt deactivate(void);

 main()
 {
        _getvideo();        // Ekran belleinin balang adresini alyor//
        randomize();        // Rasgele say kullanmak iin.
        timer_int = getvect(0x08);   // Orijinal INT8 alnyor
        keyb = getvect(0x9);         // Orijinal INT 9 alnyor
        setvect(0x9,activate);
        keep(1,0x1000);              // TSR

 }


  Yukardaki kodda '_getvideo' fonksiyonu bana ait. Yazm yle bir ey:


 static int videobuf;
 void _getvideo(void)
 {
        union REGS  vregs;

        vregs.h.ah = 0xf;

        int86(0x10,&vregs, &vregs);

        if (vregs.h.al == 2 || vregs.h.al == 3) {
                videobuf = 0xb800;
                return;
                }

        if (vregs.h.al == 7) {
                videobuf = 0xb000;
                return;
                }   else {
                printf("\nChange your video mode...");
                exit(1);
                }
 }



  te aktive eden fonksiyon. INT yerine bu arlacak, bu da orijinal
  INT 9'u aryor ve sonra da kendi iini yapyor.


 void interrupt activate(void)
 {

       (*keyb)();

       if (get_last_buffer() == F1) {   // ESC'ye basld m?
       setvect(0x08,virus);
       setvect(0x9,deactivate);   // INT 9 diaktive iin kullanlacak.
       }

       (*keyb)();
 }



  Yukarda F1 tuuna basld m TSR aktif hale geiyor. Bu sefer de diaktive
  edilebilsin diye ayn numara yaplyor.


 void interrupt deactivate(void)
 {

       (*keyb)();

       if (get_last_buffer() == F2) {  // diaktive et
       setvect(0x8, timer_int);        // eski INT 8'i yerletir
       setvect(0x9,keyb);              // Eski INT 9'u yerletir
       }

       (*keyb)();
 }


  imdi de INT 8 her arldnda alacak kesme:


 void interrupt virus(void)
 {
       int ran;
       static int row = 12, col = 40;

       ran = rand() % 4;

       row %= 24;
       col %= 79;

       if (row < -1)
               row = 24;
       if (col < -1)
               col = 79;

       switch (ran)
       {
               case 0 :_writes(row, col, " "); row++;
                       _writes (row, col,"*"); break;
               case 1 :_writes (row, col," "); row--;
                       _writes (--row, col,"*"); break;
               case 2 :_writes (row, col," "); col++;
                       _writes (row, col,"*"); break;
               case 3 :_writes (row,col," "); col--;
                       _writes (row,--col,"*"); break;

       }

       (*timer_int)();
 }


  '_writes' fonksiyonu bana ait.


 void _writes(int row, int col, char *str)
 {
       CHR far *chp;

       chp = (CHR far *) ((long) videobuf << 16 | 0L);
       chp += row * 80 + col;

       while (*str != NULL) {
               chp -> chr = *str;
               ++chp;
               ++str;
               }
 }






  Evet, bu aylk ta bu kadar... imdi size benden bir dev. Kendinize buradaki
  prensipleri kullanarak bir Trke klavye evirici program yazn.




     Ŀ
       Not : Birey sormak isterseniz, beni   
             dernekte bulabilirsiniz.         
             Sizleri de bekliyoruz.           
                                              
             Kaan Aslan                       
                                              
             Tel : (1) 288 35 20 - 288 36 31  
     



