C Program Lama Dl Ve Interrupt

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View C Program Lama Dl Ve Interrupt as PDF for free.

More details

  • Words: 6,307
  • Pages: 39
C PROGRAMLAMA DİLİ VE INTERRUPT(KESME)’LAR GİRİŞ C programlama dili makine diline en yakın programlama dilidir. Bu sebeple bu dilde yazılan programlar diğer dillerle yazılan programlardan daha hızlı çalışırlar. Günümüzde kullanılan birçok program C programlama dili ile yazılmıştır. Bu programlara diğer programlama dilleri de dahildir. Buna en iyi örnek, yakın bir zamanda piyasaya sürülen Visual Cobol programlama dili C programlama dili ile yazılmış bir programlama dilidir. Öyleyse niçin C programlama dili gibi hızlı ve görsel programların yazılabileceği bir programlama dili varken, bu dille başka programlama dilleri yazılmakta ve onlar kullanılmakta? Bunun cevabı C dili ile program yapmaya çalışanlar için çok kolaydır. Evet, bu programlama dili ile her şey yapılabilir. Her şeyi yapabileceğiniz için zor bir dildir ve bu dile tamamen hakim olmanız gereklidir. Ayrıca bu dille yüksek seviyeli programlama yapabilmeniz için C dili haricinde programcının donanım bilgisine de sahip olması gerekir. Çünkü C dilinde yapmak istediğiniz her şeyi siz yaparsınız. Yani bilgisayarın ne yapmasını istiyorsanız, her şeyi sizin programlamanız gerekir. Bu kaynakta yazılı olanlar ise C dili ile belirli bir seviyeye gelmiş programcılar için yazılmış olan C’de interrupt’ların kullanımı ile ilgili bilgiler vardır. Interrupt’ların daha iyi anlaşılması için Union yapısından başlayarak inceleyeceğiz. Fakat önce Interrup’lar hakkında biraz bilgi vermek istiyorum.

INTERRUPT NEDİR ve ÇEŞİTLERİ NELERDİR? Bilgisayarın en zor ve en ilginç konusudur. Interrupt(Kesme) nedir? Bunu açıklamak için bir örnek verelim: Çalışma esnasında bir telefon geldiği zaman çalışmamızı kısa bir süre erteleyerek telefonla ilgileniriz. Telefon konuşması bitince de çalışmamıza kaldığımız yerden devam ederiz. Telefon, bizim çalışmamızı bir ara kesti. İşte bu kesme olayına INTERRUPT denir. Aklınıza hemen bunun zor bir iş olmadığı düşüncesi gelmiştir. Bir telefonla konuşurken, ikinci bir telefonu idare edenler olabilir. Fakat aynı anda 15 tane telefonu idare etmek zordur. Bu problemi, bizimle telefonda konuşan şahıslara öncelik vererek kısmen çözebiliriz. Fakat kolay olmadığını görüyoruz. Bilgisayarda işin büyük bir kısmını BIOS ve DOS halletmektedir. İyi bir bilgisayarcı olmak için interrupt’ları anlamak şarttır. IBM PC ailesi, donanım yada yazılım tarafından yaratılabilecek Interrupt’lar ile idare edilebilir. Bir Interrupt oluştuğunda, bilgisayarın çalışması, bu Interrupt’ı halledebilecek bir rutine yollanır. Bu rutinlerin başlangıç adresleri, Interrupt Vektör Tablosu’nda saklanır. Bu tablo, bilgisayarın hafızasının en alt kesiminde, ilk bir kilobyte’lık yerde bulunur. Bu sahada 255 ayrı Interrupt için yer ayrılmıştır. Örneğin, 5. Interrupt oluştuğunda, sistem ilk olarak bütün registerleri saklar, ve bu ilk 1K’lık tablodan, 5. "kutu" ya bakıp buradaki adresi okur. Sonra, buradan öğrendiği adrese atlar ve orada ne işlemler varsa yapar. Bunlar bitince, tekrar kaldığı işleme geri döner. Donanım Interrupt’ları(Hardware Interrupts): Bunlar, sistem tarafından çağırılan rutinlerdir. Örneğin sistem, her saniyede 18.2 kere bir Interrupt ile saatini ilerletmektedir. Bu çağırım, yada Interrupt, donanım tarafından yaratılmaktadır. Diğer bir başka Interrupt ise, 9. klavye Interrupt’ıdır. Her tuşa basıldığında, bu donanım Interrupt’ı oluşur. Yazılım Interrupt’ları(Software Interrupts): Bunlar ise, herhangi bir programın çağırabileceği bir rutinler kütüphanesidir. Ekrana bir şey yazmak gerektiğine, yada silmek gerektiğinde, bunu bir Interrupt çağırarak yaparız. PC türündeki bilgisayarlardaki interrupt çeşitleri aşağıda verilmiştir. Tüm interrupt numaraları hexadecimal olarak verilmiştir. Interrupt numaraları hafızada 0. adresten başlar ve 4 byte’lık yer alırlar. Numarası verilen Interrupt’ın programın başlama segmenti bu adresten öğrenilebilir. Ayrıca bu adresi öğrenmek için DOS 25h Interrupt’ı kullanılabilir.

a) Hardware(Makine yapılırken tasarlanan) Interrupt’lar. b) BIOS Interrupt’lar. c) DOS Interrupt’lar.

Hardware Interrupt’lar INT 00h (000-003)

DIVIDE ERROR 0’a bölme. Mikroişlemci’de 0’a bölme olunca sistem durur. Normal olarak DOS tarafından hata olunca hata kodunu göstererek programdan çıkmak için kullanılır.

INT 01h (004-007)

SINGLESTEP Tek komut. Makime dilindeki her komuttan sonra kesme olur. Normal olarak DEBUG’daki T komutu gibi çalışır.

INT 02h (008-00B)

NMI(NONMASKEBLE INTERRUPT) Hafızada hardware hatası olunca sistem bu kesmeyi kullanır.

INT 03h (00C-00F) 1 BYTE INTERRUPT Program yalnızca belirli komutları icra etmek için kullanılır. DEBUG’da ve Turbo Pascal versiyon1,2,3 de {$U+} belirtilmiş ise kullanılır. INT 04h (010-013)

OVERFLOW Aritmetik işleminde taşmayı kontrol etmek için kullanılır.

INT 05h

PC/XT’lerde bios Interrupt. PRINTSCREEN KEY

INT 05

(80286 dahili Interrupt) BOUND CHECK FAILED taşma ile ilgilidir.

INT 06

(80286 dahili Interrupt) UNDEFINED OPCODE Hatalı makine kodu.

INT 07

(80286 dahili koruma modunda) NO MATH UNIT AVAILABLE Matematik ünitesi yok.

INT 08h-0Fh (020-040) Sistem kullanır. PC/XT’lerde: IRQ0 Sistem saati kesmesi IRQ1 Sistem klavye kesmesi IRQ2 EGA dikine tarama, IBM’de Harddısk kesmesi. IRQ3 Seri port 2(Com 2:)

IRQ4 IRQ5 IRQ6 IRQ7

Seri port 1(Com 1:) Harddisk veya PC/AT de LPT2 veya 60 Hz RAM tarama Disket kesmesi PPI(Paralel Printer Interface LPT1:, LPT2:) kesmesi

286/386’larda: INT 08

(80286 dahili koruma modunda) DOUBLE FAULT Çift hata.

INT 09

(80286 dahili koruma modunda) MATH UNIT PROTECTION FAULT Matematik ünitede koruma hatası.

INT 0A

(80286 dahili koruma modunda) SEGMENT Hatalı segment durumu.

INT 0B

