Bölüm 5: Kesme Fonksiyonları

Mikroişlemciler
BIOS ve DOSHizmet çağırmaINT 10h videoÖznitelik baytıINT 16h klavyeINT 21h karakter G/ÇDizgi ve satır girişiTarih ve saatINT 1Ah ve BIOS veri alanıMod 13h grafikProgram sonlandırmaÖrnek: ikili yazdırma
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Hizmet çağırma

BIOS ve DOS hizmetlerini AH'deki fonksiyon numarası ve yazmaç parametreleriyle çağırmak.

Ekran çıktısı

INT 10h ve INT 21h ile karakter, renkli karakter ve dizgi yazdırmak; imleci konumlamak.

Klavye girişi

INT 16h ve INT 21h ile tuş okumak, tuş beklemeden yoklamak, satır okumak.

Saat ve sonlandırma

Tarih/saat bilgisini okuyup yazdırmak; programı RET, INT 20h ya da INT 21h/4Ch ile doğru sonlandırmak.

Giriş

BIOS ve DOS Hizmetleri

Uygulama programımov ah, 09h / int 21hDOS hizmetleri: INT 20h, INT 21hdosya, dizgi, saat/tarih, program sonuBIOS hizmetleri: INT 10h, 13h, 16h, 1AhROM'daki aygıt yordamlarıDonanımekran kartı, klavye denetleyicisi, disk, saatdoğrudan porterişimi (IN/OUT)
  • BIOS (Basic Input/Output System): anakarttaki ROM'da bulunan, donanımı doğrudan süren yordamlar. İşletim sistemi olmadan da çalışır; açılışta kesme vektör tablosunu doldurur.
  • DOS: BIOS'un üstünde; dosya, dizgi, saat ve program yönetimi sunar. Kendi işi için çoğu zaman BIOS'u çağırır.
  • Her iki katmana da yazılım kesmesi (INT n) ile ulaşılır; çağıranın hizmet adresini bilmesi gerekmez.
Aynı iş farklı katmanlarda yapılabilir: ekrana karakter INT 21h/02h (DOS), INT 10h/0Eh (BIOS) ya da doğrudan B800h ekran belleğine yazarak. Üst katman daha taşınabilir, alt katman daha hızlı ve esnektir.

Giriş

Hizmet Çağırma Kalıbı

  1. AH ← hizmet numarası (8 bit: en çok 256 hizmet)
  2. Diğer parametreler: AL, BX, CX, DX, DS:DX, ES:BP …
  3. INT n (10h, 16h, 21h …)
  4. Sonuç yazmaçlarda: AL, AX, CX, DX, ZF/CF …