(80286 dahili koruma modunda) NOT PRESENT Bulunmadı durumu.

INT 0C

(80286 dahili koruma modunda) STACK FAULT Stack hatası.

INT 0D

(80286 dahili koruma modunda) GENERAL PROTECTION VIOLATION Genel koruma hatası.

INVALID TASK

STATE

Gerçek modda çalışırken bir komut 0FFFFh segmentine erişim yapmak isterse bu kesme devreye girer. INT 0E

(80386 dahili gerçek modda) PAGE FAULT Sayfa hatası

BIOS Interrupt’lar INT 05h (014-017)

PRINTSCREEN KEY Kullanıcı, Print Screen tuşuna bastığı zaman BIOS bu Interrupt’ı kullanır. Ekranın tümünü yazıcıya döker. Sonuç hafızanın 0050:0000 adresinde depolanmıştır.

INT 10h (040-043)

VIDEO Ekranla ilgili kesmelerdir.

INT 11h (044-047)

EQUIPMENT Bilgisayarımıza olan bağlantıları verir.

INT 12h (048-04B)

MEMORY Bilgisayarımızın hafıza kapasitesini verir.

INT 13h (04C-04F) DISK/DISKETTES Disk ve disketle ilgili okuma yazma işleri için kullanılır. INT 14h (050-053)

SERIAL PORT Seri bağlantılarda kullanılır(Komünikasyon Port’ları).

INT 15h (054-057)

SYSTEM Özellikle teyp ile ilgili işlemlerde kullanılır.

INT 16h (058-05F)

KEYBOARD Klavye ile ilgili işlemlerde kullanılır. Bu kesmeyi kullanarak ta RESIDENT program yazılabilir.

INT 17h (05C-05F) PRINTER Yazıcıyı kontrol etmek için kullanılır. INT 18h (060-063)

ROM BASIC Bazı makinelerin ROM’unda bulunan BASIC’i yükler.

INT 19h (064-068)

REBOOT Makineyi yeniden açmak için kullanılır. Kullanıcı CTRL+ALT+DEL tuşlarına bastığı zaman bu kesme devreye girer. Bu kesme sayesinde programda makineyi yeniden açmak mümkündür.

INT 1Ah (068-06B) TIME AND DATE Sistem saati ve tarihi ile ilgili işlemlerde kullanılır. INT 1Bh (06C-06F) CTRLBREAK KEY Break veya Ctrl+Break tuşlarının basılıp basılmadığını kontrol eder. INT 1Ch (070-073)

TIMER Saniyede 18.2 defa 08’i çağıran bir kesmedir.

INT 1Dh (074-077) VIDEO TABLE Ekran modunun tablosuna erişim adresi için kullanılır.

INT 1E (078-07B)

DRIVE TABLE

Diske erişimle ilgili tablonun adresi için kullanılır. INT 1F (07C-07F)

CHARACTER TABLE Karakter tablosunun adresi için kullanılır.

DOS Interrupt’lar INT 20h (080-083)

DOS PROGRAM TERMINATION Programı keser ve işletim sistemine geçirir.

INT 21h (084-087)

DOS INT_21 DOS fonksiyonlarını çağırır.

INT 22

DOS TERMINATE ADDRESS Program bitince gidilecek adresi belirler.

INT 23

DOS CONTROL “C” EXIT ADDRESS Ctrl+C ile programı kesme adresi.

INT 24

DOS FATAL ERROR HANDLER ADDRESS Kritik hata adresi.

INT 25

DOS ABSOLUTE DISK READ Disk/disketten sektör okuma.

INT 26

DOS ABSOLUTE DISK WRITE Disk/diskete sektör yazma.

INT 27

DOS TERMINATE BUT STAY RESIDENT Programı bitir. Fakat hafızada kal.

INT 28

DOS(Dahili) KBD BUSY LOOP Klavyede problem.

INT 29

DOS(Dahili) FAST PUTCHAR Hızlı karakter yazma.

INT 2A

MS NETWORK MS çok kullanıcılı sistem.

INT 2B

(Dahili) MSDOS (IRET)

INT 2C

(Dahili) MSDOS (IRET)

INT 2D

(Dahili) MSDOS (IRET)

INT 2E

DOS(Dahili) EXECUTE COMMAND Komut icra ettirme

INT 2F

MULTIPLEXOR

INT 30

RESIDENT(Hafızada kalıcı program) PRINT, SHARE, ASSIGN, APPEND... ile irtibat. FAR JUMP instruction for CP/M style calls CP/M türünde FAR JUMP komutu

INT 31

KULLANILMIYOR

INT 32

KULLANILMIYOR

INT 33

MS MOUSE MOUSE(fare) ile ilgili.

INT 34

TURBO C Floating Point emulation Turbo C Kesirli Nokta oluşturma.

INT 35 INT 36 INT 37 INT 38 INT 39 INT 3A INT 3B INT 3C INT 3D INT 3E

TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation TURBO C Floating Point emulation

INT 3F

Overlay manager Interrupt(MSLINK.EXE) Link.exe için.

INT 40

Relocated Floppy Handler

INT 13’ün kopyası. INT 41

HD params(XT,AT,XT2,XT286,PS) 1. Harddisk parametreleri.

INT 42

Relocated Video Handler(EGA,VGA,PS) INT 10’un kopyası.

INT 43

EGA Initialization Params(EGA,VGA,PS) EGA parametreleri.

INT 44

EGA/PCjr fonts(EGA,VGA,PS)

INT 45

EGA fontları. (ÖZEL)

INT 46

Secondary HD Params(INT 41h’e bakınız)(AT,XT286,PS) 2. Harddisk parametreleri.

INT 47

(ÖZEL)

INT 48

PCjr.

INT 49

PCjr.

INT 4A

AT User Alarm(AT,PS) AT kullanıcı alarmı.

INT 4B INT 4C INT 4D INT 4E INT 4F INT 58

(ÖZEL) (ÖZEL) (ÖZEL) (ÖZEL) (ÖZEL) (ÖZEL)

INT 59

GSS Computer Graphics Interface(GSS*CGI) İstatistiki grafik.

INT 5A

BIOS entry address BIOS başlama adresi.

INT 5B

(ÖZEL)

INT 5C

NETBIOS INTERFACE

NETWORK BIOS INT 5D INT 5E INT 5F INT 60 INT 61 INT 62 INT 63 INT 64 INT 65 INT 66 INT 67 INT 68 INT 69 INT 6A INT 6B INT 6C

(ÖZEL) (ÖZEL) (ÖZEL) (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. (ÖZEL) KULLANICI İÇİN. LIM EMS KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR DOS 3.2 Realtime Clock update Gerçek saati düzeltme.

INT 6D INT 6E INT 6F

KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR

INT 70-77

AT/XT286/PS50+ Vectored Hardware Lines Donanım bağlantıları.

INT 78 INT 79 INT 7A INT 7B INT 7C INT 7D INT 7E INT 7F

KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR KULLANILMIYOR

INT 80 INT 81 INT 82 INT 83 INT 84 INT 85

(ÖZEL) BASIC (ÖZEL) BASIC (ÖZEL) BASIC (ÖZEL) BASIC (ÖZEL) BASIC (ÖZEL) BASIC

INT 86

Relocated INT 18 INT 18’in kopyası.

INT 86F0

BASIC(Interpreter) BASIC kullanıyor.

INT F1 INT F2 INT F3 INT F4 INT F5 INT F6 INT F7

(ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN

INT F8

INTERVAL TIMER(10 MSEC)

INT F9

(ÖZEL) KULLANICI İÇİN

INT FA

USART READY(RS232C arabirimi)

INT FB

USART Rx READY(Klavye arabirimi)

INT FD INT FD

(ÖZEL) KULLANICI İÇİN (ÖZEL) KULLANICI İÇİN

Ekranla İlgili Interrupt’lar INT 10 Function 00H(00)

Set video mode. Ekran türünü(modunu) değiştirir.

INT 10 Function 01H(01)

Set cursor size. Cursor büyüklüğünü belirle.

INT 10 Function 02H(02)

Set cursor position. Cursor’ün yerini belirle.

INT 10 Function 03H(03)

Read cursor position and size. Cursor’ün yerini ve büyüklüğünü oku.

INT 10 Function 04H(04)

Get light pen position. Işıklı kalmin durumunu ve yerini oku.

INT 10 Function 05H(05)

Set activate display page. Sayfayı aktifleştir. Sayfa seç.

INT 10 Function 06H(06)

Initilaze or scrool up window. Pencere doldur veya yukarı kaydır.

INT 10 Function 07H(07)

Initilaze or scrool down window. Pencere doldur veya aşağı kaydır.

INT 10 Function 08H(08)

Read character and attribute. Karakter ve rengini oku.

INT 10h, 09h (9)

Write character and attribute at cursor. Cursor’ün bulunduğu yerde karakteri ve rengi göster.

INT 10h, 0Ah (10)

Write character at cursor. Cursor’ün bulunduğu yerde karakter göster.

INT 10h, 0Bh (11)

Set color palette. Renk paletini seç.

INT 10h, 0Ch (12)

Write pixel. Pixel yaz.

INT 10h, 0Dh (13)

Read pixel. Pixel oku.

INT 10h, 0Eh (14)

Write character in Teletype(TTY) mode. Karakteri bir sonraki sütuna geçerek yaz.

INT 10h, 0Fh (15)

Get current video mode. Şu naki ekran modu nedir?

INT 10h, 10h (16)

Set palette register. Palet registerini doldur(EGA/VGA).

INT 10h, 11h (17)

Character generator. Font oluştur(EGA/VGA).

INT 10h, 12h (18)

Alternate print screen.

Ekranı yazıcıya aktar(EGA/VGA). INT 10h, 13h (19)

Write character string. Ekranda karakter katarı göster.

INT 10h, 1Ah (26)

Read/write display combination code(VGA). Görüntü hangi sistemle olacak.

INT 10h, 1Bh (27)

Return fonctionality/state information(VGA). Etkinlik ve durum hakkında bilgi al.

INT 10h, 1Ch (28)

Save/restore video state(VGA). Görüntü durumunu al değiştir.

INT 11h (17)

Read equipment list. Donanım listesini oku.

INT 12h (18)

Report memory size. Hafıza kapasitesini ver.

Disk/Disketle İlgili Interrupt’lar INT 13h, 00h (00)

Reset disk/diskette system. Disk/disket bilgilerini sıfırla(yeniden oku).

INT 13h, 01h (01)

Get disk/diskette status. Disk/disket durumunu al.

INT 13h, 02h (02)

Read sectors into memory. Disk/disketten sektör oku.

INT 13h, 03h (03)

Write sectors from memory. Disk/diskete sektör yaz.

INT 13h, 04h (04)

Verify sectors. Disk/disketten okunup okunamayacağını belirtir.

INT 13h, 05h (05)

Format track. Disk/diskete bir izi formatlar.

INT 13h, 06h (06)

Format track and set bad sector flags. Diskte bozuk bir izi formatlar(Yalnızca XT).

INT 13h, 07h (07)

Format disk starting at cylinder. Belirlenen izden itibaren diski formatlar(Yalnızca XT).

INT 13h, 08h (08)

Set drive parameters

INT 13h, 09h (09)

Verilen sürücünün parametrelerini alır. Initilaze fixed disk characteristics. Diskin disk parametre bloğunu değiştirir.

INT 13h, 0Ah (10)

Read long. ECC kodu dahil sektör oku.

INT 13h, 0Bh (11)

Write long. ECC kodu dahil sektöre yazar.

INT 13h, 0Ch (12)

Seek. Verilen ize konumlanır.

INT 13h, 0Dh (13)

Reset fixed disk system. Disk bilgilerini yeniden okur.

INT 13h, 0Eh (14)

Read sector buffer. Disk buffer’dan okur.

INT 13h, 0Fh (15)

Write sector buffer. Disk buffer’a yazar.

INT 13h, 10h (16)

Get fixed disk drive status Disk sürücünün durumunu alır.

INT 13h, 11h (17)

Recalibrate fixed disk drive.

Disk sürücünün kafasını konumlandırır. INT 13h, 12h (18)

Controller RAM diagnostic. Diskin kendi buffer’ının hata rutinini başlatır.

INT 13h, 13h (19)

Controller drive diagnostic. Diskin sürücü hata rutinini başlatır.

INT 13h, 14h (20)

Controller internal diagnostic. Diskin iç hata rutinini başlatır.

INT 13h, 15h (21)

Get disk type. Disk tipini okur.

INT 13h, 16h (22)

Disket change status. Disketin değiştirilip değiştirilmediğine bakar.

INT 13h, 17h (23)

Set diskette type. Disketin tipini belirler.

INT 13h, 18h (24)

Set media type for format diskette. Disketi formatlamak için tipini belirle(Yalnızca AT).

Kominikasyon İle İlgili Interrupt’lar INT 14h, 01h (01)

Send one character. Belirtilen port’a karakter gönder.

INT 14h, 02h (02)

Recieve one character. Belirtilen port’tan karakter alır.

INT 14h, 03h (03)

Get serial port status. Port durumunu al.

Sistemle İlgili Interrupt’lar INT 15h, 00h (00)

Casette motor on(PC). Kaset motorunu aç.

INT 15h, 01h (01)

Casette motor off(PC). Kaset motorunu kapa.

INT 15h, 02h (02)

Casette read data block(PC). Kasetten veri oku.

INT 15h, 03h (03)

Casette write data block(PC). Kasete veri yaz.

INT 15h, 4Fh (79)

Keybord intercept(AT model 3x9,XT2,XT286) Klavyeye müdahele.

INT 15h, 80h (128)

Device open(AT,XT2,XT286). Ünite aç.

INT 15h, 81h (129)

Device close(AT,XT2,XT286). Ünite kapa.

INT 15h, 82h (130)

Device program termination(AT,XT2,XT286). Ünite programı bitir.

INT 15h, 83h (131)

Event wait(AT,XT2,XT286). Bekleme süresi.

INT 15h, 84h (132)

Read joystick switch settings(AT,XT,XT286). Joystick durumunu oku.

INT 15h, 85h (133)

System request key pressed(AT,XT2,XT286). Sys req veya ALT-sys req tuşuna basıldı.

INT 15h, 86h (134)

Wait(AT,XT2,XT286). Bir süre bekle.

INT 15h, 87h (135)

Extended memory block move(AT,XT2,XT286). 1 MB üstündeki hafızaya taşı(Korumalı mod).

INT 15h, 88h (136)

Get extended memory size(AT,XT2,XT286). 1 MB üstündeki hafıza miktarı(Korumalı mod).

INT 15h, 89h (137)

Switch to virtual mode(AT,XT2,XT286). 1 MB üstündeki hafıza moduna geç(Korumalı mod).

INT 15h, 90h (144)

DEVICE BUSY LOOP(ATİXT2,XT286). Ünitede anormallik döngüsü.

INT 15h, 91h (145)

Interrupt complate(AT,XT2,XT286). 90H fonksiyonu tamamlandı.

INT 15h, C0h (192)

Get system configuration(AT,XT2,XT286). Sistem bilgilerini al.

Klavye İle İlgili Interrupt’lar INT 16h, 00h (00)

Keyboard read. Klavyeden tuş al.

INT 16h, 01h (01)

Keyboard status. Klavye buffer durumu.

INT 16h, 02h (02)

Get shift status. Özel tuşların durumu.

INT 16h, 03h (03)

Get typmatic rate and delay(AT model 339,XT286). Basma hız ve zamanı ayarla.

INT 16h, 05h (05)

Write to keyboard buffer. Klavye buffer’ına yaz.

INT 16h, 10h (16)

Extended keyboard read. 101/102 dahil klavyeden tuş al.

INT 16h, 11h (17)

Extended keyboard status. 101/102 klavye buffer durumu.

INT 16h, 12h (18)

Get extended shift status. Özel tuşların durumu(101/102 klavye).

Yazıcı ile ilgili Interrupt’lar INT 17h, 00h (00)

Send one byte to printer. Yazıcıya 1 byte gönder.

INT 17h, 01h (01)

Initilaze printer. Yazıcıyı başlat.

INT 17h, 02h (02)

Get printer status. Yazıcı durumunu al.

Çeşitli Interrupt’lar INT 18h

ROM BASIC. IBM PC’de ROM BASIC’e geç.

INT 19h

Bootstrap loader. Makineyi yeniden açar.

INT 1Ah, 00h (00)

Read system timer. Sistem saatini oku.

INT 1Ah, 01h (01)

Set system timer. Sistem saatini ayarla.

INT 1Ah, 02h (02)

Read real-time clock time(AT,XT286). Gerçek saati oku.

INT 1Ah, 03h (03)

Set real-time clock time(AT,XT286). Gerçek saati ayarla.

INT 1Ah, 04h (04)

Read real-time clock date. Gerçek saat tarihini oku.

INT 1Ah, 05h (05)

Set real-time clock date. Gerçek saat tarihini ayarla.

INT 1Ah, 06h (06)

Set alarm clock. Alarm saati ayarla.

INT 1Ah, 07h (07)

Reset real-time clock alarm.

INT 1Bh

Gerçek saat alarmını iptal et. CTRLBREAK KEY CTRL+BREAK’e basıldı mı?

INT 1Ch

Timer Interrupt(Clock tick). Periodik zaman sinyali.

Tablo Adresleri INT 1Dh

Video table. Ekran özellikleri tablosu.

INT 1Eh

Drive table(Diskette parameters). Disket parametreleri.

INT 1Fh

Graph 2 table(Characters table). Grafik karakter tablosu.

C ve MS-DOS İLE EKRAN DÜZENİ Interrupt’lar C ye sonradan eklenen bir 'uzantı' olduğu, ve sadece MS yada PC-DOS ile çalışan bilgisayarlarda kullanılabileceği için, burada göreceğimiz int86() fonksiyonu, şu anda sadece Microsoft C, ve Turbo C tarafından desteklenmektedir. Derleyiciniz başka ise, bu fonksiyon çağrılış metodunu değiştirmeniz gerekebilir. Çok sayıda değişik türde ekran tipleri ile kullanılabileceği için, C de tanımlanmış, hazır ekran fonksiyonları yoktur. Bu fonksiyonlar, kullanılacak cihazın yapısına göre tanımlanabilir. Bu konu içerisinde, elimizdekinin bir IBM-PC yada uyumlu bilgisayar olduğunu kabul edeceğiz.

Ekrana Nasıl Erişelim? Temelde, 3 çeşit yoldan ekrana erişebiliriz: 1) Bir BIOS Interrupt’ı ile, 2) DOS'un ANSI.SYS’i ile, 3) Direkt donanıma karışarak.