mov ah, 02h    ; servis: karakter yaz
mov dl, 'A'    ; parametre
int 21h        ; DOS'u çağır
KesmeSağlayanGörev
INT 10hBIOSvideo: mod, imleç, karakter, dizgi
INT 16hBIOSklavye
INT 1AhBIOSsaat sayacı, gerçek zaman saati
INT 13hBIOSdisk
INT 20hDOSprogramı sonlandır (COM)
INT 21hDOSyüzlerce hizmet: G/Ç, dosya, saat, çıkış
Hizmetler kendi kullandıkları yazmaçları değiştirebilir (ör. INT 21h/02h ve 09h AL'yi); sonra gerekecek değerler başka yazmaçta ya da yığında saklanır. Bazı hizmetler AL'yi de alt seçim için kullanır (INT 10h, AX = 4F00h: VESA).

Giriş

Ekran ve Klavyede ASCII

KodAdEtki (0Eh / 02h)
07hBELzil sesi
08hBSimleç bir geri
09hTABsekme (DOS)
0AhLFbir alt satır
0DhCRsatır başı (Enter tuşu)
1BhESCEsc tuşu
KarakterASCIIİlişki
boşluk20h
'0' … '9'30h–39hrakam = kod − 30h
'A' … 'Z'41h–5Ahbit 5 = 0
'a' … 'z'61h–7Ahbit 5 = 1 (+20h)
'$'24h09h hizmetinde dizgi sonu
yalnız CR (0Dh)ABCyalnız LF (0Ah)ABCCR + LFABC
Yeni satır için iki karakter gerekir: 0Dh, 0Ah (CR LF). Yalnız LF imleci aşağı indirir ama satır başına getirmez. Türkçe harfler (ç, ğ, ı, ö, ş, ü) 7 bitlik ASCII'de yoktur; kod sayfasına (CP857) göre gösterilir.

INT 10h Video

INT 10h: BIOS Video Hizmetleri

AHHizmetGirişÇıkış / not
00hvideo modu seçAL = mod (03h: 80×25 renkli metin)ekran temizlenir
01himleç şekliCH = başlangıç, CL = bitiş satırıCH = 20h → imleç gizli
02himleç konumlaBH = sayfa, DH = satır, DL = sütun
03himleç konumu okuBH = sayfaDH, DL = konum; CH, CL = şekil
06hpencereyi yukarı kaydırAL = satır (0 = temizle), BH = öznitelik, CH,CL – DH,DL = köşelerekran/pencere silme
09hkarakter + öznitelik yazAL = karakter, BH = sayfa, BL = öznitelik, CX = sayıimleç ilerlemez
0Ahyalnız karakter yazAL, BH, CXmevcut öznitelik korunur
0Ehteletype çıkışıAL = karakter, BH = sayfaimleç ilerler; CR, LF, BS, BEL yorumlanır
13hdizgi yazAL = mod, BH, BL, CX = uzunluk, DH,DL, ES:BP = dizgiAT ve sonrası BIOS

INT 10h Video

AH = 00h: Video Modu ve Metin Ekranı

ALModBellek
01h40×25 metin, 16 renkB800h
03h80×25 metin, 16 renkB800h
07h80×25 tek renkB000h
04h320×200, 4 renkB800h
13h320×200, 256 renkA000h
mov ah, 00h
mov al, 03h   ; ya da mov ax, 0003h
int 10h      ; temiz 80×25 ekran
010203040506070790510152024(DH = 1, DL = 4)DL: sütun 0–79 →DHsatır0–24

emu8086 ekranı varsayılan olarak 80×25 metin modundadır; grafik modları sınırlı desteklenir.

INT 10h Video

İmleç Konumu: AH = 02h / 03h

  • Satır DH (0–24), sütun DL (0–79); sol üst köşe (0, 0).
  • BH = görüntü sayfası. 80×25 modda 8 sayfa (0–7) vardır; normalde 0 kullanılır.
  • İkisi tek komutla: mov dx, 0C28h → DH = 12, DL = 40 (ekranın ortası).
  • AH = 03h konumu okur: dönüşte DH, DL; ayrıca CH, CL imleç şekli.
  • INT 21h ile yazılan karakterler de bu imleç konumundan başlar.
; imleci ortaya al
mov ah, 02h
mov bh, 0
mov dx, 0C28h   ; 12. satır, 40. sütun
int 10h

; imleci bir sağa kaydır
mov ah, 03h
mov bh, 0
int 10h        ; DH, DL = konum
inc dl
mov ah, 02h
int 10h
(12, 40) → (12, 41)DH = 0Ch = 12 (satır), DL = 28h = 40 (sütun)03h ile oku → inc dl → 02h ile yaz: (12, 41)bağıl konum (12 × 80 + 40) × 2 = 07D0h
Ekran belleği karşılığı: (satır, sütun) hücresinin bağıl konumu = (satır × 80 + sütun) × 2. Örneğin (1, 4) → 84 × 2 = 00A8h; çift adreste karakter, tek adreste öznitelik.

INT 10h Video

Öznitelik (Attribute) Baytı

B7R6G5B4I3R2G1B0yanıp sönmearka plan RGBparlakön plan RGBÖrnek: 1Eh = 0001 1110b → mavi zemin, sarı (parlak kahverengi) yazı
0 siyah1 mavi2 yeşil3 camgöbeği4 kırmızı5 eflatun6 kahve7 açık gri8 koyu gri9 açık maviA açık yeşilB açık camg.C açık kırmızıD açık eflatunE sarıF beyaz
  • Öznitelik = arka plan × 16 + ön plan. 07h varsayılan (siyah üstüne açık gri), 1Fh mavi üstüne beyaz, 4Eh kırmızı üstüne sarı.
  • Bit 7 = 1 ise karakter yanıp söner (ya da BIOS ayarına göre arka plan parlak olur): 8Fh.

INT 10h Video

Öznitelik Gezgini

Seçilen renklerden öznitelik baytı ve INT 10h/09h çağrısı üretilir.

INT 10h Video

Karakter Yazma: AH = 09h mı, 0Eh mi?

ÖzellikAH = 09hAH = 0Eh (teletype)
GirişlerAL = karakter, BH = sayfa, BL = öznitelik, CX = tekrarAL = karakter, BH = sayfa
Renkvar (BL)metin modunda yok (hücrenin rengi korunur)
İmleçilerlemezilerler, satır sonunda alt satıra geçer
CR, LF, BS, BELsembol olarak basılır (♪, ◘ …)komut olarak yorumlanır
Ekran kaydırmayokson satırda ekran yukarı kayar
Tipik kullanımrenkli kutular, çerçeveler, aynı karakteri CX kezdüz metin akışı
AH = 09h, AL = '*', CX = 3***imleç başta kaldıAH = 0Eh, AL = 'A'Aimleç bir sağda
Renkli metin için yaygın kalıp: önce 09h ile karakteri renkli yaz (CX = 1), sonra imleci 02h ile bir sağa taşı; ya da tüm dizgi için 13h kullan.

INT 10h Video · Kodu adım adım çalıştır

Kod İzleme: Mod, İmleç, 09h ve 0Eh

AH = 00h (mod seç), AL = 03h (80×25, 16 renk metin). İki yazmaç tek komutla yüklenir.

int 10h: mod ayarlanır, ekran temizlenir, imleç (0,0)'a gider.

AH = 02h: imleç konumunu ayarla.

BH = görüntü sayfası (metin modunda 0–7; normalde 0).

DX = 0104h → DH = 1 (satır), DL = 4 (sütun). Sol üst köşe (0,0).

İmleç satır 1, sütun 4'e taşınır. Ekranda henüz bir şey yok.

AH = 09h: imleç konumuna AL'yi BL özniteliğiyle CX kez yaz.

Yazılacak karakter AL = '*' (2Ah).

BL = 4Eh: arka plan 4 (kırmızı), ön plan E (sarı).

Tekrar sayısı CX = 3.

Ekrana *** yazılır, ama 09h imleci ilerletmez: imleç hâlâ (1,4).

AH = 0Eh: teletype (daktilo) çıkışı.

AL = 'A'.

'A', imlecin bulunduğu (1,4)'e yazılır ve ilk yıldızın üzerine gelir; imleç (1,5)'e ilerler.

AL = 'B'. AH hâlâ 0Eh.

'B' (1,5)'e yazılır: ekranda AB*. 0Eh metin modunda öznitelik almaz; hücrelerdeki 4Eh rengi korunur.

09h imleci ilerletmez; yazdıktan sonra imleç AH = 02h ile ayrıca ilerletilir.

org 100h
mov ax, 0003h    ; AH=00h, AL=03h
int 10h          ; ekran silinir
mov ah, 02h      ; imleç konumla
mov bh, 0        ; sayfa 0
mov dx, 0104h    ; DH=1, DL=4
int 10h
mov ah, 09h      ; karakter + öznitelik
mov al, '*'
mov bl, 4Eh      ; kırmızı üstüne sarı
mov cx, 3        ; 3 kez
int 10h          ; imleç ilerlemez!
mov ah, 0Eh      ; teletype
mov al, 'A'
int 10h          ; imleç ilerler
mov al, 'B'
int 10h
ret

INT 10h Video

Demo: Metinden INT 10h Koduna

Yazılan metnin her karakteri için gereken MOV AL / INT 10h çifti ve ASCII kodları üretilir.

INT 10h Video · Kodu adım adım çalıştır

Kod İzleme: AH = 13h ile Renkli Dizgi

AH = 13h (dizgi yaz). AL = 01h: tüm karakterler BL özniteliğinde, yazdıktan sonra imleç ilerler.

BH = 0 (sayfa), BL = 1Eh: mavi (1) zemin, sarı (E) yazı.

CX = karakter sayısı. '$' gibi bir bitiş işareti yoktur.

DH = 2, DL = 5: yazmanın başlayacağı konum.

Dizginin adresi ES:BP'de olmalıdır (DS:DX değil!). COM programında ES = DS: BP = 0113h.

Satır 2, sütun 5'ten itibaren Merhaba yazılır; imleç (2,12)'ye gider.

AL = 00h olsaydı dizgi yine yazılır ama imleç eski yerinde kalırdı. AL = 02h/03h'te dizgi karakter, öznitelik çiftlerinden oluşur.

org 100h
mov ax, 1301h    ; AH=13h, AL=01h
mov bx, 001Eh    ; BH=0, BL=1Eh
mov cx, 7        ; dizgi uzunluğu
mov dx, 0205h    ; satır 2, sütun 5
lea bp, mesaj    ; ES:BP → dizgi
int 10h
ret
mesaj db 'Merhaba'

INT 10h Video

AH = 06h: Pencere Kaydırma ve Ekran Temizleme

YazmaçAnlamı
ALkaydırılacak satır sayısı; 0 = pencereyi temizle
BHboşalan satırların özniteliği
CH, CLsol üst köşe (satır, sütun)
DH, DLsağ alt köşe (satır, sütun)
  • AH = 07h aynı işi aşağı doğru yapar.
  • İmleç yerinde kalır; temizledikten sonra 02h ile (0,0)'a alın.
; tüm ekranı mavi zemine temizle
mov ax, 0600h   ; AH=06h, AL=0
mov bh, 1Fh     ; mavi/beyaz
mov cx, 0000h   ; (0,0)
mov dx, 184Fh   ; (24,79)
int 10h

; ortada 10×40'lık kırmızı kutu
mov ax, 0600h
mov bh, 4Fh
mov cx, 0714h   ; (7,20)
mov dx, 103Bh   ; (16,59)
int 10h
184Fh = satır 24 (18h), sütun 79 (4Fh). Mod 03h'ü yeniden seçmek de ekranı temizler, ama renkleri varsayılana (07h) döndürür.

INT 10h Video · Kodu adım adım çalıştır

Ekranı ve Bir Pencereyi Temizlemek

org 100h
mov ax, 0600h   ; AH=06h, AL=0
mov bh, 1Fh     ; mavi/beyaz
mov cx, 0000h   ; (0,0)
mov dx, 184Fh   ; (24,79)
int 10h
mov ax, 0600h
mov bh, 4Fh     ; kırmızı/beyaz
mov cx, 0714h   ; (7,20)
mov dx, 103Bh   ; (16,59)
int 10h
ret
AX0600hBH00hCX0000hDX0000hCH,CL = (0, 0)DH,DL = (0, 0)(0,0)(24,79)

AH = 06h (pencereyi yukarı kaydır), AL = 0: kaydırma yerine temizle.

AX0600hBH1FhCX0000hDX0000hCH,CL = (0, 0)DH,DL = (0, 0)(0,0)(24,79)

BH = 1Fh: boşalan hücrelerin özniteliği (zemin 1 mavi, yazı F beyaz).

AX0600hBH1FhCX0000hDX0000hCH,CL = (0, 0)DH,DL = (0, 0)(0,0)(24,79)

CX = 0000h → CH = 0 (satır), CL = 0 (sütun): sol üst köşe.

AX0600hBH1FhCX0000hDX184FhCH,CL = (0, 0)DH,DL = (24, 79)(0,0)(24,79)

DX = 184Fh → DH = 18h = 24, DL = 4Fh = 79: sağ alt köşe.

AX0600hBH1FhCX0000hDX184FhCH,CL = (0, 0)DH,DL = (24, 79)(0,0)(24,79)

INT 10h: 80 × 25 ekranın tamamı mavi zemine silinir. İmleç yerinde kalır.

AX0600hBH4FhCX0000hDX184FhCH,CL = (0, 0)DH,DL = (24, 79)(0,0)(24,79)

İkinci çağrı: AX = 0600h, BH = 4Fh (kırmızı zemin, beyaz yazı).

AX0600hBH4FhCX0714hDX184FhCH,CL = (7, 20)DH,DL = (24, 79)(0,0)(24,79)

CX = 0714h → (7, 20).

AX0600hBH4FhCX0714hDX103BhCH,CL = (7, 20)DH,DL = (16, 59)(0,0)(24,79)

DX = 103Bh → (16, 59): 10 satır × 40 sütunluk kutu.

AX0600hBH4FhCX0714hDX103BhCH,CL = (7, 20)DH,DL = (16, 59)(0,0)(24,79)

INT 10h: yalnız bu pencere kırmızıya silinir; dışı mavi kalır.

AX0600hBH4FhCX0714hDX103BhCH,CL = (7, 20)DH,DL = (16, 59)(0,0)(24,79)

RET: program biter.

Yazmaç değerleri yorumlayıcıda çalıştırılarak alındı; yorumlayıcı 06h'nin ekran etkisini benzetmez, ekran BIOS tanımına göre çizildi.

INT 10h Video

BIOS'suz Çıktı: B800h Ekran Belleği

  • Mod 03h'te ekran, B800:0000h'dan başlayan 4000 baytlık bellekte tutulur (80 × 25 × 2).
  • Her hücre 2 bayt: karakter (çift adres) + öznitelik (tek adres).
  • Belleğe yazılan değer ekran kartı tarafından anında gösterilir: kesme çağrısından çok daha hızlı.
  • Sözcük olarak yazarken little-endian: 4E41h → 41h ('A') düşük adrese, 4Eh özniteliğe.
; (1,4) hücresine sarı/kırmızı 'A'
mov ax, 0B800h
mov es, ax
mov di, (1*80+4)*2  ; 00A8h
mov ax, 4E41h
mov es:[di], ax

; tüm ekranı '.' ile doldur
xor di, di
mov ax, 072Eh
mov cx, 2000
cld
rep stosw
41hB800:00A8 · karakter 'A'4EhB800:00A9 · öznitelikmov es:[di], ax (AX = 4E41h)düşük bayt 41h → çift adres (karakter)
Doğrudan yazma imleci hareket ettirmez ve BIOS'un tuttuğu imleç bilgisini güncellemez. emu8086 bu belleği de destekler.

INT 10h Video · Kodu adım adım çalıştır

Ekran Belleğine Doğrudan Yazmak

org 100h
mov ax, 0B800h
mov es, ax
mov di, (1*80+4)*2  ; 00A8h
mov ax, 4E41h
mov es:[di], ax
xor di, di
mov ax, 072Eh
mov cx, 3           ; ilk 3 hücre
cld
rep stosw
ret
ESB800hDI0000hAXB800hCX0000hB800:0000…000000000000B800:00A80000karakter · öznitelikekran: satır 0–1, sütun 0–5

ES = B800h: mod 03h metin ekranının kesimi. Kesim yazmacına sabit doğrudan yazılamadığı için AX üzerinden.

ESB800hDI00A8hAXB800hCX0000hB800:0000…000000000000B800:00A80000karakter · öznitelikekran: satır 0–1, sütun 0–5

(1, 4) hücresi: (1 × 80 + 4) × 2 = 168 = 00A8h. Çarpım derleme zamanında hesaplanır.

ESB800hDI00A8hAX4E41hCX0000hB800:0000…000000000000B800:00A80000karakter · öznitelikekran: satır 0–1, sütun 0–5

AX = 4E41h: AL = 41h ('A', karakter), AH = 4Eh (öznitelik: kırmızı zemin, sarı yazı).

ESB800hDI00A8hAX4E41hCX0000hB800:0000…000000000000B800:00A8414Ekarakter · öznitelikAekran: satır 0–1, sütun 0–5

MOV ES:[DI], AX: little-endian → B80A8h ← 41h, B80A9h ← 4Eh. Karakter anında ekranda; imleç yerinde kalır.

ESB800hDI0000hAX4E41hCX0000hB800:0000…000000000000B800:00A8414Ekarakter · öznitelikAekran: satır 0–1, sütun 0–5

DI = 0: sol üst köşe.

ESB800hDI0000hAX072EhCX0003hB800:0000…000000000000B800:00A8414Ekarakter · öznitelikAekran: satır 0–1, sütun 0–5

AX = 072Eh ('.' + 07h açık gri), CX = 3.

ESB800hDI0000hAX072EhCX0003hB800:0000…000000000000B800:00A8414Ekarakter · öznitelikAekran: satır 0–1, sütun 0–5

CLD: DF = 0, DI artarak ilerler.

ESB800hDI0006hAX072EhCX0000hB800:0000…2E072E072E07B800:00A8414Ekarakter · öznitelik...Aekran: satır 0–1, sütun 0–5

REP STOSW: ES:[DI] ← AX, DI += 2, CX kez → ilk 3 hücre '.' oldu; DI = 0006h, CX = 0. (Tüm ekran için CX = 2000.)

ESB800hDI0006hAX072EhCX0000hB800:0000…2E072E072E07B800:00A8414Ekarakter · öznitelik...Aekran: satır 0–1, sütun 0–5

RET: program biter.

INT 10h Video

Mod 13h: 320×200, 256 Renk

  • mov ax, 0013h / int 10h: 320 × 200 grafik modu. Görüntü belleği A000:0000h – A000:F9FFh (64 000 bayt).
  • Her piksel 1 bayt: renk numarası (palet girişi). İlk 16 renk metin renkleriyle aynıdır: 0Eh sarı, 0Fh beyaz.
  • Satır başına 320 = 140h bayt: bağıl konum = y · 320 + x.
  • Örnek: (100, 50) → 50 · 320 + 100 = 16 100 = 3EE4h.
INT 10h / AH = 0Ch: piksel yaz
ALrenk
BHsayfa (mod 13h'te 0)
CX / DXx (sütun 0–319) / y (satır 0–199)

AH = 0Dh aynı CX, DX ile pikselin rengini AL'ye okur.

x=0x=1x=2x=3x=319y=00000000100020003013Fy=10140014101420143027Fy=2028002810282028303BFy=199F8C0F8C1F8C2F8C3F9FF…………⋮⋮ofset = y·320 + x · turuncu köşegen: +141h

INT 10h Video

Köşegen Çizgi: BIOS ile ve A000h ile

INT 10h / 0Ch: koordinatla

mov ax, 0013h
int 10h          ; 320×200, 256 renk
xor cx, cx       ; x = 0
xor dx, dx       ; y = 0
mov bh, 0        ; sayfa
nokta: mov ax, 0C0Eh ; AH=0Ch, AL=sarı
int 10h
inc cx           ; bir sağ
inc dx           ; bir alt
cmp dx, 200
jb  nokta         ; 200 piksel
Neden 141h? +140h (320) bir alt satırın aynı sütununa, +1 bir sağ sütuna gider: 141h = 321. Son piksel (199, 199) = 199 · 321 = F987h. Sağ üstten inen ters köşegen için 13Fh (320 − 1) eklenir.

A000h belleği: bağıl konumla

mov ax, 0013h
int 10h
mov ax, 0A000h
mov es, ax
xor di, di       ; (0,0) → ofset 0
mov al, 0Eh      ; sarı
mov cx, 200
ciz: mov es:[di], al
add di, 141h     ; 320 + 1
loop ciz
mov ah, 0
int 16h          ; tuş bekle
mov ax, 0003h
int 10h          ; metin moduna dön

Belleğe doğrudan yazma, her piksel için kesme çağırmaktan çok daha hızlıdır.

emu8086'nın grafik desteği sınırlıdır: 0Ch yavaş çizer, A000h'a doğrudan yazma her sürümde görünmeyebilir; DOSBox'ta tam görünür.

INT 10h Video · Kodu adım adım çalıştır

Mod 13h Belleğine Köşegen Çizmek

org 100h
mov ax, 0A000h
mov es, ax
xor di, di       ; (0,0) → ofset 0
mov al, 0Eh      ; sarı
mov cx, 4        ; ilk 4 piksel
ciz: mov es:[di], al
add di, 141h     ; 320 + 1
loop ciz
ret
ESA000hDI0000hCX0000hAL00hDI = 0 → y = 0, x = 0satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

ES = A000h: mod 13h görüntü belleği (320 × 200, piksel başına 1 bayt).

ESA000hDI0000hCX0000hAL00hDI = 0 → y = 0, x = 0satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

DI = 0: (x, y) = (0, 0) piksel bağıl konumu y · 320 + x = 0.

ESA000hDI0000hCX0004hAL0EhDI = 0 → y = 0, x = 0satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

AL = 0Eh (sarı), CX = 4: ilk 4 pikseli çiz.

ESA000hDI0141hCX0003hAL0EhDI = 321 → y = 1, x = 1satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

ES:[0000h] ← 0Eh: piksel (0, 0). ADD DI, 141h → DI = 0141h (bir alt satır + bir sağ). LOOP: CX = 3.

ESA000hDI0282hCX0002hAL0EhDI = 642 → y = 2, x = 2satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

ES:[0141h] ← 0Eh: piksel (1, 1). ADD DI, 141h → DI = 0282h (bir alt satır + bir sağ). LOOP: CX = 2.

ESA000hDI03C3hCX0001hAL0EhDI = 963 → y = 3, x = 3satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

ES:[0282h] ← 0Eh: piksel (2, 2). ADD DI, 141h → DI = 03C3h (bir alt satır + bir sağ). LOOP: CX = 1.

ESA000hDI0504hCX0000hAL0EhDI = 1284 → y = 4, x = 4satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

ES:[03C3h] ← 0Eh: piksel (3, 3). ADD DI, 141h → DI = 0504h (bir alt satır + bir sağ). LOOP: CX = 0. Döngü biter.

ESA000hDI0504hCX0000hAL0EhDI = 1284 → y = 4, x = 4satır başına 320 = 140h bayt+141h = bir alt, bir sağekranın sol üstü (6 × 6 piksel)

RET. 200 tur sürseydi son piksel (199, 199) = 199 · 321 = F987h olurdu.

INT 10h Video

Piksel Adresi Gezgini (320 × 200)

Ekrana tıklanınca (x, y) için y · 320 + x bağıl konumu ve fiziksel adres hesaplanır.

INT 16h Klavye

INT 16h: BIOS Klavye Hizmetleri

AHHizmetÇıkış
00htuş bekle ve okuAH = tarama kodu, AL = ASCII; tuş tampondan silinir
01htuş var mı? (beklemez)ZF = 1: yok · ZF = 0: AX = tuş, tampondan silinmez
02hShift durumlarıAL bitleri: 0 sağ Shift, 1 sol Shift, 2 Ctrl, 3 Alt, 4 Scroll, 5 Num, 6 Caps, 7 Insert
TuşAH (tarama)AL (ASCII)
a / A1Eh61h / 41h
102h31h
Enter1Ch0Dh
Esc01h1Bh
Boşluk39h20h
TuşAH (tarama)AL
↑ / ↓48h / 50h00h
← / →4Bh / 4Dh00h
F1 … F103Bh … 44h00h
Backspace0Eh08h
Ctrl+C2Eh03h

Tarama kodu tuşun klavyedeki fiziksel konumudur: 'a' ve 'A' aynı tarama kodunu verir. ASCII karşılığı olmayan (genişletilmiş) tuşlarda AL = 00h olur; tuş AH'den tanınır. Program sonundaki MOV AH, 0 · INT 16h çıktı ekranı kapanmadan okunabilsin diye bir tuş bekler.

INT 16h Klavye

Klavye Gezgini: INT 16h / AH = 00h Ne Döndürür?

AH (tarama kodu)--
AL (ASCII)--
AX----

Harfler, rakamlar, ok tuşları, F1–F10, Enter, Esc ve Ctrl+harf tanınır. Değerler IBM PC/AT klavye düzenine (US) göredir.

INT 16h Klavye · Kodu adım adım çalıştır

Kod İzleme: Enter'a Kadar Oku, Büyük Harfle Yaz

AH = 00h: klavye tamponundan bir tuş bekle ve al.

Kullanıcı O (Shift+o) bastı: AL = 4Fh (ASCII), AH = 18h (tarama kodu).

4Fh ≠ 0Dh.

Enter değil, devam.

'O' (4Fh) < 'a' (61h) → CF = 1.

Küçük harf değil → doğrudan yaz.

AH = 0Eh (teletype). AL'de yazılacak karakter var.

Ekrana O.

Sonraki tuşa dön.

AH = 00h: klavye tamponundan bir tuş bekle ve al.

Kullanıcı k bastı: AL = 6Bh, AH = 25h.

6Bh ≠ 0Dh.

Devam.

'k' ≥ 'a' → CF = 0.

Küçük harf olabilir, devam.

6Bh − 7Ah: ödünç → CF = 1, ZF = 0. Yani 'k' < 'z'.

ja CF = 0 ve ZF = 0 ister; CF = 1 → atlama yok: küçük harf.

Bit 5 temizlenir: 6Bh − 20h = 4Bh = 'K'.

AH = 0Eh (teletype). AL'de yazılacak karakter var.

Ekrana K.

Sonraki tuşa dön.

AH = 00h: klavye tamponundan bir tuş bekle ve al.

Kullanıcı Enter bastı: AL = 0Dh, AH = 1Ch.

AL = 0Dh → ZF = 1.

Enter → bitti.

Enter'da program biter. INT 16h/00h tuşu ekrana yansıtmaz; yansıtma programda yapıldı.

org 100h
oku:
mov ah, 0        ; tuş bekle
int 16h          ; AH=tarama, AL=ASCII
cmp al, 0Dh      ; Enter?
je bitti
cmp al, 'a'
jb yaz
cmp al, 'z'
ja yaz
sub al, 20h      ; küçük → büyük
yaz:
mov ah, 0Eh
int 10h          ; ekrana yaz
jmp oku
bitti:
ret

INT 16h Klavye · Kodu adım adım çalıştır

Kod İzleme: AH = 01h ile Beklemeden Yoklama

DX = 0: bekleme sırasında yapılan işi sayacağız.

Arka planda iş yapılıyor: DX = 0001h.

AH = 01h: tuş durumunu sorgula (beklemez).

Tamponda tuş yok → ZF = 1.

ZF = 1 → bekle'ye dön; program donmaz.

Arka planda iş yapılıyor: DX = 0002h.

AH = 01h: tuş durumunu sorgula (beklemez).

Hâlâ tuş yok → ZF = 1.

Yoklamaya devam.

Arka planda iş yapılıyor: DX = 0003h.

AH = 01h: tuş durumunu sorgula (beklemez).

Tuş geldi: ZF = 0, AL = 'x' (78h), AH = 2Dh. Tuş tamponda kalır.

ZF = 0 → döngüden çık.

Tuşu tampondan almak için AH = 00h.

Aynı tuş okunur ve tampondan silinir: AL = 'x', AH = 2Dh.

Oyunlarda ve animasyonlarda bu kalıp kullanılır: çalışmayı sürdür, tuşa basılınca tepki ver.

org 100h
xor dx, dx       ; iş sayacı
bekle:
inc dx           ; arka plan işi
mov ah, 01h      ; tuş var mı?
int 16h          ; ZF=1 → yok
jz bekle
mov ah, 00h      ; tuşu tampondan al
int 16h
ret

INT 21h DOS

INT 21h: Sık Kullanılan DOS Hizmetleri

AHHizmetGirişÇıkış
01hkarakter oku, yansıt–AL = karakter
02hkarakter yazDL = karakterAL = DL
07h / 08hkarakter oku, yansıtmadan–AL (08h Ctrl+C'yi denetler)
09hdizgi yazDS:DX → '$' ile biten dizgiAL = 24h
0Ahtamponlu satır okuDS:DX → tampontampon[1] = sayı, tampon+2 = metin
2Ahtarihi al–CX = yıl, DH = ay, DL = gün, AL = gün adı (0 = Pazar)
2Chsaati al–CH = saat, CL = dakika, DH = saniye, DL = salise
2Bh / 2Dhtarihi / saati ayarla2Ah / 2Ch ile aynı yazmaçlarAL = 00h başarılı
4Chprogramı sonlandırAL = çıkış kodu(dönmez)

DOS hizmetleri G/Ç yönlendirmesine uyar: program > cikti.txt ile 02h/09h çıktısı dosyaya gider; BIOS INT 10h çıktısı ise her zaman ekrana gider.

INT 21h DOS

INT 10h/0Eh mi, INT 21h/02h mi?

BIOS · INT 10h, AH = 0Eh
  • Karakter AL'de.
  • Doğrudan video BIOS'u; DOS gerekmez.
  • Açılış (boot) kodunda da çalışır.
  • Renk (grafik modda BL) verilebilir.
DOS · INT 21h, AH = 02h
  • Karakter DL'de.
  • DOS çağrısı; çıktı yönlendirilebilir (dosyaya, yazıcıya).
  • Dönüşte AL = DL olur.
  • Ctrl+Break denetimi yapılır.
İkisi de bir karakter yazar ve imleci ilerletir; seçim, programın hangi ortamda çalışacağına bağlıdır. Aynı programda karıştırılabilir.

INT 21h DOS · Kodu adım adım çalıştır

Kod İzleme: Karakter Oku, Yeni Satır, Karakter Yaz

AH = 01h: klavyeden bir karakter bekle ve ekrana yansıt.

Kullanıcı k bastı: AL = 6Bh, ekranda 'k' göründü.

AL sonraki INT 21h çağrılarında değişeceği için BL'de saklanır.

AH = 02h: DL'deki karakteri yaz.

DL = 0Dh (Carriage Return).

İmleç satır başına döner (görünür bir değişiklik yok).

DL = 0Ah (Line Feed).

İmleç bir alt satıra iner. Yeni satır = CR + LF.

BL = 6Bh + 1 = 6Ch = 'l'.

DL = 'l'.

Ekrana l yazılır. 02h sonrası AL de yazılan karakteri içerir.

Program biter.

org 100h
mov ah, 01h      ; oku + yansıt
int 21h          ; AL = karakter
mov bl, al       ; sakla
mov ah, 02h      ; karakter yaz
mov dl, 0Dh      ; CR: satır başı
int 21h
mov dl, 0Ah      ; LF: alt satır
int 21h
inc bl           ; sonraki harf
mov dl, bl
int 21h
ret

INT 21h DOS · Kodu adım adım çalıştır

Kod İzleme: AH = 09h ile Dizgi Yazdırma

DX = 010Dh: dizginin bağıl konumu. Kesim DS'dir.

AH = 09h: '$' ile biten dizgiyi yaz.

'$' görülene kadar yazılır; 0Dh 0Ah satırı bitirir. Dönüşte AL = 24h ('$').

İkinci dizgi: DX = 011Eh.

AH değişmediği için yeniden yüklemek gerekmez (yine de yüklemek iyi alışkanlıktır).

Çıktı iki satır. '$' karakterinin kendisi bu hizmetle yazdırılamaz.

org 100h
mov dx, offset msg1   ; DS:DX → dizgi
mov ah, 09h
int 21h
mov dx, offset msg2
int 21h               ; AH hâlâ 09h
ret
msg1 db 'Merhaba, 8086!', 0Dh, 0Ah, '$'
msg2 db 'Gule gule$'

INT 21h DOS

AH = 0Ah: Tamponlu Satır Girişi

0Ah+0?+1?+2?+3?+4?+5?+6en fazlaokunankarakterler …DS:DX →

Program tamponu hazırlar: tampon db 10, ?, 10 dup(?). Bayt 0 = en fazla 10 karakter (Enter dahil).

0Ah+0?+1'A'+2?+3?+4?+5?+6en fazlaokunankarakterler …DS:DX →

Kullanıcı A yazar: karakter 2. konuma gelir ve ekrana yansıtılır. Backspace ile düzeltme yapılabilir.

0Ah+0?+1'A'+2'l'+3'i'+4?+5?+6en fazlaokunankarakterler …DS:DX →

l ve i de eklenir.

0Ah+003h+1'A'+2'l'+3'i'+40Dh+5?+6en fazlaokunankarakterler …DS:DX →

Enter: 0Dh sona yazılır; DOS bayt 1'e okunan sayıyı (3, CR hariç) yazar ve döner.

0Ah+003h+1'A'+2'l'+3'i'+4'$'+5?+6en fazlaokunankarakterler …DS:DX →

Metin tampon+2'den başlar, uzunluğu [tampon+1]'dedir. '$' ile bitmez; 09h ile yazdırmak için 0Dh yerine '$' konur.

  • DOS satır düzenlemeyi kendisi yapar (Backspace, Esc); Enter'a basılana kadar program beklemez, çalışmaz.
  • Tampon dolunca fazla tuşlar kabul edilmez ve zil çalar. İlk bayt 0 olamaz.

INT 21h DOS · Kodu adım adım çalıştır

Kod İzleme: İsim Oku, Selam Ver

DS:DX tamponu gösterir: DX = 0120h.

AH = 0Ah: Enter'a kadar satır oku.

Kullanıcı Ali⏎ yazdı. DOS: tampon[1] = 3, tampon[2..4] = 'Ali', tampon[5] = 0Dh. Enter yalnızca CR basar: imleç satır başında.

BL = okunan karakter sayısı = 3 (CR sayılmaz).

BX = 0003h; adres hesaplamasında kullanılacak.

tampon[3 + 2] = tampon[5]: 0Dh yerine '$' yazılır → dizgi AH = 09h ile yazılabilir.

DX = selam.

AH = 09h.

CR LF + 'Merhaba ' yazılır (yeni satırda).

DX = tampon + 2: girilen metnin başlangıcı (0122h).

Çıktı: Merhaba Ali.

tampon[0] = 10: en çok 9 karakter + CR. Fazlası kabul edilmez (DOS zil sesi çalar).

org 100h
mov dx, offset tampon
mov ah, 0Ah          ; tamponlu giriş
int 21h
mov bl, [tampon+1]   ; okunan sayı
mov bh, 0
mov byte ptr tampon[bx+2], '$'
mov dx, offset selam
mov ah, 09h
int 21h
lea dx, [tampon+2]
int 21h
ret
tampon db 10, ?, 10 dup(?)
selam  db 0Dh, 0Ah, 'Merhaba $'

INT 21h DOS

AH = 2Ah / 2Ch: Tarih ve Saat

AH = 2Ah (tarih)
CXyıl (ör. 07EAh = 2026)
DHay (1–12)
DLgün (1–31)
ALhaftanın günü (0 = Pazar … 6 = Cumartesi)
AH = 2Ch (saat)
CHsaat (0–23)
CLdakika (0–59)
DHsaniye (0–59)
DLsalise (0–99)
; gün adını yazdır
mov ah, 2Ah
int 21h          ; AL = 0…6
mov ah, 0
mov bl, 4
mul bl           ; AX = AL × 4
mov dx, offset gunler
add dx, ax
mov ah, 09h
int 21h
ret
gunler db 'Paz$Pzt$Sal$Car$'
       db 'Per$Cum$Cmt$'
Değerler ikili sayıdır, BCD değil: saat 14 → CH = 0Eh. Ekrana yazmak için AAM ya da 10'a bölme kullanılır. BIOS'taki INT 1Ah/02h ise saati BCD olarak verir.

INT 21h DOS · Kodu adım adım çalıştır

Tablodan Gün Adı: AL × 4

org 100h
mov ah, 2Ah
int 21h          ; AL = 0…6
mov ah, 0
mov bl, 4
mul bl           ; AX = AL × 4
mov dx, offset gunler
add dx, ax
mov ah, 09h
int 21h
ret
gunler db 'Paz$Pzt$Sal$Car$'
       db 'Per$Cum$Cmt$'
AL00hBL00hAX2A00hDX0000hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24ekran▌

AH = 2Ah: DOS tarih hizmeti.

AL03hBL00hAX2A03hDX0000hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24ekran▌

INT 21h dönüşte CX = yıl, DH = ay, DL = gün ve AL = haftanın günü verir. Örnek gün Çarşamba: AL = 3 (0 = Pazar).

AL03hBL04hAX0003hDX0000hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24ekran▌

AH = 0 (AX = 0003h), BL = 4: her gün adı '$' dahil 4 bayt.

AL0ChBL04hAX000ChDX0000hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24ekran▌

MUL BL: AX = 3 × 4 = 12 = 000Ch: tablodaki bağıl konum.

AL0ChBL04hAX000ChDX0114hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24ekran▌

DX = gunler = 0114h.

AL0ChBL04hAX000ChDX0120hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24DXekran▌

ADD DX, AX → DX = 0120h: 'Car$' dizgisinin başı.

AL24hBL04hAX0924hDX0120hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24DXekranCar▌

AH = 09h, INT 21h: DS:DX'ten '$'a kadar → ekranda Car.

AL24hBL04hAX0924hDX0120hgunler (0114h): 7 × 4 baytPaz$+0Pzt$+4Sal$+8Car$+12Per$+16Cum$+20Cmt$+24DXekranCar▌

RET: program biter.

Yorumlayıcıda INT 21h/2Ah olmadığından çalıştırılan kopyada bu satır, aynı uzunluktaki mov al, 3 ile değiştirildi (örnek gün Çarşamba).

INT 21h DOS · Kodu adım adım çalıştır

Kod İzleme: Saati SS:DD Biçiminde Yazdırma

AH = 2Ch: sistem saatini oku.

Dönüş: CH = 14 (0Eh) saat, CL = 35 (23h) dakika, DH = 7 saniye, DL = 42 salise.

AL = saat = 0Eh.

Prosedür çağrılır: dönüş adresi yığında.

aam: 14 → AH = 1, AL = 4.

Her iki basamak ASCII'ye: AX = 3134h.

BX'te sakla; INT 21h/02h AL'yi değiştirir.

DL = onlar basamağı.

AH = 02h.

Ekrana '1'.

DL = birler basamağı.

Ekrana '4' → 14.

Prosedürden dönülür.

DL = ':'.

AH = 02h.

Ekrana ':'.

AL = dakika = 23h (35). CL hiçbir çağrıda bozulmadı.

Dakika için aynı prosedür.

35 → AH = 3, AL = 5.

Her iki basamak ASCII'ye: AX = 3335h.

BX'te sakla; INT 21h/02h AL'yi değiştirir.

DL = onlar basamağı.

AH = 02h.

Ekrana '3'.

DL = birler basamağı.

Ekrana '5' → 14:35.

Prosedürden dönülür.

Ekranda 14:35. Tarih için AH = 2Ah: CX = yıl, DH = ay, DL = gün, AL = haftanın günü.

org 100h
mov ah, 2Ch       ; sistem saatini al
int 21h           ; CH=saat CL=dakika
mov al, ch
call yaz2
mov dl, ':'
mov ah, 02h
int 21h
mov al, cl
call yaz2
ret
yaz2:             ; AL (0-99) → 2 hane
aam               ; AH=onlar AL=birler
add ax, 3030h     ; ASCII
mov bx, ax
mov dl, bh
mov ah, 02h
int 21h
mov dl, bl
int 21h
ret

INT 1Ah ve BIOS Verileri

INT 1Ah: Saat Sayacı ve Gerçek Zaman Saati

AHİşlevDönüş
00htık sayacını okuCX:DX = gece yarısından beri tık, AL = gün döndü bayrağı
02hRTC saatini okuCH = saat, CL = dakika, DH = saniye (BCD), DL = yaz saati; CF = 1: hata
04hRTC tarihini okuCH = yüzyıl, CL = yıl, DH = ay, DL = gün (BCD); CF = 1: hata

RTC, pille beslenen CMOS saatidir (AT ve sonrası); bilgisayar kapalıyken de çalışır.

Paketli BCD → ASCII (CL = 35h, yani dakika 35)

35h = 0011 0101b

Her 4 bit bir onluk basamaktır: yüksek nibble 3, düşük nibble 5.

shr dl, cl (CL = 4) → 03h

Üst basamak sağa kaydırılır. 8086'da 1'den büyük kaydırma sayısı CL ile verilir.

and dl, 0Fh → 05h

Alt basamak maskelenir.

+30h → '3' 33h, '5' 35h

Her basamak ASCII rakama çevrilir. INT 21h/2Ch ise aynı dakikayı ikili verir: CL = 23h; orada AAM gerekir.

emu8086'nın desteklediği kesmeler arasında INT 1Ah için yalnızca 00h (tık sayacı) bulunur; 02h gerçek DOS ya da DOSBox'ta çalışır. emu8086'da saat INT 21h/2Ch ile okunur.

INT 1Ah ve BIOS Verileri · Kodu adım adım çalıştır

Kod İzleme: RTC Saatini SS:DD:ss Yazdırma

AH = 02h: BIOS gerçek zaman saatini (RTC) oku.

Dönüş paketli BCD: CH = 14h (saat 14), CL = 35h (dakika 35), DH = 07h (saniye). DL = 00h (yaz saati yok).

CF = 0: okuma başarılı. CF = 1 olsaydı saat çalışmıyor demekti; program yazdırmadan biterdi.

CL'ye birazdan kaydırma sayısı yazılacak; dakika önce BL'ye kopyalanır.

CL = 4: SHR DL, CL 4 bit kaydıracak (8086'da 1'den büyük sabit kaydırma yok).

BH = saat = 14h. Prosedür değeri BH'de bekler; INT 21h/02h BH'yi bozmaz.

Saat için prosedür çağrılır (ikinokta atlanır, doğrudan bcdyaz).

DL = BH = 14h = 0001 0100b.

shr dl, cl: 0001 0100b → 0000 0001b. DL = 01h, yani üst basamak.

+30h: DL = 31h = '1'.

AH = 02h: DL'deki karakteri yaz.

Ekrana '1'. DOS, AL'ye DL'yi koyar (AL = 31h).

DL = BH = 14h (ikinci basamak için yeniden).

and dl, 0Fh: üst 4 bit silinir: 0000 0100b = 04h.

+30h: DL = 34h = '4'.

Ekrana '4' → 14. AH hâlâ 02h olduğundan yeniden yüklemek gerekmez.

Prosedürden dönülür.

BH = dakika = 35h (BL'de saklanmıştı).

Bu kez ikinokta girişi çağrılır: önce ':' yazar, sonra bcdyaz'a düşer.

DL = ':' (3Ah).

AH = 02h.

Ekrana ':' → 14:. Ardından komut bcdyaz etiketine kendiliğinden geçer (fall-through).

35h → 03h (üst basamak).

Ekrana '3' (33h).

35h AND 0Fh = 05h.

Ekrana '5' → 14:35.

Dönülür.

BH = saniye = 07h. DH, INT 21h/02h tarafından değiştirilmedi.

Saniye için yine ikinokta.

DL = ':'.

Ekrana ':' → 14:35:.

07h → 00h (üst basamak).

Ekrana '0' (30h).

07h AND 0Fh = 07h.

Ekrana '7' → 14:35:07.

Dönülür.

Ekranda 14:35:07. Aynı saat INT 21h/2Ch ile ikili (CH = 0Eh, CL = 23h) gelirdi; BCD'de onaltılık basamaklar doğrudan onluk basamaklardır.

org 100h
mov ah, 02h
int 1Ah          ; CH=saat CL=dk DH=sn
jc  son          ; CF=1: saat okunamadı
mov bl, cl       ; dakikayı sakla
mov cl, 4        ; SHR kaydırma sayısı
mov bh, ch
call bcdyaz      ; "14"
mov bh, bl
call ikinokta    ; ":35"
mov bh, dh
call ikinokta    ; ":07"
son: ret
ikinokta: mov dl, ':'
mov ah, 02h
int 21h
bcdyaz:          ; BH = paketli BCD
mov dl, bh
shr dl, cl       ; üst hane
add dl, 30h      ; ASCII rakam
mov ah, 02h
int 21h
mov dl, bh
and dl, 0Fh      ; alt hane
add dl, 30h
int 21h
ret

INT 1Ah ve BIOS Verileri

BIOS Veri Alanı (Kesim 0040h)

AdresBoyutİçerik
0040:0010sözcükdonanım listesi (INT 11h'nin döndürdüğü değer)
0040:0013sözcüktaban bellek, KB (INT 12h)
0040:0017baytklavye bayrakları: bit 0 sağ Shift, 1 sol Shift, 2 Ctrl, 3 Alt, 4 Scroll Lock, 5 Num Lock, 6 Caps Lock, 7 Insert
0040:001Asözcüktampon başı: sıradaki okunacak tuşun bağıl konumu
0040:001Csözcüktampon sonu: sıradaki boş yerin bağıl konumu (baş = son → tampon boş)
0040:001E–003D32 baytklavye tamponu: 16 sözcük (ASCII + tarama kodu), dairesel; en çok 15 tuş
0040:0049baytgeçerli video modu (03h, 13h, …)
0040:004Asözcükekrandaki sütun sayısı (mod 03h'te 80)
0040:00508 sözcük8 sayfanın imleç konumu (düşük bayt sütun, yüksek bayt satır)
0040:006Cdwordtık sayacı: gece yarısından beri ≈ 18,2 Hz'lik kesme sayısı
0040:0070baytgece yarısı geçti bayrağı (INT 1Ah/00h AL'de verir ve sıfırlar)

Fiziksel adres = 00400h + bağıl konum: 0040:006C = 0046Ch = 0000:046C. INT 16h ve INT 1Ah bu alanı kullanır; program da doğrudan okuyabilir.

INT 1Ah ve BIOS Verileri

BIOS Veri Alanını Okumak

; yaklaşık 1 saniye bekle
mov ax, 0040h
mov es, ax
mov bx, es:[006Ch]  ; başlangıç tıkı
bekle:
mov ax, es:[006Ch]  ; şimdiki tık
sub ax, bx          ; geçen tık
cmp ax, 18          ; 18 tık ≈ 0,99 s
jb  bekle

; Caps Lock açık mı? Bekleyen tuş var mı?
test byte ptr es:[0017h], 40h
jnz caps_acik       ; bit 6 = 1
mov ax, es:[001Ah]  ; tampon başı
cmp ax, es:[001Ch]  ; tampon sonu
je  tampon_bos

1 193 182 Hz ÷ 65 536 = 18,2065 Hz

8253/8254 zamanlayıcısı bölen 65 536 iken IRQ 0'ı bu sıklıkta üretir; her kesmede 0040:006C bir artar.

1 tık = 65 536 ÷ 1 193 182 s ≈ 54,9 ms
18 tık ≈ 0,989 s · 5 s ≈ 91 tık

Bekleme süresi tık sayısıyla ölçülür; çözünürlük yaklaşık 55 ms'dir.

Günde 1800B0h = 1 573 040 tık

Sayaç bu değere ulaşınca sıfırlanır ve 0040:0070 bayrağı kurulur.

sub ax, bx ile fark

Yalnız düşük sözcük okunur. Fark alındığı için düşük sözcük FFFFh → 0000h dönse de sonuç doğrudur; yalnız gece yarısındaki sıfırlama hesabı bozar.

emu8086 BIOS veri alanının tamamını gerçek PC'deki gibi güncellemez; tık sayacı ve klavye tamponu örnekleri DOSBox'ta tam çalışır.

Program Sonlandırma

Programı Sonlandırmanın Üç Yolu

YöntemNasıl çalışır?Nerede?
retCOM programında yığının üstünde 0000h vardır; RET, PSP:0000h'a döner, orada int 20h (CD 20) bulunur.yalnız COM, yığın dengeli ise
int 20hDOS programı sonlandırır; CS'nin PSP kesimini göstermesi gerekir.COM
mov ax, 4C00h
int 21h
AL'deki çıkış kodu ile sonlandırır, açık dosyaları kapatır.COM ve EXE · önerilen
Çıkış koduAL = 0 başarı, ≠ 0 hata anlamına gelir. Toplu iş dosyasında IF ERRORLEVEL 1 ile sınanır.
Sık hataSonlandırma komutu unutulursa işlemci programdan sonraki baytları (verileri!) komut gibi yürütür ve sistem kilitlenebilir.

PSP (Program Segment Prefix): DOS'un her programın önüne koyduğu 256 baytlık alan; COM'larda kod bu yüzden ORG 100h'tan başlar.

Program Sonlandırma

emu8086 Şablonları: COM ve EXE

COM (tek kesim)

org 100h
  mov dx, offset msg
  mov ah, 09h
  int 21h
  ret             ; ya da int 20h
msg db 'Merhaba$'
  • CS = DS = ES = SS; ayar gerekmez.
  • En fazla 64 KB (kod + veri + yığın).
  • Dosya yalnız makine kodudur (başlık yok); yürütme 0100h'den başlar.

EXE (ayrı kesimler)

.model small
.stack 100h
.data
msg db 'Merhaba$'
.code
basla:
  mov ax, @data
  mov ds, ax      ; DS'yi ayarla!
  mov dx, offset msg
  mov ah, 09h
  int 21h
  mov ax, 4C00h
  int 21h
end basla
EXE dosyası yeniden yerleştirme (relocation) bilgili bir başlık taşır, giriş noktası end basla ile belirtilir ve 64 KB'tan büyük olabilir. DOS başlangıçta DS'yi PSP'ye ayarlar; mov ax, @data / mov ds, ax yapılmazsa DS:DX yanlış yeri gösterir ve ekrana çöp basılır.

Program Sonlandırma · Kodu adım adım çalıştır

EXE Programında DS Ayarı

.model small
.stack 100h
.data
msg db 'Merhaba$'
.code
basla:
mov ax, @data
mov ds, ax      ; DS'yi ayarla!
mov dx, offset msg
mov ah, 09h
int 21h
mov ax, 4C00h
int 21h
end basla
DS0700hAX0720hDX0000h0700h PSP (256 bayt)DS0710h yığın (.stack 100h)0720h veri: 'Merhaba$'0721h kodCSekran▌

Başlangıçta DS = ES = 0700h: DOS onları PSP'ye ayarlar. CS = 0721h (kod), SS = 0710h (yığın). @data veri kesiminin değeridir → AX = 0720h.

DS0720hAX0720hDX0000h0700h PSP (256 bayt)0710h yığın (.stack 100h)0720h veri: 'Merhaba$'DS0721h kodCSekran▌

MOV DS, AX: artık DS = 0720h, veri kesimini gösteriyor. Bu satır unutulsaydı DS:DX PSP'yi gösterir, ekrana çöp basılırdı.

DS0720hAX0720hDX0000h0700h PSP (256 bayt)0710h yığın (.stack 100h)0720h veri: 'Merhaba$'DS0721h kodCSekran▌

DX = offset msg = 0000h: msg, veri kesiminin başında.

DS0720hAX0920hDX0000h0700h PSP (256 bayt)0710h yığın (.stack 100h)0720h veri: 'Merhaba$'DS0721h kodCSekran▌

AH = 09h.

DS0720hAX0924hDX0000h0700h PSP (256 bayt)0710h yığın (.stack 100h)0720h veri: 'Merhaba$'DS0721h kodCSekranMerhaba▌

INT 21h: DS:DX = 0720h:0000h'den '$'a kadar → Merhaba.

DS0720hAX4C00hDX0000h0700h PSP (256 bayt)0710h yığın (.stack 100h)0720h veri: 'Merhaba$'DS0721h kodCSekranMerhaba▌

AX = 4C00h, INT 21h: çıkış kodu 0 ile DOS'a dön. EXE'de RET kullanılamaz (yığının üstünde PSP adresi yok).

Kesim değerleri yorumlayıcının yerleşimidir (PSP 0700h); gerçek DOS'ta sayılar farklı olabilir, sıra ve DS ayarının gereği aynıdır.

Uygulama

Toplama, Çıkarma ve Sonucu Yazdırma

org 100h
mov al, 5       ; bin=00000101b
mov bl, 10      ; hex=0ah or bin=00001010b
; 5 + 10 = 15 (decimal), 0fh, 00001111b
add bl, al
; 15 - 1 = 14 (decimal), 0eh, 00001110b
sub bl, 1
mov cx, 8       ; sonucu ikilik tabanda yazdır
print:
mov ah, 2   ; yazdırma fonksiyonu
mov dl, '0'
test bl, 10000000b  ; ilk biti test et
jz zero
mov dl, '1'
zero:
int 21h
shl bl, 1
loop print
; b (binary suffix) yazdır
mov dl, 'b'
int 21h
; klavye tuşu basılmasını bekle
mov ah, 0
int 16h
ret
  • 5 + 10 − 1 = 14 = 0Eh hesaplanır; sonuç BL'dedir.
  • Döngü 8 kez (CX = 8) çalışır: her turda BL'nin en anlamlı biti (MSB) test edilir, '0' ya da '1' yazılır, BL bir sola kaydırılır.
  • En sonda 'b' eki yazılır ve bir tuşa basılması beklenir. Beklenen çıktı: 00001110b.

Uygulama

TEST ve SHL ile Bit Okuma

BL0706050413121100maske10000000AND → 00000000ZF = 1 (bit 7 = 0)

TEST BL, 10000000b: BL ile maske VE'lenir ama BL değişmez. Sonuç 0 ise bit 7 = 0 → ZF = 1, JZ atlar.

önce0706050413121100sonra00011100CF0bit 7 → CFsağdan 0 girer

SHL BL, 1: tüm bitler bir sola kayar; çıkan bit 7 CF'ye gider, bit 0'a 0 girer. Bir sonraki bit, test edilecek konuma (bit 7) gelir.

tur:12345678bit:00001110

8 tur sonunda BL'nin bitleri MSB'den LSB'ye sırayla yazılmış olur: 00001110, ardından b.

Alternatif: SHL BL,1 ardından JC ile CF'ye bakmak. Ancak bu sıralamada kaydırma, yazdırmadan önce yapılmalıdır.

Uygulama · Kodu adım adım çalıştır

Kod İzleme (1/2): Hesaplama

AL = 5 = 05h = 00000101b. MOV bayrakları etkilemez.

BL = 10 = 0Ah = 00001010b.

ADD BL, AL: BL = 0Ah + 05h = 0Fh (15). Taşma yok (CF = 0), sonuçta dört 1 biti var → PF = 1.

SUB BL, 1: BL = 0Eh (14) = 00001110b. Üç 1 biti → PF = 0. Ödünç yok: CF = 0.

CX = 8: LOOP sayacı, her bit için bir tur.

org 100h
mov al, 5       ; bin=00000101b
mov bl, 10      ; hex=0ah or bin=00001010b
; 5 + 10 = 15 (decimal), 0fh, 00001111b
add bl, al
; 15 - 1 = 14 (decimal), 0eh, 00001110b
sub bl, 1
mov cx, 8       ; sonucu ikilik tabanda yazdır

Uygulama · Kodu adım adım çalıştır

Kod İzleme (2/2): İkili Yazdırma

BL0706050413121100CF0DL—

Tur 1: AH = 2 (DOS karakter yaz).

BL0706050413121100CF0DL'0'

Varsayılan karakter DL = '0' (30h).

BL0706050413121100maske 10000000b → bit 7CF0DL'0'

TEST: bit 7 = 0 → ZF = 1, CF = 0.

BL0706050413121100maske 10000000b → bit 7CF0DL'0'

ZF = 1 → JZ zero atlar; DL '0' kalır.

BL0706050413121100CF0DL'0'

INT 21h: DL'deki '0' yazılır.

BL0706051413120100CF0DL'0'

SHL BL,1: BL = 1Ch, çıkan bit CF = 0.

BL0706051413120100CF0DL'0'

LOOP: CX = 7 ≠ 0 → print'e dön.

BL0706151413020100CF0DL'0'

Tur 2 (özet): bit = 0, '0' yazıldı, BL = 38h. LOOP: CX = 6 ≠ 0 → print'e dön.

BL0716151403020100CF0DL'0'

Tur 3 (özet): bit = 0, '0' yazıldı, BL = 70h. LOOP: CX = 5 ≠ 0 → print'e dön.

BL1716150403020100CF0DL'0'

Tur 4 (özet): bit = 0, '0' yazıldı, BL = E0h. LOOP: CX = 4 ≠ 0 → print'e dön.

BL1716150403020100CF0DL'0'

Tur 5: AH = 2 (DOS karakter yaz).

BL1716150403020100CF0DL'0'

Varsayılan karakter DL = '0' (30h).

BL1716150403020100maske 10000000b → bit 7CF0DL'0'

TEST: bit 7 = 1 → ZF = 0, CF = 0.

BL1716150403020100maske 10000000b → bit 7CF0DL'0'

ZF = 0 → JZ atlamaz, sıradaki komut çalışır.

BL1716150403020100maske 10000000b → bit 7CF0DL'1'

DL = '1' (31h).

BL1716150403020100CF0DL'1'

INT 21h: DL'deki '1' yazılır.

BL1716050403020100CF1DL'1'

SHL BL,1: BL = C0h, çıkan bit CF = 1.

BL1716050403020100CF1DL'1'

LOOP: CX = 3 ≠ 0 → print'e dön.

BL1706050403020100CF1DL'1'

Tur 6 (özet): bit = 1, '1' yazıldı, BL = 80h. LOOP: CX = 2 ≠ 0 → print'e dön.

BL0706050403020100CF1DL'1'

Tur 7 (özet): bit = 1, '1' yazıldı, BL = 00h. LOOP: CX = 1 ≠ 0 → print'e dön.

BL0706050403020100CF0DL'0'

Tur 8 (özet): bit = 0, '0' yazıldı, BL = 00h. LOOP: CX = 0 → döngü biter.

BL0706050403020100CF0DL'b'

DL = 'b'. AH hâlâ 2.

BL0706050403020100CF0DL'b'

INT 21h: 'b' eki yazılır.

BL0706050403020100CF0DL'b'

AH = 0: tuş bekleme.

BL0706050403020100CF0DL'b'

INT 16h: kullanıcı bir tuşa basana kadar beklenir (çıktı okunabilsin).

BL0706050403020100CF0DL'b'

RET: program biter. Ekranda 00001110b.

print:
mov ah, 2   ; yazdırma fonksiyonu
mov dl, '0'
test bl, 10000000b  ; ilk biti test et
jz zero
mov dl, '1'
zero:
int 21h
shl bl, 1
loop print
; b (binary suffix) yazdır
mov dl, 'b'
int 21h
; klavye tuşu basılmasını bekle
mov ah, 0
int 16h
ret

Uygulama

Ekran Çıktısı ve Notlar

00001110b_

emu8086 ekran penceresi (80×25)

  • Sayının içi zaten ikilidir; yazdırmak, her biti '0'/'1' karakterine çevirmektir.
  • TEST sonucu saklamadığı için BL bozulmaz; bozan yalnızca SHL'dir (bilerek).
  • LOOP CX'i azaltır; döngü içinde CX başka amaçla kullanılmamalıdır.
  • INT 21h/02h AL'yi değiştirir (AL = DL); AL'de saklanan bir değer varsa önce korunmalıdır.

Uygulama · Kodu adım adım çalıştır

Kod İzleme: Mini Menü Programı

DX = menü metninin adresi.

AH = 09h.

Menü yazılır.

AH = 01h: yansıtmalı tek karakter oku.

Kullanıcı 1 bastı: AL = 31h (ekranda görünür).

31h ≠ 'q' → ZF = 0.

Çıkış değil.

AL = '1' → ZF = 1.

Eşit → atlama yok (başka tuşta menü yeniden gösterilirdi).

DX = selam.

AH = 09h.

Yeni satıra Selam! yazılır.

Menüye dön.

DX = menü metninin adresi.

AH = 09h.

Menü yeniden yazılır.

AH = 01h: yansıtmalı tek karakter oku.

Kullanıcı q bastı: AL = 71h.

AL = 'q' → ZF = 1.

→ cikis.

AH = 4Ch (sonlandır), AL = 00h (çıkış kodu).

Program DOS'a döner; çıkış kodu toplu iş dosyalarında ERRORLEVEL ile okunur.

org 100h
goster:
mov dx, offset menu
mov ah, 09h
int 21h
mov ah, 01h       ; seçimi oku
int 21h
cmp al, 'q'
je cikis
cmp al, '1'
jne goster
mov dx, offset selam
mov ah, 09h
int 21h
jmp goster
cikis:
mov ax, 4C00h     ; çıkış kodu 0
int 21h
menu  db 0Dh, 0Ah, '1:Selam q:Cikis $'
selam db 0Dh, 0Ah, 'Selam!$'

Uygulama

Sık Yapılan Hatalar

'$' unutulduINT 21h/09h belleği '$' bulana kadar yazar: ekrana çöp dolar.
DS ayarlanmadı (EXE)DX doğru ama kesim yanlış: mov ax, @data / mov ds, ax.
AL'nin bozulması02h ve 09h AL'yi değiştirir; okunan karakter yazılmadan önce başka yazmaçta saklanır.
09h sonrası imleçINT 10h/09h imleci ilerletmez; sonraki yazı üstüne gelir.
13h'te DS:DXBIOS dizgi hizmeti adresi ES:BP'de bekler.
0Ah tamponuİlk bayt (kapasite) ayarlanmalı; metin tampon+2'den başlar, '$' ile bitmez.
Yalnız LFYeni satır için CR + LF (0Dh, 0Ah) gerekir.
Sonlandırma yokRET/4Ch unutulursa veriler komut olarak yürütülür.

Özet

Özet: Hızlı Başvuru

İşÇağrıParametreler
Ekranı temizleINT 10h / 00hAL = 03h
İmleci konumlaINT 10h / 02hBH = 0, DH = satır, DL = sütun
Renkli karakterINT 10h / 09hAL, BH, BL = öznitelik, CX = sayı
Karakter (daktilo)INT 10h / 0EhAL
Renkli dizgiINT 10h / 13hAL = mod, BL, CX, DH:DL, ES:BP
Tuş bekle / yoklaINT 16h / 00h, 01h→ AH = tarama, AL = ASCII; 01h: ZF
Karakter oku / yazINT 21h / 01h, 02h→ AL / DL
Dizgi yaz / satır okuINT 21h / 09h, 0AhDS:DX ('$' / tampon)
Tarih / saatINT 21h / 2Ah, 2Ch→ CX DH DL AL / CH CL DH DL
RTC saati (BCD)INT 1Ah / 02h→ CH CL DH, CF = 1 hata
Piksel (mod 13h)INT 10h / 0ChAL = renk, CX = x, DX = y; ya da A000:(y·320 + x)
Programı bitirINT 21h / 4Ch, INT 20h, RETAL = çıkış kodu

Özet

Alıştırmalar

  1. Ekranın tam ortasına (12, 38) mavi zemin üzerine beyaz "8086" yazan programı INT 10h/13h ile yazın.
  2. Kullanıcıdan iki rakam okuyup (01h) toplamlarını tek basamaklı olarak yazdırın (toplam ≤ 9).
  3. Esc'ye basılana kadar basılan tuşların tarama kodunu onaltılık yazdıran bir program yazın.
  4. 0Ah ile okunan metni tersten yazdırın.
  5. Tarihi GG.AA.YYYY biçiminde yazdırın. Yıl için hangi yöntemi kullanırsınız?
İpuçları / cevaplar
  1. AX = 1301h, BX = 001Fh, CX = 4, DX = 0C26h, ES:BP → '8086'.
  2. AL'den 30h çıkar, BL'de topla, sonra 30h ekleyip DL ile 02h; arada CR LF yazılır.
  3. INT 16h/00h; AH, XLAT tablosu ile iki onaltılık basamağa çevrilir; cmp al, 1Bh.
  4. SI = tampon+2+sayı−1'den geriye doğru: std + lodsb + 02h, CX = sayı.
  5. Gün/ay için AAM; yıl (CX) için 10'a tekrarlı DIV ve yığın.

Özet

Alıştırmalar (devam)

  1. mov ah, 09h / int 21h ile '$' karakterini nasıl yazdırırsınız?
  2. Mod 13h'te (160, 100) pikselinin A000h kesimindeki bağıl konumu nedir?
  3. INT 1Ah/02h DH = 59h döndürdü. Ekrana ne yazılır? Aynı saniye INT 21h/2Ch ile hangi değerle gelir?
  4. 0040:006C tık sayacıyla yaklaşık 5 saniye beklemek için kaç tık beklenmelidir?
İpuçları / cevaplar
  1. Yazdırılamaz; '$' için 02h hizmeti (DL = 24h) kullanılır.
  2. 100 · 320 + 160 = 32 160 = 7DA0h.
  3. '5' ve '9' → 59; 2Ch ise ikili DH = 3Bh verir.
  4. 5 × 18,2065 ≈ 91 tık.

Özet

Kaynaklar

  • Ralf Brown, Ralf Brown's Interrupt List (INT 10h, 16h, 21h ayrıntılı başvuru).
  • IBM, Personal Computer AT Technical Reference, BIOS bölümü, 1984.
  • Peter Abel, IBM PC Assembly Language and Programming, 5. baskı, Prentice Hall, 2001.
  • Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009.
  • emu8086 yardım belgeleri: supported interrupt functions.
  • Ş. Ç. Öztürk, O. Ergin, Intel 8086 ile Mikroişlemci Programlamaya Giriş, 2009.

Son

Bölüm 5: Kesme Fonksiyonları
Sonraki bölüm: Bölüm 6: Aritmetik ve Mantıksal İşlemler · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.