BIOS nedir? (Basic Input/Output System) BIOS’un görevi, bilgisayarın yapması gereken temel servisleri yerine getirmektir. Geniş anlamda, BIOS IBM'in içindeki yongalarda bulunan rutinler kütüphanesidir. BIOS, DOS ile donanım arasında bir yerde bulunur. Bir taraftan, bir programdan yapılması gereken standart BIOS komutunu alır. Programımız, BIOS’a bu isteği, bir Interrupt vasıtası ile bildirir. BIOS’un diğer tarafı ise, bilgisayarın donanım parçaları(ekran, disk drive, seri port, vs.) ile ilişki kurar. BIOS’un bu tarafı ise, dikkati çekmek için bir Interrupt yaratan bir donanım ile konuşur.

DOS nedir? DOS ise, bir başka kütüphanedir. Özellikle diske erişimde uzmanlaşmış olan DOS, bundan başka ekrana yazma, yazıcıya bilgi yollama, vs. gibi servisleri de kapsar. DOS'un da aynı BIOS gibi Interrupt’ları ve sağladığı birçok servis vardır. Aslında DOS, çoğu bu servisler için BIOS'dan yardım görmektedir. Aklınızda bulunsun: BIOS yongalarda bulunur, DOS ise sonradan yüklenir. Şimdi, BIOS ile nasıl ekran kontrolü yapabileceğimizi görelim. Bir kere, bütün BIOS ekran fonksiyonları, bir Interrupt ile çağırılır, bunun da Interrupt numarası 16 dır. Herhangi bir BIOS fonksiyonunu kullanmak için yapmamız gerekenler, önce bazı registerleri değiştirmek, onaltinci Interrupt’ı çağırmak, ve sonuçları zevkle seyretmektir.

Register? IBM-PC ailesinin kullandığı 8088 yongasının, çalışmasında kullandığı bazı özel sahalar vardır. Bu sahalara "register" ismi verilir. IBM-PC de, toplam olarak ondört tane register vardır. PC bunları, aritmetik işlemler, karşılaştırmalar gibi işlerde kullanır. Bunlardan dört tanesini BIOS Interrupt’ları ile kullanacağız. Bu kullanacaklarımızın isimleri, AX,BX,CX ve DX dır. Bunlar aynı birer değişken gibi içlerinde değerler taşıyabilirler. Bu registerlerin bir özelliği ise, ister tam olarak, yani bütün AX birden, istersek de yarım (AH ve AL yi) değerlerini değiştirmemiz mümkündür. Yani, dilersek AX in içine bir 16 bitlik veri koyabiliriz, yada AL ve AH'ların içlerine sekizer bitlik veri koyabiliriz. Hep AX i kullandığıma bakmayın, BX i BL ve BH, CX i CH ve CL diye, DX i DL ve DH diye ayırmamız mümkün.

C PROGRAMLAMA DİLİNDE UNION YAPISI(BİRLİKLER) Bu konuda union yapısını anlatırken, bu yapıdan yazımı kolay olduğu için birlikler olarak bahsedeceğim. Birlikler struct yapısı gibi belleğe sürekli bir biçimde yerleşen nesnelerdir. Tanımlanmaları ve bildirimleri birbirinin aynı olsa da içerdiği nesnelerin yerleşim biçimleri arasında fark vardır. Birlikler yapılara göre seyrek kullanılırlar.

Birliklerin Bildirimi Birliklerin bildirimi de yapılarda olduğu gibidir. Yalnızca struct anahtar sözcüğü yerine union anahtar sözcüğü kullanılır. Union [birlik ismi] { Tür ; Tür ; Tür ; ... }; Yukarıdaki genel biçimde: union birlik_ismi birlik_elemanı

Bildirim için gerekli bir anahtar sözcüktür. Birliği anlatan isimlendirme kurallarına uygun herhangi bir isim olabilir. Birlik elemanıdır; isimlendirme kurallarına uygun herhangi bir isim olabilir.

Örneğin: union DWORD { unsigned char byte; unsigned int word; unsigned long dword; }; Diğer bir örnek: union DBL_FORM { double n; unsigned char s[8]; };

Birlik Değişkenlerinin Tanımlanması Tıpkı yapılarda olduğu gibi birliklerde de bellekte yer ayırma işlemi bildirim ile değil tanımlama işlemi ile yapılmaktadır. Birlik bildirimlerinin yapı bildirimlerinden tek farkı struct anahtar sözcüğü yerine union anahtar sözcüğü kullanılmasıdır. Genel biçim: union ; Örneğin: union DWORD a, b; ile a ve b union DWORD türünden iki değişken olarak tanımlanmışlardır. Benzer biçimde: union DBL_FORM x, y; x ve y union DBL_FORM türünden iki değişken biçimindedir. Yine tıpkı yapılarda olduğu gibi birliklerde de bildirim ve tanımlama işlemi birlikte yapılabilir. Örneğin: union DBL_FORM { double n; unsigned char s[8]; } x, y; Bu durumda x ve y değişkenlerinin faaliyet alanları birliğin bildirildiği yere bağlı olarak global yada yerel olabilir. Birlik elemanlarına da * operatörüyle erişilir. Örneğin yukarıda ki tanımlama ele alınırsa: union DWORD a; a byte birliğin unsigned char olan ilk elemanını belirtmektedir. Benzer biçimde birlik türünden de pointer(gösterici)’lar tanımlanabilir. Ok operatörü yine yapılarda olduğu gibi gösterici yoluyla birlik elemanlarına erişmekte kullanılır. Örneğin: union DWORD *p; ... p → word ifadesi ile p adresi ile belirtilen bölgedeki birliğin word elemanına erişilmektedir. Genel olarak şunları söyleyebiliriz: Yapılarda birliklerin bildirilmesi, tanımlanması ve yapı değişkenlerinin kullanılması tamamen aynı biçimde yapılamaktadır. İkisi arasındaki tek fark yapı ve birlik elemanlarının organizasyonunda ortaya çıkar.

Birlik elemanlarının organizasyonu konusuna değinmeden önce bir byte’tan daha uzun bilgilerin bellekteki görünümleri üzerinde duracağız.

Sayıların Bellekteki Yerleşimleri Bir byte’tan daha büyük olan sayılar belleğe biçimi kullanılan mikroişlemciye göre değişebilir. Bu nedenle sayıların bellekteki görünümleri taşınabilir bir bilgi değildir. Mikroişlemciler iki tür yerleşim biçimi kullabilirler. 1) Düşük anlamlı byte değerleri belleğin düşük anlamlı adresinde bulunacak biçimde. 80x86 ailesi Intel işlemcileri bu yerleşim biçimini kullanır. Bu işlemcilerin kullanıldığı sistemlerde örneğin: int x = 0x1234; biçimindeki bir x değişkeninin bellekte 1FC0 adresinden başlayarak yerleştiğini varsayalım:

1FC0 1FC1

... 34 12 ...

Düşük anlamlı byte Yüksek anlamlı byte

Şekilde de görüldüğü gibi x değişkenini oluşturan sayılar düşük anlamlı byte değeri (34H) düşük anlamlı bellek adresinde(1FC0H) olacak biçimde yerleştirilmiştir. Şimdi aşağıdaki kodu inceleyiniz. ... unsigend long a = 0x12345678; unsigned int *b; b = (unsigned int *) &a; printf(“%x\n”,*b); ile ekrana HEX sistemde 5678 sayıları basılır. Aşağıdaki şekli inceleyiniz. B değişkeninin 1B10 adresinden başlayarak yerleştiği varsayılmıştır. b 1B00 1B10 1B11 1B12 1B13

... 78 56 34 12 ...

*b

2) Düşük anlamlı byte değerleri belleğin yüksek anlamlı adresinde bulunacak biçimde. Motorola işlemcileri bu yerleşim biçimini kullanır. Örneğin yukarıdaki kod Motorola işlemcilerinin kullanıldığı bir sistemden yazılmış olsaydı; ... unsigend long a = 0x12345678; unsigned int *b; b = (unsigned int *) &a; printf(“%x\n”,*b); ekrana HEX sistemde 1234 basılırdı. b 1B00 ... 12 34 56 78 ...

1B10 1B11 1B12 1B13

*b

Birlik Elemanlarının Organizasyonu Birlik değişkenleri için birliğin en uzun elemanı kadar yer ayrılır. Birlik elemanlarının hepsi aynı orjinden başlayacak biçimde belleğe yerleşirler. Örneğin: union DWORD { unsigned char byte; unsigned int word; unsigned long dword; }; ... union DWORD a; bildirimi ile a değişkeni için 4 byte yer ayrılacaktır. Çünkü a değişkeninin dword elemanı 4 byte ile birliğin en uzun elemanıdır. ... b.byte

a.word

a.dword ...

Birlik bir dizi içeriyorsa dizi tek bir eleman olarak ele alınır. Örneğin: union DBL_FORM { double n; unsigned char s[8]; }; ... union DBL_FORM x; tanımlaması ile x değişkeni için ne kadar yer ayrılacaktır? DBL_FORM birliğinin iki elemanı vardır. Birincisi 8 byte uzunluğunda bir karakter dizisi, ikincisi de 8 byte uzunluğunda double bir sayıdır. İki uzunlukta aynı olduğuna göre x için 8 byte yer ayrılacağını söyleyebiliriz.

n

s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7]

n.x

Buna göre; union DBL_FORM x; ... x.n = 10.2; ile x.s[0], x.s[1], x.s[2], x.s[3], x.s[4], x.s[5], x.s[6], x.s[7] sırasıyla double elemanlarının byte değerlerini göstermektedir. Birlik elemanlarının aynı orjinden başlayarak yerleşmesi bir elemanını değiştirince diğer elemanlarının da içeriğinin değişeceği anlamına gelir. Zaten birliklerin kullanılmasının asıl amacı da budur. Birlik elemanı olarak yapıların kullanılması uygulamada en sık karşılaşılan durumdur. Örneğin: struct WORD { unsigned char low_byte; unsigned char high_byte; }; union WORD_FORM { unsigned int x; struct WORD y; };

bildirimlerinden sonra union WORD_FORM türünden bir birlik tanımlanırsa: union WORD_FORM

wf;

bu birliğin alçak(low_byte) ve yüksek(high_byte) anlamlı byte değerlerine ayrı ayrı erişebiliriz; hem de onu bir bütün olarak kullanbiliriz. wf ... wf.low_byte wf.x wf.high_byte ... Yani, intel işlemcilerin bulunduğu 16 bit sistemlerde: wf.y.low_byte = 0x12; wf.y.high_byte = 0x34; işlemlerinden sonra: printf(“%x\n”,wf.y); ile 3412 sayısını ekrana yazdıracaktır(Motorola işlemcilerinde bellğin düşük anlamlı bölgesinde düşük anlamlı byte değeri olacağına göre sayının ters olarak gözükmesi gerekir). ... 0x12

wf.low_byte

0x34

wf.high_byte

wf.x

... 80x86 mimarisindeki sistem programlama uygulamalarında sıklıkla rastladığımız başka bir durum CPU içerisindeki yazmaçların bir birlik ile temsil edilmesidir. Önce kısaca Intel işlemcilerinin yazmaç yapısından bahsetmek yerinde olacaktır.

Intel 80x86 İşlemcilerin Yazmaç Yapısı 16 bitlik Intel 8086 işlemcisinde 14 yazmaç vardır. Bu yazmaçlar işlevlerine göre birkaç gruba ayrılırlar. 4 tanesi genel amaçlı yazmaçlardır: AX, BX, CX, DX 4 tanesi segment yazmaçlarıdır: CS,SS,DS,ES 2 tanesi index yazmacıdır: SI, DI 3 tanesi gösterici yazmacıdır: IP, SP, BP 1 tanede bayrak yazmacı vardır: F 8086 yazmaçlarının hepsi 16 bittir. Genel amaçlı yazmaçların dışındakiler tek parça olarak kullanılırlar. Ancak genel amaçlı yazmaçlar 8 bitlik iki ayrı yazmaçmış gibi de kullanılabilirler. AX AH

AL BX

BH

BL CX

CH

CL DX

DH

DL

AH ve AL yazmaçlarına değer yüklendiğinde bu AX yazmacını da bütünsel olarak etkilemektedir. 80386, 80486 ve Pentium mikroişlemcilerinde(birçoğu koruma mekanizması sağlamaya yönelik) 8086’dan daha fazla yazmaç vardır. Bu işlemciler 32 bit olduğundan yazmaçları da 32 bittir. 80386, 80486 ve Pentium işlemcilerindeki genel amaçlı yazmaçlar 8086 ile uyumun korunabilmesi için genişletilmişlerdir. Segment yazmaçları dışındaki yazmaçların başına E harfi(İngilizce extended sözcüğünden geliyor) getirilerek genişletilmiş 32 bit biçimleri kullanılabilir. EAX, EBX, ECX, EDX, EBP, EIP, ESP,... Bu durumda 32 bit genel amaçlı yazmaçlar bağımsız 4 kısımda kullanılabilirler.

EAX AX AH

AL

EBX BX BH

BL

ECX CX CH

CL

EDX DX DH

DL

Genişletilmiş yazmaçların yüksek anlamlı 16 bitinin ayrık bir biçimde kullanılmadığına dikkat ediniz. 32 bit ailede bunlardan başka: 2 ilave segment yazmacı(16 bit): FS, GS 4 tane korumalı modla ilgili yazmaç: GDTR, IDTR, LDTR, TR 3 tane kontrol yazmacı: CR0, CR1, CR2 8 debug yazmacı: DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7 5 test yazmacı: TR3, TR4, TR5, TR6, TR7 vardır.

8086 Yazmaç Yapısının Yapı ve Birliklerle Temsil Edilmesi Yazmaçları temsil için iki yapı ve bir birlik kullanılabilir. struct BYTEREGS { unsigned char al, ah, bl, bh; unsigned char cl, ch, dl, dh; }; struct WORDREGS { unsigned int ax, bx, cx, dx; unsigned int si, di, cflags, flags; }; union REGS { struct WORDREGS x; sturct BYTEREGS h; };

union REGS türünden bir değişken tanımlayalım; union REGS regs; regs birliğinin elemanlarının bellekteki yerleşimi şöyledir:

regs

regs.h.al regs.h.ah regs.h.bl regs.h.bh regs.h.cl regs.h.ch regs.h.dl regs.h.dh

regs.x.ax regs.x.bx regs.x.cx regs.x.dx regs.x.si regs.x.di regs.x.cflag regs.x.flags

union REGS türünün uzunluğunu sizeof (union REGS) ifadesi ile derleyiciye hesaplatabilirsiniz. regs.h.ah regs.h.al regs.h.ax ...

AX yazmacının yüksek anlamlı byte değeri AX yazmacının düşük anlamlı byte değeri AX yazmacının tamamı

Tabi union REGS biçiminde tanımladığımız bir değişken bellekte bir yerdedir. Oysa mikroişlemcinin yazmaçları kendi içerisindedir. Biz yalnızca bu birlik ile yazmaç takımlarının bellekte bir benzetimini yapmış olduk.

Birlik Kullanmanın Yararları Birlikler iki amaçla kullanılabilir. Birincisi yer kazanmak içindir. Birlik kullanarak farklı zamanlarda kullanılacak birden fazla değişken için ayrı ayrı yer ayırma zorunluluğu ortadan kaldırılır. Örneğin bir işletmede çalışan kişilerin maaş bilgilerini tutan bir yapı düşünün. Çalışanların bir kısmının banka hesap numaraları, banka hesap numaraları olmayanların sıra numaraları kullanıyor olsun. Bu iki bilgide aynı anda kullanılmayacaksa aşağıdaki gibi bir tanımlama yer kaybına yol açacaktır.

struct PERSON { char adi_soyadi[30]; char departman[20]; long maas; char hesap_no[15]; int sira_no; ... }; Oysa hesap_no ve sira_no bir birlik içinde ifade edilirse daha etkin bir yerleşim sağlanır. struct PERSON { char adi_soyadi[30]; char departman[20]; long maas; union { char hesap_no[15]; int sira_no; } hesap_sira_no; ... }; Birlik kullanmanın ikinci nedeni “bir bütünün parçaları üzerinde işlem yapmak yada parçalar üzerinde işlem yaparak bütünü oluşturmaktır.” Bunun için int türünden bir sayının byte değerlerini ayrıştırma örneğini inceleyebiliriz. struct WORD { unsigned char low_byte; unsigned char high_byte; }; union WORD_FORM { unsigned int x; struct WORD y; }; union WORD_FORM wf; Tanımlamalarından sonra wf.x elemanına değer atadığımızda wf.y.low_byte ve wf.y.high_byte ile yüksek ve alçak anlamlı byte değerleri üzerinde kolaylıkla işlem yapabiliriz. Birlikler konusunda uygulama amacıyla 80x86 sistemindeki kesmeler konusu ele alınacaktır.

Kesmeler(Interrupts) Kesmeler mikroişlemcinin o anda çalıştırdığı koda ara vererek başka bir kodu icra edilmesi durumudur. Kesmeler tanım olarak normal fonksiyon çağırmalarına benzeseler de birtakım farklılıkları vardır. Kesmeleri çağrılma biçimlerine göre 3 gruba ayırabiliriz. Kesmeler Yazılım kesmeleri

Donamın Kesmeleri

İçsel kesmeler

Yazım Kesmeleri(Software Interrupts): Bunlar programcının INT makine komutuyla programa dahil ettiği kesmelerdir. İşlevsel olarak fonksiyon çağırmadan büyük bir fark yoktur. Donanım Kesmeleri(Hardware Interrupts): Gerçek kesmeler donanım kesmeleridir. Donanım kesmeleri dışsal bir birim tarafından mikroişlemcinin INT ucunun aktive edilmesi yoluyla çağrılırlar. Intel tabanlı PC mimarisinde dışsal kesme birimi ile mikroişlemci arasındaki iletişimin “Kesme Denetleyicisi(Interrupt Controller)” diye isimlendirilen bir işlemci kurar. PC mimarisinde toplam 15 ayrı dışsal kesme tanımlanabilir(Bu dışsal kesmeler IRQ diye de isimlendirilebilmektedir). Dışsal kesmelerin çoğu tasarımsal olarak belli birimlere atanmışlardır. Örneğin 8 numaralı dışsal kesme 8254 zamanlayıcısı tarafından saniyede yaklaşık 18.2 kere çağrılarak birtakım işlemleri yerine getirir. Yine 9 numaralı dışsal kesme klavyenin tuşuna her basıldığında çağrılır. Klavyenin tuşuna her basıldığında 9H kesme kodu 8042 denetleyicisinden basılan tuşun scan kodunu alarak belleğin düşük anlamlı bölgesinde bulunan klavye tamponuna yazmaktadır. Böylece basılan tuşun kodları bellekte kullanıma hazır bir biçime getirilmiş olur. Bunların dışında örneğin ekrandaki farenin konum değiştirmesini sağlayanda bir donanım kesmesidir. Bu kesme seri port’tan farenin içerisindeki bir kontrol birimi yardımıyla periyodik olarak verilerek farenin hareket etmesinin sağlar. İçsel Kesmeler(Internel Interrupts): mikroişlemcinin bir makine kodunu icra ederken problemle karşılaştığında kendisinin çağırdığı kesmelerdir. Örneğin mikroişlemci DIV komutunu icra ederken bölen değerin 0 olduğunu görürse “0 nolu 0’a bölme(divide by zero)” kesmesini çağırır. Intelin 8086 işlemcileri korumalı modun sürekliliğini sağlamak için çok sayıda içsel kesme kullanırlar. İşletim sistemi tasarımcıları bu kesmeleri bellek ve proses kontrollerini sağlamak amacı ile yönlendirmektedir.

Intel İşlemcilerinde Kesmeler Intel işlemcilerinin toplam 256 kesme kapasitesi vardır. Her kesme bir numarayla ve genellikle HEX sistem kullanılarak belirtilir. Örneğin: 10H kesmesi, 21H kesmesi gibi... Kesmenin türü ne olursa olsun(yazılım kesmesi, donanım kesmesi yada içsel kesme) mikroişlemci kesme ile karşılaştığında aynı biçimde davranır. Tıpkı fonksiyon çağırmasında olduğu gibi, programa ara vererek kesme kodunu icra eder sonra programa kaldığı yerden devam eder.

Intel işlemcilerinde 256 kesme olsa da dallanma yordamıyla bu sayı istenildiği kadar çoğaltılabilir. Bir kesmenin farklı yollarına fonksiyon denir. Örneğin 10H kesmesinin birçok fonksiyonu vardır. Fonksiyon numarası genellikle AH yazmacının içerisine konur(AH yazmacı 8 bit olduğuna göre bir kesmenin en fazla 256 fonksiyonu olabilir). Fonksiyonlarda yine alt fonksiyonlar biçiminde dallar ayrılabilirler. Alt fonksiyon numarası ise genellikle AL yazmacının içerisinde saklanmaktadır. Tabi bir kesmenin fonksiyonu yada alt fonksiyonu olması zorunlu değildir. Kesmelerde tıpkı fonksiyonlar gibi parametre alabilir ve geri dönüş değeri verebilirler. Kesme parametreleri kesme çağrılmadan önce yazmaçlara yerleştirilir. Kesmelerin geri dönüş değerleri kesme çağrıldıktan sonra yazmaçlara alınır. Kesme parametrelerinin hangi yazmaçlara yerleştirileceği ve geri dönüş değerlerinin hangi yazmaçlardan alınacağı önceden belirlenmiştir.

Kesmelerin Çağrılması 8086 tabanlı mikroişlemcilerde yazmaçlar bellekte union REGS ile temsil edildikten sonra özel fonksiyonlarla kesme çağrılmaktadır. REGS birliğini daha önce ele almıştık. Bu birlik DOS.H başlık dosyası içerisinde bildirilmiştir. Kesme çağıran fonksiyonlar bellekteki yazmaç benzetimini alarak bunları mikroişlemcinin gerçek yazmaçlarına kopyalar ve kesmeyi çağırırlar. Bu fonksiyonlar kesme sonrasındaki yazmaç değerlerinin yine programcıya geri verirler. Aşağıda kesme çağırma amacı ile en sık kullanılan int86 fonksiyonu ele alınmaktadır Int86 Fonksiyonu: Kesme çağırmak için en sık kullanılan fonksiyon budur. Prototipi DOS.H içerisinde bildirilmiştir. Int Int86 (int interrupt_no, union REGS *inregs, union REGS *outregs); Bu fonksiyon ikinci parametresiyle yazmaç bilgilerini alarak gerçek CPU yazmaçlarına kopyalar. Daha sonra birinci parametresiyle belirtilen kesmeyi çağırır. Int86 kesme sonunda CPU yazmaçlarının durumunu üçüncü parametresi ile belirtilen adresten itibaren tekrar belleğe yazmaktadır. ...

inregs

Outregs

...

Kesme Parametreleri

Kesmenin Geri Dönüş Değerleri

...

...

Kesme çağırmadan önce kesme parametrelerinin union REGS biçiminde ifade edilerek adresin fonksiyonun ikinci parametresine geçirilmesi gerekir. Fonksiyon çağrıldıktan sonra int86 bu bilgileri CPU yazmaçlarına kopyalayarak çağıracaktır. Kesme

sonunda geri dönüş değerleri yine bu fonksiyon tarafından CPU yazmaçlarından alarak üçüncü parametresi ile belirtilen adrese yazılır.

Kesme İle İlgili Örnekler 10h kesmesi temel video işlemleri için kullanılır. Kendi içerisinde pek çok fonksiyona ve alt fonksiyona ayrılmaktadır. Aşağıda 10h ile ilgili birkaç örnek göreceksiniz. Video Modunun Değiştirilmesi INT 10h, fonksiyon 00h Parametreler: AH:fonksiyon numarası AL:video mod Geri dönüş değeri yok. Union REGS bildirimi için DOS.H dosyasını kaynak koda dahil etmelisiniz. #include<stdio.h> #include<dos.h> void set_video_mode(int mode) { union REGS regs; regs.h.ah = 0; regs.h.al = mode; int86(0x10, ®s, ®s); } int86 fonksiyonunun 2. parametresi ile 3. parametresinin aynı olduğuna dikkat ediniz. Bu durumda kesme çağrıldıktan sonra geri dönüş değerleri aynı adrese yazılarak parametre bilgilerini bozacaktır. Parametre bilgilerini kesme çağrıldıktan sonra kullanmayacağımıza göre bozulmasının da bizim için bir önemi olamaz. Video Modunun Alınması INT 10h, fonksiyon 0Fh Parametreler: AH:fonksiyon numarası Geri dönüş değeri AL:video mod İnt get_video_mode(void) { union REGS regs; regs.h.ah = 0x0F; int86(0x10, ®s, ®s); return regs.h.al; }

get_video_mode o andaki video modun hangisi olduğunu bulmakta kullanılır. Bu fonksiyonlar çalıştığınız derleyicinin kütüphanelerinde başka isimlerle zaten olabilirler. Dilerseniz uygulamada doğrudan onları da kullanabilirsiniz. Ancak o fonksiyonları yazanlarda yukarıdakilerden farklı bir şey yapmamışlardır. Bu iki kesme fonksiyonunu aşağıdaki kod ile deneyebilirsiniz. void main(void) { int mode; mode = get_video_mode(); set_video_mode(1); printf(“1 numaralı video modu \n”); getch(); set_video_mode(mode); } Deneme kodunuzda o anki video mod bir değişkende saklandıktan sonra 1 numaralı video moda geçilmiştir. Herhangi bir tuşa basarsanız eski video moda geri dönersiniz. Ekranda çıkacak yazının iriliği sizi şaşırtmasın çünkü 1 numaralı video mod VGA kartlarında 40x25 çözünürlüğe sahiptir. İmlecin Yerleştirilmesi Int 10h, fonksiyon 02h Parametreler: AH:fonksiyon numarası DH:imlecin yerleştirileceği satırın numarası(ilk satır 0) DL:imlecin yerleştirileceği sütunun numarası(ilk sütun 0) BH:sayfa numarası(0 olmalı) Geri dönüş değeri yok. İmlecin(kursör) konumu ancak yukarıdaki kesme ile değiştirilebilir. C’nin standart çıkış fonksiyonlarının imlecin bulunduğu yerden itibaren ekrana yazdığını unutmayınız. Printf, puts gibi standart fonksiyonlarla ekranın istediğiniz bir yerine bir şey yazdırmak istiyorsanız önce imleci oraya yerleştirmeniz gerekir. Bu fonksiyonun ismine de pos diyelim. void pos(int row, int col) { union REGS regs; regs.h.ah = 2; regs.h.dh = row; regs.h.dl = col; regs.h.bh = 0; int86(0x10, ®s, ®s); } Microsoft ve Borland derleyicilerinde aynı işlemi yapan gotoxy fonksiyonu vardır. O fonksiyonda bu kesme çağrılarak yazılmıştır. Ancak bizim yazdığımız pos

fonksiyonunda ilk parametrenin satır, ikinci parametrenin sütun olduğunu belirtelim. Ayrıca pos fonksiyonunda ekranın orjin noktası(0,0)dır. Gotoxy fonksiyonunda (1,1)dir. Aşağıdaki kod ile fonksiyonu test edebilirsiniz: void main(void) { pos(0,0); getch(); pos(24,79); getch(); pos(0,0); getch(); pos(25,80); getch(); pos(10,10); getch(); pos(0,0); getch(); }

/* Menzil dışı, imleç görünmez olur. */

İmleci görünmez yapmanın en iyi yolu menzil dışına çıkarmaktır. Örneğimizde pos(25,80) ile imleç görünmez yapılmıştır. Aşağıdaki kod ise imlecin yerini bulmamıza yarar. #include <dos.h> void posogren(satir, kolon) /* Bu fonksiyon, imlecin yerini BIOS yardımı */ unsigned *satir, *kolon; /* ile öğrenir */ { union REGS giris,cikis; giris.h.ah = 3; /* fonksiyon 3 - imlecin yerini oku */ giris.h.bh = 0; /* 0 inci sayfa.. */ int86(16,&giris,&cikis); *satir = cikis.h.dh; /* 3. fonksiyondan donen değerler: */ *kolon = cikis.h.dl; /* DH içinde, imlecin satir no su, */ } /* ve DL içinde kolon numarası.. */ Bu programı çalıştıran ana program, söyle olabilir: main() { int a,b; posogren(&a,&b); printf(" Program çalıştığında imleç %d. satir, %d. kolonda idi\n",a,b); } a ve b’nin adreslerinin geçirildiğine dikkatinizi çekerim.

Ekranı Silmek Ekranı silmek, iki yoldan olabilir. Birincisi, ekranın modunu değiştirmek. Değiştirdiğiniz mod, şu anki mod bile olsa, yine de ekran silinir. Yegane dezavantaj, Compaq tipi makinelerde bu işlem uzun zaman alır. Dolayısı ile, bu işi doğru yapmamız gerekir. #include <dos.h> void ekransil() /* bu rutin, ekranı siler */ { union REGS gir; gir.h.ah = 6; /* ekranı yukarı kaydır: servis no su 6 ekranı aşağı kaydır: servis no 7 dır. */ gir.h.al = 0; /* kaç satir scroll edeceği 'döneceği' sıfır olunca, bütün ekranı siler */ gir.h.ch = 0; /* sol üst kösenin satir no su */ gir.h.cl = 0; /* sol üst kösenin kolon no su */ gir.h.dh = 23; /* sağ alt kösenin satir no su */ gir.h.dl = 79; /* sağ alt kösenin kolon no su */ gir.h.bh = 7; /* yeni yaratılacak satırlar için renk değeri */ int86(16,&gir,&gir); } Altıncı BIOS servisi sayesinde, ekranı yukarı kaydırma metodu ile silmekteyiz. Ayni servis sayesinde, CX ve DX de gördüğünüz değerleri değiştirerek, ekranın sadece bir parçasını 'scroll' etmek yani kaydırmak mümkündür. Kaydırma yönünü servis numarasını 6 yada 7 yaparak değiştirebilirsiniz. Burada gördüğünü gir.h.bh deki değer ise, yeni açılacak satırların 'attribute' yani, rengi ve özellikleri(parlak, yanıp sonen, vs.) dır. Ayrıca, yukarıdaki örnekte, gir.h.ch = 0; gir.h.cl = 0; yerine, sadece gir.x.cx = 0; diyebilirdik. Printscreen Fonksiyonu #include <dos.h> main() { union REGS in; /* buna ihtiyacimiz yok, ama tanimlamamiz lazim */ int86(5,&in,&in); /* print-screen yapalim */ } Bu program, görevi ekranı olduğu gibi yazıcıya göndermek olan Interrupt 5’i kullanmaktadır. Artık klavyeden PRINTSCREEN tuşuna bastığınızda, sistemin ne yaptığını biliyorsunuz.

Sistem Saatini Öğrenme /* *************************************************** zamani_al /* Bu rutin, DOS u çağırarak, günün zamanını öğrenir. Çağıran /* programa kendisine geçirilmiş olan 3 pointer'da bu bilgiyi /* döndürür.. /* ************************************************************ zamani_al(saat,dakika,saniye) int *saat, *dakika, *saniye; { union REGS gir_reg; union REGS cik_reg; gir_reg.h.ah = 44; /* Hex 2C - Şimdiki zamanı al */ int86(0x21,&gir_reg,&cik_reg); *saat = cik_reg.h.ch; *dakika = cik_reg.h.cl; *saniye = cik_reg.h.dh; }

*/ */ */ */ */

Sistem Tarih ve Saatini Yazdırma /* *******************************************goster_zaman_tarih /* Bu rutin, zamanı ve tarihi ekranda sabit bir noktada /* gösterir. Zamanı zamani_al fonksiyonundan öğrenir, ve tarihi, /* kendi içindeki bir DOS çağrımından alır. İyi programlama /* tekniği, tarihin de ayrı bir rutine konmasını söyler, ama biz /* sadece islerin nasıl yapıldığını değişik yollardan göstermek /* amacı ile yapıyoruz. Bu rutin ayni zamanda cursor_koy ile /* saat ve tarihi sabit bir yere koyar. /* ************************************************************ goster_zaman_tarih() { int saat, dakika, saniye; union REGS gir_reg; union REGS cik_reg; cursoru_koy(19,19); /* Saat ve takvim için yer */ gir_reg.h.ah = 42; /* hex 2A - tarih nedir? */ int86(0x21,&gir_reg,&cik_reg); /* interrupt 21 */ printf("Tarih= %2d/%2d/%2d ", cik_reg.h.dh, /* ay - 1 den 12 */ cik_reg.h.dl, /* gün - 1 den 31 */ cik_reg.x.cx); /* yıl - 1980 den 2099*/ zamani_al(&saat, &dakika, &saniye); printf("Saat = %2d:%2d:%2d\n",saat, dakika, saniye); cursoru_koy(25,1); /* cursoru 26. satıra saklayalım */ }

*/ */ */ */ */ */ */ */ */

Pencere Kaydırma /* ********************************************** pencere_scroll /* Basılan tuş penceresindeki her şeyi bir satir yukarı kaydırır, /* yeni yazılacak şeylere yer acar. /* ************************************************************ pencere_scroll() { union REGS gir_reg; union REGS cik_reg; gir_reg.h.ah = 6; /* servis 6 - pencereyi scroll */ gir_reg.h.al = 1; /* kac satir kayacagi */ gir_reg.h.ch = 3; /* pencerenin ust satiri */ gir_reg.h.cl = 9; /* pencerenin sol kolonu */ gir_reg.h.dh = 17; /* pencerenin alt satiri */ gir_reg.h.dl = 69; /* pencerenin sag kolonu */ gir_reg.h.bh = 7; /* acilan bos satir(larin) 'rengi' */ int86(0x10,&gir_reg,&cik_reg); /* interrupt 10 */ }

*/ */ */ */

ASİ_GENC

Related Documents