Bölüm 10: Aygıt Kontrolü

Mikroişlemciler
IN / OUTYoklamaTrafik ışıklarıINT 15h beklemeYazılımla gecikme8255 PPIStep motorLED ekran7 bölütlü göstergeTermometreYazıcıRobotTest aygıtı
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Port tabanlı G/Ç

IN ve OUT komutlarının biçimlerini ve sınırlarını bilmek.

Bit düzeyinde denetim

Bir porttaki her bitin bir lambaya, mıknatısa ya da duruma karşılık geldiğini çözümlemek.

Yoklama (polling)

Aygıtın hazır bitini bekleyen döngüler yazmak.

Zamanlama

INT 15h / AH = 86h ile mikrosaniye cinsinden bekleme süresi hesaplamak.

emu8086 aygıtları

Trafik ışıkları, step motor, LED ekran, termometre, yazıcı, robot ve test aygıtını programlamak.

Gömülü sistem bakışı

Programın ROM'dan RAM'e yüklenip çalıştırılma ilkesini açıklamak.

Giriş

emu8086'ya Bağlı 7 Sanal Aygıt

AygıtPort(lar)YönVeri
Trafik lambaları (traffic lights)4OUTsözcük: 12 lamba biti
Step motor (stepper motor)7OUT / INbit 0–2 mıknatıslar, bit 7 hazır
Robot9, 10, 11OUT / INkomut, veri, durum
Test aygıtı (simple io test)110, 112IN / OUTbayt (110), sözcük (112)
Termometre ve ısıtıcı125, 127IN / OUTsıcaklık, ısıtıcı aç/kapa
Yazıcı (printer)130OUTkarakter (INT 21h/05h ile)
LED ekran (LED display)199OUTsözcük: işaretli sayı

Aygıtlar emu8086'da virtual devices menüsünden açılır; programın başına #start=Traffic_Lights.exe# gibi bir direktif yazılırsa öykünücü aygıtı kendisi başlatır.

G/Ç Temelleri

Aygıt Kontrolü

  • x86 ailesi CPU'lar geniş bir aygıt yelpazesini denetleyebilir. Temel G/Ç port numaraları sistemden sisteme farklılık gösterebilir ve uygun bir donanımla (adres çözücü, “tricky” elektronik devre) değiştirilebilir.
  • Gömülü bir sistemde derlenen .bin dosyası Salt Okunur Bellek (ROM) yongasına yazılır.
  • Sistem açılınca programı ROM'dan okur, RAM'e yükler ve yürütür. Bu ilke birçok modern cihazda (çamaşır makinesi, yazıcı, modem…) kullanılır.
ROMprogram.binRAMçalışan kopyaCPUyürütürG/Ç portları① oku② yükle③ IN / OUT

G/Ç Temelleri

IN ve OUT Komutları

BiçimAnlamıPort aralığı
IN AL, portporttan 1 bayt oku0–255 (sabit)
IN AX, portporttan 1 sözcük oku0–255 (sabit)
IN AL, DX / IN AX, DXport numarası DX'te0–65 535
OUT port, AL / OUT port, AXporta yaz0–255 (sabit)
OUT DX, AL / OUT DX, AXport numarası DX'te0–65 535
CPUAL / AXG/Ç portun ya da [DX]OUT port, AL/AXIN AL/AX, port
Veri yalnızca AL ya da AX üzerinden geçer: OUT 4, BX veya IN CL, 7 geçersizdir.
255'ten büyük port için önce MOV DX, 300 yazılır, sonra OUT DX, AL. Bu derste tüm emu8086 portları 255'in altındadır.

G/Ç Temelleri

Port Eşlemeli ve Bellek Eşlemeli G/Ç

Port eşlemeli (isolated) G/Ç
  • 8086'nın ayrı bir 64 K'lık G/Ç adres uzayı vardır.
  • Erişim yalnızca IN/OUT ile; M/IO̅ pini G/Ç döngüsünü belirtir.
  • Bellek adreslerini tüketmez.
  • emu8086'nın sanal aygıtlarının hepsi böyledir.
Bellek eşlemeli (memory-mapped) G/Ç
  • Aygıt yazmaçları bellek adreslerinde durur.
  • Her MOV/ADD/CMP komutu kullanılabilir.
  • Örnek: PC metin ekranı B800:0000'dan başlar; oraya yazılan bayt ekranda görünür.
bellek 00000h – FFFFFh (1 MB)G/Ç 0000h – FFFFhIN / OUT, M/IO̅ = 0B800hbellekaygıt bellekte: MOV, ADD, CMP … kullanılabilirport eşlemelibellek eşlemeli
Yoklama (polling): CPU aygıtın durum bitini döngü içinde okuyarak “hazır” olmasını bekler. Basittir ama beklerken CPU başka iş yapamaz. Alternatifi aygıtın CPU'ya kesme göndermesidir.

G/Ç Temelleri

8255 Programlanabilir Çevre Arayüzü (PPI)

  • Üç 8 bitlik port (A, B, iki 4 bitlik yarıya ayrılabilen C) ve bir kontrol yazmacı; yazmaç A1, A0 ile seçilir, C̅S̅ adres çözücüden gelir.
  • RESET sonrası tüm portlar giriştir; önce kontrol sözcüğü yazılır.
A1 A0YazmaçAdres (taban 310h)
0 0port A310h
0 1port B311h
1 0port C312h
1 1kontrol yazmacı313h
8255D0–D7A0A1R̅D̅ (IOR̅)W̅R̅ (IOW̅)RESETadres çözücüC̅S̅PA0–PA7PB0–PB7PC4–PC7PC0–PC3port Aport Bport C üstport C alt
8086'da çift adresler D0–D7'den (alt bank) aktarılır; yazmaçlar çift adrese düşsün diye 8255.A0 ← A1, A1 ← A2 bağlanır (310h, 312h, 314h, 316h). 8088'de A0 ← A0, A1 ← A1 yeterlidir. Port > 255: erişim DX ile.

G/Ç Temelleri

8255 Kontrol Sözcüğü (Mod 0)

D7D6 D5D4D3D2D1D0
1 = mod seçimiA grubu modu
00 = mod 0
port APC7–PC4B grubu modu
0 = mod 0
port BPC3–PC0
yön bitleri:1 = giriş, 0 = çıkış (D4, D3, D1, D0)

1 00 0 0 0 1 0b = 82h

İstenen: A çıkış (LED/röle), B giriş (anahtar), C'nin iki yarısı çıkış, hepsi mod 0.

D7 = 1: mod seçimi · D6 D5 = 00 ve D2 = 0: mod 0

Mod 0 el sıkışmasız basit G/Ç'dir; mod 1 ve 2 el sıkışmalı (strobe) aktarım içindir.

D4 = 0 (A çıkış) · D3 = 0 (C üst çıkış)
D1 = 1 (B giriş) · D0 = 0 (C alt çıkış)

Sonuç 1000 0010b = 82h. Örneğin A giriş, B çıkış, C giriş için 1001 1001b = 99h olur.

D7 = 0 ise bit kur/sil (BSR):
D3–D1 = C'nin bit numarası, D0 = yeni değer

0Fh (0000 1111b) → PC7 = 1, 0Eh → PC7 = 0. Diğer C bitleri değişmez.

mov dx, 313h   ; kontrol yazmacı
mov al, 82h    ; A çık, B gir, C çık
out dx, al
mov dx, 311h   ; port B
in  al, dx     ; anahtarları oku
mov dx, 310h   ; port A
out dx, al     ; LED'lere yaz
mov dx, 313h
mov al, 0Fh    ; BSR: PC7 = 1
out dx, al

G/Ç Temelleri · Kodu adım adım çalıştır

8255: Kontrol Sözcüğü, Okuma, Yazma, BSR

org 100h
mov dx, 313h   ; kontrol yazmacı
mov al, 82h    ; A,C çık; B gir
out dx, al
mov dx, 311h   ; port B
in  al, dx     ; anahtarları oku
mov dx, 310h   ; port A
out dx, al     ; LED'lere yaz
mov dx, 313h
mov al, 0Fh    ; BSR: PC7 = 1
out dx, al
ret
DX0313hAL82h8255kontrol = yok (hepsi giriş)A 310hgiriş— (yazılmadı)B 311hgiriş ← anahtar10010110C 312hgiriş— (yazılmadı)G/Ç kaydı:

RESET sonrası üç port da giriş. Port B'ye bağlı anahtarlar 1001 0110b = 96h konumunda (port sözlüğünde 311h = 96h). DX = 313h, AL = 82h.

DX0313hAL82h8255kontrol = 82hA 310hçıkış → LED— (yazılmadı)B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)OUT → kontrolG/Ç kaydı:OUT 313h ← 82h

OUT 313h ← 82h = 1 00 0 0 0 1 0b: mod 0; A çıkış, C üst çıkış, B giriş, C alt çıkış.

DX0311hAL82h8255kontrol = 82hA 310hçıkış → LED— (yazılmadı)B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)G/Ç kaydı:OUT 313h ← 82h

DX = 311h: port B. 311h > 255 olduğundan port numarası DX'te verilir.

DX0311hAL96h8255kontrol = 82hA 310hçıkış → LED— (yazılmadı)B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)IN ← port BG/Ç kaydı:OUT 313h ← 82hIN 311h → 96h

IN AL, DX: anahtarlar okunur → AL = 96h.

DX0310hAL96h8255kontrol = 82hA 310hçıkış → LED— (yazılmadı)B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)G/Ç kaydı:OUT 313h ← 82hIN 311h → 96h

DX = 310h: port A.

DX0310hAL96h8255kontrol = 82hA 310hçıkış → LED10010110B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)OUT → port AG/Ç kaydı:OUT 313h ← 82hIN 311h → 96hOUT 310h ← 96h

OUT 310h ← 96h: port A çıkış olduğundan LED'ler anahtarları kopyalar (yanan: bit 7, 4, 2, 1).

DX0313hAL0Fh8255kontrol = 82hA 310hçıkış → LED10010110B 311hgiriş ← anahtar10010110C 312hçıkış— (yazılmadı)G/Ç kaydı:OUT 313h ← 82hIN 311h → 96hOUT 310h ← 96h

DX = 313h, AL = 0Fh = 0000 111 1b: D7 = 0 → mod sözcüğü değil, bit kur/sil (BSR).

DX0313hAL0Fh8255kontrol = 82hA 310hçıkış → LED10010110B 311hgiriş ← anahtar10010110C 312hçıkış10000000OUT → kontrol (BSR)G/Ç kaydı:IN 311h → 96hOUT 310h ← 96hOUT 313h ← 0Fh

OUT 313h ← 0Fh: D3–D1 = 111 → PC7, D0 = 1 → PC7 = 1. Port yönleri (82h) değişmez, diğer C bitleri korunur.

Port değerleri yorumlayıcının G/Ç kaydından (anahtar girişi 96h örnek). BSR sözcüğü yalnız seçilen C bitini değiştirir.

G/Ç Temelleri

Etkileşimli 8255 Kontrol Sözcüğü

Port yönüne tıklanınca yön değişir; kutuya doğrudan bir değer de yazılabilir (ör. 9B, 80, 0F).

Trafik Işıkları

Trafik Lambaları (Port 4)

  • Kavşakta 4 direk, her direkte 3 lamba: toplam 12 lamba = port 4'e yazılan sözcüğün bit 0–11'i.
  • Bit = 1 → lamba yanar, 0 → söner. Bit 12–15 kullanılmaz.
  • Her direkte (k = 0…3): bit 3k kırmızı, 3k+1 sarı, 3k+2 yeşil.
  • Örnek: 0000_0011_0000_1100b → bit 2 ve 8 (yeşil), bit 3 ve 9 (kırmızı).
DirekBitler
sağ alt0 1 2
sağ üst3 4 5
sol üst6 7 8
sol alt9 A B
0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

Trafik Işıkları

Durum (Situation) Tablosu

;                 FEDC_BA98_7654_3210
situation     dw  0000_0011_0000_1100b
s1            dw  0000_0110_1001_1010b
s2            dw  0000_1000_0110_0001b
s3            dw  0000_1000_0110_0001b
s4            dw  0000_0100_1101_0011b
sit_end = $
all_red       equ 0000_0010_0100_1001b
AdHexLambalar
situation030Chsağ alt: yeşil; sağ üst: kırmızı; sol üst: yeşil; sol alt: kırmızı
s1069Ahsağ alt: sarı; sağ üst: kırmızı + sarı; sol üst: sarı; sol alt: kırmızı + sarı
s20861hsağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil
s30861hsağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil
s404D3hsağ alt: kırmızı + sarı; sağ üst: sarı; sol üst: kırmızı + sarı; sol alt: sarı
all_red0249hsağ alt: kırmızı; sağ üst: kırmızı; sol üst: kırmızı; sol alt: kırmızı

s2 ve s3 aynıdır: yan yol yeşili iki aralık (10 s) sürer. s1 ve s4 sarı geçişleridir (kırmızı + sarı = “hazırlan”).

Trafik Işıkları

Durumlar Adım Adım

0123456789ABFEDC BA98 7654 32100000 0010 0100 1001

all_red = 0249h → sağ alt: kırmızı; sağ üst: kırmızı; sol üst: kırmızı; sol alt: kırmızı

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

situation = 030Ch → sağ alt: yeşil; sağ üst: kırmızı; sol üst: yeşil; sol alt: kırmızı

0123456789ABFEDC BA98 7654 32100000 0110 1001 1010

s1 = 069Ah → sağ alt: sarı; sağ üst: kırmızı + sarı; sol üst: sarı; sol alt: kırmızı + sarı

0123456789ABFEDC BA98 7654 32100000 1000 0110 0001

s2 = 0861h → sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil

0123456789ABFEDC BA98 7654 32100000 1000 0110 0001

s3 = 0861h → sağ alt: kırmızı; sağ üst: yeşil; sol üst: kırmızı; sol alt: yeşil

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

s4 = 04D3h → sağ alt: kırmızı + sarı; sağ üst: sarı; sol üst: kırmızı + sarı; sol alt: sarı

Program önce tüm yönleri kırmızı yapar, sonra situation → s1 → s2 → s3 → s4 → situation… diye 5 saniyelik aralıklarla döner.

Trafik Işıkları

INT 15h / AH = 86h ile Bekleme

; 5 saniye bekle (5 milyon µs)
mov cx, 4Ch    ; 004C4B40h = 5 000 000
mov dx, 4B40h
mov ah, 86h
int 15h
  • BIOS işlevi INT 15h, AH = 86h: CX:DX mikrosaniye bekler.
  • CX yüksek sözcük, DX düşük sözcük: 32 bitlik bekleme süresi.
5 000 000 µs = 004C4B40h (32 bit)004C4B40CX = 004ChDX = 4B40hyüksek sözcükdüşük sözcük

5 s = 5 × 1 000 000 = 5 000 000 µs

Süre mikrosaniyeye çevrilir.

5 000 000 ÷ 16 = 312 500 kalan 0
312 500 ÷ 16 = 19 531 kalan 4
19 531 ÷ 16 = 1 220 kalan 11 (B)
1 220 ÷ 16 = 76 kalan 4
76 ÷ 16 = 4 kalan 12 (C)
4 ÷ 16 = 0 kalan 4

Ardışık 16'ya bölme: kalanlar sondan başa okunur → 4C4B40h.

0 0 4 C | 4 B 4 0
CX = 004Ch · DX = 4B40h

32 bitlik değer 0000 0000 0100 1100 0100 1011 0100 0000b ikiye bölünür.

1 s → 1 000 000 = 000F4240h → CX = 000Fh, DX = 4240h

Başka bir örnek: 1 saniyelik bekleme.

Trafik Işıkları

Yazılımla Gecikme: LOOP ve Saat Turu

; ≈ 1 ms gecikme (4,77 MHz 8086)
mov cx, 281    ; 4 çevrim
bekle:
loop bekle     ; 280 × 17 + 1 × 5 çevrim
KomutSaat turu
MOV CX, sabit4
LOOP (CX ≠ 0, atlar)17
LOOP (CX = 0, atlamaz)5

Toplam = 4 + 17(N − 1) + 5 = 17N − 8 saat turu.

4,77 MHz: 1 saat turu ≈ 0,2096 µs
1 ms = 4 770 saat turu

Süre, saat turu sayısının saat frekansına bölümüdür.

17N − 8 = 4 770 → N ≈ 281,06
N = 281 → 4 769 saat turu ≈ 0,9998 ms

CX'e tam sayı yazılabildiği için en yakın değer seçilir.

5 MHz: 1 ms = 5 000 saat turu → N ≈ 294,6
N = 295 → 5 007 saat turu ≈ 1,0014 ms

Aynı N = 281 5 MHz'de yalnızca 0,954 ms sürer: gecikme saat hızına bağlıdır.

En uzun: CX = 0 → 65 536 tur
17 · 65 536 − 8 = 1 114 104 saat turu ≈ 233,6 ms

Daha uzun bekleme için iç içe döngü gerekir. Prosedür olarak çağrılırsa CALL (19) ve RET (8) saat turu da eklenir.

Hesap yaklaşıktır: kesmeler, bellek bekleme durumları ve komut kuyruğu süreyi uzatabilir. emu8086 komut zamanlamasını modellemez; döngü bilgisayarın ve adım gecikmesi ayarının hızında koşar. emu8086'da süreli bekleme INT 15h/86h ile yapılır.

Trafik Işıkları · Kodu adım adım çalıştır

Gecikme Döngüsünde Saat Turlarını Saymak

org 100h
mov cx, 4      ; 4 saat turu
bekle:
loop bekle     ; 17 tur, sonuncu 5
ret
CX0004htoplam: 4 tur≈ 0.84 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

CX = 4. mov cx, sabit 4 saat turu sürer; 4,77 MHz'de 1 tur ≈ 0,2096 µs.

CX0003htoplam: 21 tur≈ 4.40 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

1. LOOP: CX = 3 ≠ 0 → atlar (aynı komuta döner): 17 tur. Toplam 21.

CX0002htoplam: 38 tur≈ 7.97 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

2. LOOP: CX = 2, yine 17 tur. Toplam 38.

CX0001htoplam: 55 tur≈ 11.53 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

3. LOOP: CX = 1, 17 tur. Toplam 55.

CX0000htoplam: 60 tur≈ 12.58 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

4. LOOP: CX = 0 → atlamaz: yalnız 5 tur. Toplam 60 = 17 · 4 − 8 tur.

CX0000htoplam: 60 tur≈ 12.58 µs41717175MOVLOOP (atlar) ×3LOOP (çıkar)060 tur

60 tur ÷ 4,77 MHz ≈ 12,6 µs. CX'i N yapınca süre 17N − 8 turdur; 1 ms için N = 281 bulunmuştu.

Tur sayıları 8086 komut sürelerinden; yorumlayıcı yalnız CX ve atlama davranışını doğrular (emu8086 zamanlamayı modellemez).

Trafik Işıkları · Kodu adım adım çalıştır

Trafik Işıkları Programı

0123456789ABFEDC BA98 7654 32100000 0000 0000 0000

Tablo 0124h'de varsayıldı (ORG 100h; adres derleyiciye göre değişebilir). sit_end = 012Eh.

0123456789ABFEDC BA98 7654 32100000 0000 0000 0000

AX = all_red = 0249h (sabit, EQU).

0123456789ABFEDC BA98 7654 32100000 0010 0100 1001

Port 4'e yaz: tüm yönler kırmızı.

0123456789ABFEDC BA98 7654 32100000 0010 0100 1001

SI = 0124h: tablonun başı (situation).

0123456789ABFEDC BA98 7654 32100000 0010 0100 1001

AX ← [SI] = 030Ch.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

OUT 4, AX: lambalar yeni duruma geçer (SI = 0124h).

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

CX = 004Ch (bekleme süresinin yüksek sözcüğü).

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

DX = 4B40h (düşük sözcük).

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

AH = 86h: BIOS bekleme işlevi.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

INT 15h: 5 saniye bekle.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

SI = 0126h: sonraki sözcük.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

CMP SI, sit_end (012Eh): SI < sit_end → CF = 1.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

JB: CF = 1, next'e dön.

0123456789ABFEDC BA98 7654 32100000 0110 1001 1010

… bekleme ve SI artırma … OUT 4, AX: SI = 0126h → port 4 = 069Ah.

0123456789ABFEDC BA98 7654 32100000 1000 0110 0001

… bekleme ve SI artırma … OUT 4, AX: SI = 0128h → port 4 = 0861h.

0123456789ABFEDC BA98 7654 32100000 1000 0110 0001

… bekleme ve SI artırma … OUT 4, AX: SI = 012Ah → port 4 = 0861h.

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

… bekleme ve SI artırma … OUT 4, AX: SI = 012Ch → port 4 = 04D3h.

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

CMP SI, sit_end (012Eh): SI = sit_end → CF = 0.

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

JB: CF = 0, atlama yok: tablo bitti.

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

SI = 0124h: tabloya baştan başla.

0123456789ABFEDC BA98 7654 32100000 0100 1101 0011

JMP next: sonsuz döngü.

0123456789ABFEDC BA98 7654 32100000 0011 0000 1100

… bekleme ve SI artırma … OUT 4, AX: SI = 0124h → port 4 = 030Ch.

#start=Traffic_Lights.exe#
mov ax, all_red
out 4, ax
mov si, offset situation
next:
mov ax, [si]
out 4, ax
mov cx, 4Ch      ; 5 s bekle
mov dx, 4B40h
mov ah, 86h
int 15h
add si, 2        ; sonraki durum
cmp si, sit_end
jb  next
mov si, offset situation
jmp next

Döngü hiç bitmez: gömülü sistemlerde ana program genellikle sonsuz bir döngüdür.

Trafik Işıkları

Etkileşimli Trafik Bit Düzenleyici

Bir bite tıklanınca o lamba yanar ya da söner (F…0). Bit 12–15 kullanılmaz.

Step Motor

Step Motor (Port 7)

  • Motor hem saat yönünde (CW) hem de tersine (CCW) döndürülebilir.
  • Port 7'ye yazılan baytın bit 0, 1, 2'si üç elektromıknatısı açar/kapatır.
  • Yarı adım 11,25°, tam adım 22,5°'dir.
  • Yarı adım: çift mıknatıs, ardından tek mıknatıs açılarak döndürülür.
  • Tam adım: çift mıknatıs, çift mıknatıs, tek mıknatıs şeklinde devam eder.
  • Motor yeni komut almaya hazır olduğunda porttan okunan baytın bit 7'sini 1 yapar.
2107654321000000110port 7 = 00000110b

Step Motor

Step Motor Veri Tabloları

TabloAnlam1234
datcwCW yarı adım110100011010
datccwCCW yarı adım011001110010
datcw_fsCW tam adım001011110000
datccw_fsCCW tam adım100110011000
110100011010011001110010001011110000100110011000datcw · 0102hdatccw · 0106hdatcw_fs · 010Ahdatccw_fs · 010Ehadd bx, 4 → sonraki tablo
  • Tablolar bellekte arka arkaya durur: her biri 4 bayt. Bu yüzden add bx, 4 bir sonraki tabloya geçirir.
  • Program 32 (20h) tur sonra tabloyu değiştirir: CW yarı → CCW yarı → CW tam → CCW tam → başa.
  • Bayt değerindeki bitler mıknatısları gösterir: 110b = mıknatıs 2 ve 1 açık; 000b = hepsi kapalı.
  • Kaynak koddaki biçim: datcw db 0000_0110b ve alt satırlarda db 0000_0100b… (alt çizgi yalnızca okunabilirlik içindir).

Step Motor

Mıknatıs Dizileri Adım Adım

  • Yarı adım dizisi (datcw): çift → tek → çift → tek mıknatıs.
  • Tam adım dizisi (datcw_fs): tek, çift, çift ve “hepsi kapalı” bayt.
  • Her OUT komutundan sonra motor yeni konumuna gidene kadar meşguldur; bu yüzden program her bayttan önce bit 7'yi yoklar.
2107654321000000110datcw[0] = 110b

CW yarı adım, 1. bayt: açık mıknatıslar → 2, 1

2107654321000000100datcw[1] = 100b

CW yarı adım, 2. bayt: açık mıknatıslar → 2

2107654321000000011datcw[2] = 011b

CW yarı adım, 3. bayt: açık mıknatıslar → 1, 0

2107654321000000010datcw[3] = 010b

CW yarı adım, 4. bayt: açık mıknatıslar → 1

2107654321000000001datcw_fs[0] = 001b

CW tam adım, 1. bayt: açık mıknatıslar → 0

2107654321000000011datcw_fs[1] = 011b

CW tam adım, 2. bayt: açık mıknatıslar → 1, 0

2107654321000000110datcw_fs[2] = 110b

CW tam adım, 3. bayt: açık mıknatıslar → 2, 1

2107654321000000000datcw_fs[3] = 000b

CW tam adım, 4. bayt: açık mıknatıslar → hiçbiri

Step Motor

Step Motor Kontrol Programı

ORG 100h
steps_before_direction_change = 20h
jmp start
datcw     db 110b,100b,011b,010b
datccw    db 011b,001b,110b,010b
datcw_fs  db 001b,011b,110b,000b
datccw_fs db 100b,110b,011b,000b
start:
mov bx, offset datcw
mov si, 0
mov cx, 0   ; tur sayacı
  • Yoklama (wait): bit 7 = 0 ise motor meşgul, tekrar oku.
  • [bx][si] = [BX + SI]: BX tablonun başı, SI sıra (0–3).
  • 4 bayt gönderilince SI = 0, CX +1; CX = 20h olunca BX 4 artar, son tablodan sonra başa döner.
  • steps_before_direction_change = 20h bir sabittir (EQU gibi), bellekte yer kaplamaz.
next_step:
wait: in al, 7
test al, 10000000b
jz wait
mov al, [bx][si]
out 7, al
inc si
cmp si, 4
jb next_step
mov si, 0
inc cx
cmp cx, steps_before_direction_change
jb  next_step
mov cx, 0
add bx, 4   ; sonraki tablo
cmp bx, offset datccw_fs
jbe next_step
mov bx, offset datcw
jmp next_step

Step Motor · Kodu adım adım çalıştır

Step Motor: İlk Tur

2107654321000000000

ORG 100h, steps_before_direction_change = 20h. Port 7 önce 00h (meşgul), sonra 80h (hazır) döndürecek.

2107654321000000000

Veri tablolarının üzerinden atla.

2107654321000000000

BX = 0102h: datcw tablosu (CW yarı adım).

2107654321000000000

SI = 0: tablonun ilk baytı.

2107654321000000000

CX = 0: tur sayacı.

2107654321000000000

IN AL, 7 → AL = 00h (bit 7 = 0, motor meşgul).

2107654321000000000

TEST AL, 80h → ZF = 1.

2107654321000000000

JZ: ZF = 1 → tekrar bekle.

2107654321000000000

IN AL, 7 → AL = 80h (bit 7 = 1, hazır).

2107654321000000000

TEST AL, 80h → ZF = 0.

2107654321000000000

JZ: ZF = 0 → devam.

2107654321000000000

AL ← [BX+SI] = [0102h] = 110b.

2107654321000000110

OUT 7, AL: mıknatıslar 110b → motor yarım adım (11,25°) döner.

2107654321000000110

SI = 1.

2107654321000000110

CMP SI, 4 → CF = 1.

2107654321000000110

JB: SI < 4 → next_step.

2107654321000000110

IN AL, 7 → AL = 80h (bit 7 = 1, hazır).

2107654321000000110

TEST AL, 80h → ZF = 0.

2107654321000000110

JZ: ZF = 0 → devam.

2107654321000000110

AL ← [BX+SI] = [0103h] = 100b.

2107654321000000100

OUT 7, AL: mıknatıslar 100b → motor yarım adım (11,25°) döner.

2107654321000000100

SI = 2.

2107654321000000100

CMP SI, 4 → CF = 1.

2107654321000000100

JB: SI < 4 → next_step.

2107654321000000100

IN AL, 7 → AL = 80h (bit 7 = 1, hazır).

2107654321000000100

TEST AL, 80h → ZF = 0.

2107654321000000100

JZ: ZF = 0 → devam.

2107654321000000100

AL ← [BX+SI] = [0104h] = 011b.

2107654321000000011

OUT 7, AL: mıknatıslar 011b → motor yarım adım (11,25°) döner.

2107654321000000011

SI = 3.

2107654321000000011

CMP SI, 4 → CF = 1.

2107654321000000011

JB: SI < 4 → next_step.

2107654321000000011

IN AL, 7 → AL = 80h (bit 7 = 1, hazır).

2107654321000000011

TEST AL, 80h → ZF = 0.

2107654321000000011

JZ: ZF = 0 → devam.

2107654321000000011

AL ← [BX+SI] = [0105h] = 010b.

2107654321000000010

OUT 7, AL: mıknatıslar 010b → motor yarım adım (11,25°) döner.

2107654321000000010

SI = 4.

2107654321000000010

CMP SI, 4 → CF = 0.

2107654321000000010

JB: SI = 4: tablo bitti.

2107654321000000010

SI = 0: tabloyu baştan oku.

2107654321000000010

CX = 1: bir tur (4 adım) tamamlandı.

2107654321000000010

CMP CX, 20h → CF = 1 (henüz 32 tur olmadı).

2107654321000000010

JB next_step: aynı tabloyla devam. 32 turdan sonra add bx, 4 sonraki tabloya geçer.

jmp start   ; tablolar 0102h-0111h
start:
mov bx, offset datcw
mov si, 0
mov cx, 0   ; tur sayacı
next_step:
wait: in al, 7
test al, 10000000b
jz wait
mov al, [bx][si]
out 7, al
inc si
cmp si, 4
jb next_step
mov si, 0
inc cx
cmp cx, steps_before_direction_change
jb  next_step

Step Motor

Gerçek Donanım: Unipolar Step Motor ve ULN2003

  • Unipolar motorda iki orta uçlu sargı vardır: dört sargı yarısı A, B, A̅, B̅; orta uçlar +V'ye bağlanır (5 ya da 6 tel).
  • Sargı akımı (yüzlerce mA) port ucunun sürebileceğinden çok büyüktür; araya ULN2003 konur: 7 Darlington kanalı, kanal başına 500 mA'e kadar.
  • Giriş = 1 → çıkış toprağa çeker → o sargı yarısından akım geçer.
  • Akım kesilince sargıda oluşan ters gerilim, COM ucu +V'ye bağlanarak ULN2003'ün iç diyotlarıyla sönümlenir.
  • Motor açık çevrimdir: “hazır” biti yoktur, hızı adımlar arası bekleme belirler. Çok kısa beklemede motor adım kaçırır.
8255ULN2003PA01B1CAPA12B2CBPA23B3CA̅PA34B4CB̅COM+V (motor beslemesi)unipolar motorAA̅BB̅orta uç

Step Motor

Gerçek Motor: Uyarma Dizileri

SürüşPort A dizisi (B̅ A̅ B A = bit 3…0)
Tek faz (dalga), tam adım01h 02h 04h 08h
İki faz, tam adım03h 06h 0Ch 09h
Yarım adım01h 03h 02h 06h 04h 0Ch 08h 09h
  • İki faz sürüşte her an iki sargı yarısı akım çeker: tork daha yüksektir.
  • Yarım adım iki diziyi sırayla karıştırır: adım açısı yarıya iner (ör. 1,8° → 0,9°).
  • Dizi tersten uygulanırsa motor ters yönde döner.
  • emu8086'nın sanal motoru 3 mıknatıslı basit bir modeldir (bit 0–2, bit 7 hazır); onun tabloları (110b, 100b, …) 4 fazlı gerçek motora uygulanmaz.
; 82h ile port A çıkış yapılmış olsun
yarim db 01h,03h,02h,06h
      db 04h,0Ch,08h,09h
adim  dw 0

ileri:
inc adim         ; geri için: dec adim
mov bx, adim
and bx, 7        ; dizin 0–7
mov al, yarim[bx]
mov dx, 310h     ; port A
out dx, al
call bekle       ; adım aralığı = hız
jmp ileri

Step Motor · Kodu adım adım çalıştır

Gerçek Motor: Yarım Adım Dizisini Sürmek

org 100h
ileri:
inc adim         ; geri: dec adim
mov bx, adim
and bx, 7        ; dizin 0–7
mov al, yarim[bx]
mov dx, 310h     ; port A
out dx, al
call bekle       ; adım aralığı
jmp ileri
bekle: ret       ; (gecikme)
yarim db 01h,03h,02h,06h
      db 04h,0Ch,08h,09h
adim  dw 6
BX0007hAL00hyarim[ ]0100310220630440C5086097port A (310h) = —ABA̅B̅

Sargılar: bit 0 = A, bit 1 = B, bit 2 = A̅, bit 3 = B̅. adim = 6 iken INC → 7; AND BX, 7 dizini 0–7'de tutar → BX = 7.

BX0007hAL09hyarim[ ]0100310220630440C5086097port A (310h) = 09hABA̅B̅alan ≈ 315°

AL ← yarim[7] = 09h = 1001b → B̅ ve A sargıları: alan ikisinin arasına (≈ 315°) döner. Port A'ya yazılır.

BX0007hAL09hyarim[ ]0100310220630440C5086097port A (310h) = 09hABA̅B̅alan ≈ 315°

CALL bekle / RET: adımlar arası bekleme motorun hızını belirler. JMP ileri.

BX0000hAL09hyarim[ ]0100310220630440C5086097port A (310h) = 09hABA̅B̅alan ≈ 315°

adim = 8 → AND 7 → BX = 0: dizi başa sarar.

BX0000hAL01hyarim[ ]0100310220630440C5086097port A (310h) = 01hABA̅B̅alan ≈ 0°

yarim[0] = 01h → yalnız A: alan 0°'ye geldi (yarım adım).

BX0000hAL01hyarim[ ]0100310220630440C5086097port A (310h) = 01hABA̅B̅alan ≈ 0°

Bekle ve tekrar.

BX0001hAL01hyarim[ ]0100310220630440C5086097port A (310h) = 01hABA̅B̅alan ≈ 0°

adim = 9 → BX = 1.

BX0001hAL03hyarim[ ]0100310220630440C5086097port A (310h) = 03hABA̅B̅alan ≈ 45°

yarim[1] = 03h → A + B: 45°. Her OUT alanı bir yarım adım (45° sargı açısı) ilerletir; dizi tersten okunursa motor geri döner.

Port 310h'e yazılan baytlar (09h, 01h, 03h …) yorumlayıcının G/Ç kaydından alındı; bekle burada yalnız RET'tir.

LED Ekran

LED Ekran (Port 199)

  • Port 199'a yazılan sözcük 5 basamaklı onluk sayı olarak gösterilir.
  • Değer işaretli (ikiye tümleyen) yorumlanır: −32 768 … 32 767.
  • −5678 = 10000h − 162Eh = E9D2h; ekranda -5678 görünür.
  • Yalnızca OUT 199, AX kullanılır (199 ≤ 255 olduğundan sabit port yeterli).
  • #make_bin#: DOS'a bağlı olmayan düz ikili (.bin) dosya üretilir.
00355port 199 (2 bayt) · AX = 0163h

LED Ekran · Kodu adım adım çalıştır

LED Ekran Kontrolü

00000port 199 (2 bayt) · AX = 0000h

Ekran başlangıçta 00000 gösterir.

00000port 199 (2 bayt) · AX = 0000h

AX = 1234 (onluk) = 04D2h.

01234port 199 (2 bayt) · AX = 04D2h

OUT 199, AX: ekranda 1234.

01234port 199 (2 bayt) · AX = 04D2h

AX = −5678 = E9D2h (ikiye tümleyen).

-5678port 199 (2 bayt) · AX = E9D2h

OUT 199, AX: ekranda -5678.

-5678port 199 (2 bayt) · AX = E9D2h

AX = 0: sayaç.

00000port 199 (2 bayt) · AX = 0000h

OUT 199, AX: ekranda 0.

00000port 199 (2 bayt) · AX = 0000h

AX = 1.

00000port 199 (2 bayt) · AX = 0000h

JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz).

00001port 199 (2 bayt) · AX = 0001h

OUT 199, AX: ekranda 1.

00001port 199 (2 bayt) · AX = 0001h

AX = 2.

00001port 199 (2 bayt) · AX = 0001h

JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz).

00002port 199 (2 bayt) · AX = 0002h

OUT 199, AX: ekranda 2.

00002port 199 (2 bayt) · AX = 0002h

AX = 3.

00002port 199 (2 bayt) · AX = 0002h

JMP x1: sonsuz döngü (alttaki HLT'ye hiç ulaşılmaz); sayaç 32767'den sonra −32768'e geçer.

#start=led_display.exe#
mov ax, 1234
out 199, ax
mov ax, -5678
out 199, ax
; port'a sonsuz döngüde yaz:
mov ax, 0
x1:
out 199, ax
inc ax
jmp x1
hlt              ; hiç çalışmaz

emu8086'da adım gecikmesi (step delay) 0 iken sayılar çok hızlı akar; döngüye INT 15h/86h ile bekleme eklenebilir.

LED Ekran

Gerçek Donanım: 7 Bölütlü Gösterge

abcdefgdpD70dpD61gD50fD40eD31dD21cD11bD01aortak katot '3': 4Fhortak anot '3': B0h (tersi)PA7 … PA0 → dp g f e d c b a
  • Ortak katot (CC): ortak uç toprakta, bit = 1 bölütü yakar.
  • Ortak anot (CA): ortak uç +5 V'ta, bit = 0 yakar: kod CC kodunun tersidir (NOT AL).
  • Her bölüte akım sınırlayıcı direnç bağlanır.
  • emu8086'nın port 199 LED ekranı sayıyı kendisi çözer; gerçek göstergede kodu program üretir.
RakamYanan bölütlerCCCA
0a b c d e f3FhC0h
1b c06hF9h
2a b d e g5BhA4h
3a b c d g4FhB0h
4b c f g66h99h
5a c d f g6Dh92h
6a c d e f g7Dh82h
7a b c07hF8h
8a b c d e f g7Fh80h
9a b c d f g6Fh90h

LED Ekran

Kod Tablosu, XLAT ve Çoklamalı Tarama

; rakamı (0–9) bölüt koduna çevir
mov bx, offset kod
mov al, 3        ; rakam
xlat              ; AL = [BX + AL] = 4Fh
; not al          ; ortak anot ise
mov dx, 310h     ; 8255 port A
out dx, al
kod db 3Fh,06h,5Bh,4Fh,66h
    db 6Dh,7Dh,07h,7Fh,6Fh
  • Çoklama: 4 basamağın bölüt uçları ortak port A'ya, ortak uçları ayrı transistörlerle port C'ye bağlanır.
  • Her an tek basamak yanar; basamak başına ≈ 4 ms → tam tur 16 ms ≈ 62 Hz. Göz titremeyi görmez (≈ 50 Hz üstü).
  • Basamağı değiştirmeden önce tümü kapatılır; yoksa önceki kod yan basamakta soluk görünür (gölge).
tara:
mov si, 0
hane:
mov dx, 312h      ; port C: hane seçimi
mov al, 0
out dx, al        ; önce tüm haneler sönük
mov al, rakam[si]
mov bx, offset kod
xlat
mov dx, 310h      ; port A: bölütler
out dx, al
mov al, secim[si] ; 01h, 02h, 04h, 08h
mov dx, 312h
out dx, al        ; yalnız bu hane yanar
call bekle_4ms
inc si
cmp si, 4
jb  hane
jmp tara
rakam db 1, 2, 3, 4
secim db 01h, 02h, 04h, 08h

LED Ekran · Kodu adım adım çalıştır

Çoklamalı Tarama: 2026 Gösterimi

org 100h
mov bx, offset kod
mov si, 0
hane:
mov dx, 312h  ; port C (hane)
mov al, 0
out dx, al    ; tümü sönük
mov al, rakam[si]
xlat          ; bölüt kodu
mov dx, 310h  ; port A (bölüt)
out dx, al
mov al, secim[si]
mov dx, 312h
out dx, al    ; tek hane yanar
inc si
cmp si, 4
jb  hane
ret
kod   db 3Fh,06h,5Bh,4Fh,66h
      db 6Dh,7Dh,07h,7Fh,6Fh
rakam db 2, 0, 2, 6
secim db 01h, 02h, 04h, 08h
SI0000hAL00hport A = —port C = —hane 1hane 2hane 3hane 4

BX = tablo başı, SI = 0. Gösterilecek sayı 2026 (rakam dizisi); 4 hanenin bölüt uçları ortak port A'ya bağlı.

SI0000hAL5Bhport A = —port C = 00hhane 1hane 2hane 3hane 4

1. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[0] = 2; XLAT → AL = 5Bh.

SI0001hAL01hport A = 5Bhport C = 01hhane 1hane 2hane 3hane 4

Port A ← 5Bh (bölütler), port C ← 01h: yalnız 1. hane yanar. INC SI, CMP, JB → sonraki hane.

SI0001hAL3Fhport A = 5Bhport C = 00hhane 1hane 2hane 3hane 4

2. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[1] = 0; XLAT → AL = 3Fh.

SI0002hAL02hport A = 3Fhport C = 02hhane 1hane 2hane 3hane 4

Port A ← 3Fh (bölütler), port C ← 02h: yalnız 2. hane yanar. INC SI, CMP, JB → sonraki hane.

SI0002hAL5Bhport A = 3Fhport C = 00hhane 1hane 2hane 3hane 4

3. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[2] = 2; XLAT → AL = 5Bh.

SI0003hAL04hport A = 5Bhport C = 04hhane 1hane 2hane 3hane 4

Port A ← 5Bh (bölütler), port C ← 04h: yalnız 3. hane yanar. INC SI, CMP, JB → sonraki hane.

SI0003hAL7Dhport A = 5Bhport C = 00hhane 1hane 2hane 3hane 4

4. hane: önce port C ← 00h (hepsi sönük, gölge olmasın). AL = rakam[3] = 6; XLAT → AL = 7Dh.

SI0004hAL08hport A = 7Dhport C = 08hhane 1hane 2hane 3hane 4

Port A ← 7Dh (bölütler), port C ← 08h: yalnız 4. hane yanar. INC SI, CMP, JB → SI = 4, döngü biter.

SI0004hAL08hport A = 7Dhport C = 08hhane 1hane 2hane 3hane 4

Dört hane sırayla birer kez yandı. Her hane ≈ 4 ms yansa tam tur 16 ms (≈ 62 Hz): göz dördünü birlikte görür.

Ortak katot kodları; port değerleri yorumlayıcının G/Ç kaydından. Gerçekte her hane ≈ 4 ms yanık tutulur.

Termometre

Termometre ve Isıtıcı (Port 125, 127)

  • IN AL, 125: anlık hava sıcaklığını (°C, işaretli bayt) okur.
  • OUT 127, AL: AL = 1 ısıtıcıyı açar, AL = 0 kapatır.
  • Isıtıcı açıkken sıcaklık yavaşça artar, kapalıyken düşer.
  • Amaç: sıcaklığı 60–80 °C arasında tutan bir termostat.
  • Sıcaklık eksi olabileceği için karşılaştırmalar işaretli atlamalarla (JL, JLE, JG) yapılır.
-4004080120port 125: 70 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

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

Termostat Programı

-4004080120port 125: 50 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

Port 125 sırayla 55, 70 ve 85 °C döndürecek. Isıtıcı başlangıçta kapalı.

-4004080120port 125: 50 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

AX = CS = 0700h.

-4004080120port 125: 50 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

DS = 0700h (kesim yazmacına sabit doğrudan yazılamaz).

-4004080120port 125: 55 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

IN AL, 125 → sıcaklık 55 °C.

-4004080120port 125: 55 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

CMP AL, 60: 55 − 60 → SF = 1, OF = 0.

-4004080120port 125: 55 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

JL (SF ≠ OF): 55 < 60 → low.

-4004080120port 125: 55 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

AL = 1.

-4004080120port 125: 55 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

OUT 127, AL: ısıtıcı açıldı.

-4004080120port 125: 55 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JMP ok.

-4004080120port 125: 55 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JMP start: yeni ölçüm.

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

IN AL, 125 → sıcaklık 70 °C.

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

CMP AL, 60: 70 − 60 → SF = 0, OF = 0.

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JL (SF ≠ OF): atlama yok.

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

CMP AL, 80 → ZF = 0, SF = 1.

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JLE: 60 ≤ 70 ≤ 80 → ok (ısıtıcıya dokunma).

-4004080120port 125: 70 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JMP start: yeni ölçüm.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

IN AL, 125 → sıcaklık 85 °C.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

CMP AL, 60: 85 − 60 → SF = 0, OF = 0.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JL (SF ≠ OF): atlama yok.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

CMP AL, 80 → ZF = 0, SF = 0.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JLE: atlama yok.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

JG: 85 > 80 → high.

-4004080120port 125: 85 °Cısıtıcı AÇIKport 127 = 1hedef aralık: 60–80 °C

AL = 0.

-4004080120port 125: 85 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

OUT 127, AL: ısıtıcı kapatıldı.

-4004080120port 125: 85 °Cısıtıcı KAPALIport 127 = 0hedef aralık: 60–80 °C

JMP start: yeni ölçüm.

; DS'yi CS'ye eşitle:
mov ax, cs
mov ds, ax
start:
in  al, 125
cmp al, 60
jl  low
cmp al, 80
jle ok
jg  high
low:
mov al, 1
out 127, al   ; ısıtıcı açık
jmp ok
high:
mov al, 0
out 127, al   ; ısıtıcı kapalı
ok:
jmp start     ; sonsuz döngü

jg high yerine jmp high da yazılabilirdi: JLE atlamadıysa sıcaklık zaten 80'den büyüktür.

Termometre

Etkileşimli Termostat

Yazıcı

Yazıcı (Printer, Port 130)

  • emu8086 yazıcısı port 130'a bağlıdır; ama program porta doğrudan yazmak yerine DOS işlevini kullanır:
  • INT 21h, AH = 05h: DL'deki karakteri yazıcıya (PRN) gönderir.
  • Kontrol karakterleri yazıcıyı yönetir:
KodAdEtki
0Ah (10)LFbir satır aşağı
0Dh (13)CRsatır başına dön
09h (9)HTyatay sekme (tab)
0Ch (12)FFyeni sayfa (form feed)
db 13, 9: 13 = CR (satır başı), 9 = yatay sekme (HT). Dikey sekme (VT) 11 = 0Bh'dir.

0Ah, 0Dh sırası LF + CR'dir; alışılmış sıra CR + LF'tir, ama ikisi birlikte aynı sonucu verir.
Hello, Printer!********Have a nice…0Ah, 0Dh: alt satırın başıCR (13): aynı satırın başına dönHT (9): 8. sütuna atla → üzerine basFF (12): sayfayı çıkar, yeni sayfa

Yazıcı

Yazıcı Programı: Veri

org 100h
jmp start
msg db "Hello, Printer!", 0Ah, 0Dh
    db "***************"
    db 13, 9    ; CR ve yatay sekme (HT)
    db "Have a nice printing day!"
msg_end db 0
msg2 db "press any key to eject the page.$"
Uzunlukoffset msg_end - offset msg derleme zamanında hesaplanır: 15 + 2 + 15 + 2 + 25 = 59 = 3Bh bayt.
msg_endSon karakterden hemen sonraki adres; değeri (0) yazdırılmaz, yalnızca bir işarettir.
msg2'$' ile biter: INT 21h / AH = 09h ekrana yazdırırken $'a kadar gider.

Yazıcı · Kodu adım adım çalıştır

Yazıcı Programı: Yazdırma Döngüsü

Çıktı paneli yazıcı kâğıdını gösterir: LF satır atlar, CR satır başına döner, TAB 8 sütunluk sekmeye gider.

DL = 12 (0Ch): form feed.

AH = 05h: DOS yazıcı çıkışı.

INT 21h: yazıcı yeni sayfaya geçer.

SI = 0102h: msg'nin adresi.

CX = 59 (003Bh): karakter sayısı.

DL ← [SI] = 'H'.

AH = 05h: DOS yazıcı çıkışı.

INT 21h: 'H' yazıcıya gider.

SI = 0103h.

LOOP: CX = 58 → devam.

DL ← [SI] = 'e'.

AH = 05h: DOS yazıcı çıkışı.

INT 21h: 'e' yazıcıya gider.

SI = 0104h.

LOOP: CX = 57 → devam.

DL ← [SI] = 'l'.

AH = 05h: DOS yazıcı çıkışı.

INT 21h: 'l' yazıcıya gider.

SI = 0105h.

LOOP: CX = 56 → devam.

… INT 21h: 'l' yazıldı (CX = 56).

… INT 21h: 't' yazıldı (CX = 48).

… INT 21h: '*' yazıldı (CX = 40).

… INT 21h: '*' yazıldı (CX = 32).

… INT 21h: 'a' yazıldı (CX = 24).

… INT 21h: 'c' yazıldı (CX = 16).

… INT 21h: 'i' yazıldı (CX = 8).

DL ← [SI] = '!'.

AH = 05h: DOS yazıcı çıkışı.

… INT 21h: '!' yazıldı (CX = 1).

SI = 013Dh.

LOOP: CX = 0 → 59 karakter bitti.

start:
mov dl, 12      ; form feed: yeni sayfa
mov ah, 5
int 21h
mov si, offset msg
mov cx, offset msg_end - offset msg
print:
mov dl, [si]
mov ah, 5       ; DOS yazıcı işlevi
int 21h
inc si          ; sonraki karakter
loop print

CR (13) LF olmadan gelince üçüncü metin yıldızların üzerine basılır (panelde üzerine yazma olarak gösterildi). Döngüden sonra: mov dx, offset msg2 / mov ah, 9 / int 21h ekrana mesaj yazar; int 16h (AH = 0) bir tuş bekler; son form feed sayfayı yazıcıdan çıkarır.

Robot

Robot (Port 9, 10, 11)

command (9): 00000001data (10): 00000000status (11): 00000000yanan lambasönük lambaduvar
  • Robot bir ızgara dünyasında hareket eder; duvarları ve lambaları algılayabilir, lambaları yakıp söndürebilir.
  • Port 9 komut (OUT), port 10 veri (IN), port 11 durum (IN). Dünya, aygıt penceresindeki araç kutusuyla düzenlenir.

Robot

Robot Komutları ve Durum Bitleri

Komut (port 9)Etki
0hiçbir şey yapma
1ileri git
2sola dön
3sağa dön
4önündekini incele (examine)
5lambayı yak
6lambayı söndür
Veri (port 10)Önündeki
255 (FFh)duvar
0boş
7yanan lamba
8sönük lamba
Durum (port 11)1 ise
bit 0veri yazmacında yeni veri var
bit 1robot meşgul (komut sürüyor)
bit 2son komutta hata

Robot

Robot Programı: Lambayı Bul ve Yak

#start=robot.exe#
dongu: CALL hazir_bekle
       MOV  AL, 4       ; incele
       OUT  9, AL
       CALL veri_bekle
       IN   AL, 10
       CMP  AL, 0FFh    ; duvar?
       JE   don
       CMP  AL, 8       ; sönük lamba?
       JNE  ilerle
       CALL hazir_bekle
       MOV  AL, 5       ; yak
       OUT  9, AL
       JMP  dongu
don:   MOV  AL, 3       ; sağa dön
       JMP  gonder
ilerle: MOV AL, 1       ; ileri
gonder: PUSH AX         ; komutu koru
       CALL hazir_bekle
       POP  AX
       OUT  9, AL
       JMP  dongu
  • Her komuttan önce meşgul biti (bit 1) sıfır olana kadar beklenir.
  • İncele (4) komutundan sonra veri hazır biti (bit 0) beklenir, sonra port 10 okunur.
  • Duvarsa sağa dön, sönük lambaysa yak, yoksa ilerle.
  • Bekleme yordamları CALL ile çağrılır: dönüş adresi yığında.

Robot

Robot: Bekleme Yordamları ve Dikkat Edilecekler

hazir_bekle PROC
b1:    IN   AL, 11
       TEST AL, 010b    ; meşgul?
       JNZ  b1
       RET
hazir_bekle ENDP

veri_bekle PROC
v1:    IN   AL, 11
       TEST AL, 001b    ; yeni veri?
       JZ   v1
       RET
veri_bekle ENDP
AL korunmalıhazir_bekle AL'yi IN ile ezer. gonder yolunda AL komut değerini taşıdığı için yordamdan önce PUSH AX, sonra POP AX yapılır; aksi hâlde porta durum baytı gönderilirdi.
Hata bitiDuvara doğru “ileri” komutu hata (bit 2) üretir; durum okunup kontrol edilmelidir.
Yoklama maliyetiCPU bekleme döngüsünde tamamen meşguldür; gerçek sistemlerde kesmeler tercih edilir.

Robot

Basit G/Ç Test Aygıtı (Port 110, 112)

  • Port 110: bir bayt; port 112: bir word.
  • Pencereye yazılan değerler programa giriş olur (hex için h soneki), programın yazdıkları pencerede görünür.
  • Giriş portları her 100 ms'de güncellenir.
  • IN/OUT'u denemek ve hata ayıklamak için idealdir.
IN   AL, 110    ; ör. A7h okunur
INC  AL
OUT  110, AL    ; A8h yazılır
IN   AX, 112    ; ör. 1234h
ADD  AX, 1
OUT  112, AX    ; 1235h
simple io testwrite byte to port 110:write word to port 112:read byte from port 110:A8hread word from port 112:1235h

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

Test Aygıtı: Bayt ve Sözcük G/Ç

org 100h
in   al, 110     ; bayt oku
inc  al
out  110, al     ; bayt yaz
in   ax, 112     ; sözcük oku
add  ax, 1
out  112, ax     ; sözcük yaz
ret
AX00FFhZF0SF0OF0CF0port 110 (bayt)giriş: FFhçıkış: —port 112 (sözcük)giriş: 7FFFhçıkış: —

Test aygıtı penceresine girilen değerler: port 110 = FFh, port 112 = 7FFFh. IN AL, 110 → AL = FFh.

AX0000hZF1SF0OF0CF0port 110 (bayt)giriş: FFhçıkış: —port 112 (sözcük)giriş: 7FFFhçıkış: —

INC AL: FFh + 1 = 00h (8 bitte taşar). ZF = 1; INC, CF'yi değiştirmez.

AX0000hZF1SF0OF0CF0port 110 (bayt)giriş: FFhçıkış: 00hport 112 (sözcük)giriş: 7FFFhçıkış: —

OUT 110, AL: pencerede port 110 = 00h.

AX7FFFhZF1SF0OF0CF0port 110 (bayt)giriş: FFhçıkış: 00hport 112 (sözcük)giriş: 7FFFhçıkış: —

IN AX, 112: 16 bit okuma → AX = 7FFFh (+32 767).

AX8000hZF0SF1OF1CF0port 110 (bayt)giriş: FFhçıkış: 00hport 112 (sözcük)giriş: 7FFFhçıkış: —

ADD AX, 1 → 8000h: iki pozitifin toplamı negatif oldu → OF = 1, SF = 1; işaretsiz taşma yok, CF = 0.

AX8000hZF0SF1OF1CF0port 110 (bayt)giriş: FFhçıkış: 00hport 112 (sözcük)giriş: 7FFFhçıkış: 8000h

OUT 112, AX: pencerede port 112 = 8000h.

AX8000hZF0SF1OF1CF0port 110 (bayt)giriş: FFhçıkış: 00hport 112 (sözcük)giriş: 7FFFhçıkış: 8000h

RET: program biter.

Giriş değerleri yorumlayıcının port sözlüğüne verildi; çıkışlar G/Ç kaydından okundu.

Özet

Özet

AygıtPortAnahtar fikir
Trafik lambaları4Her bit bir lamba; durum tablosu + INT 15h/86h bekleme.
Step motor7Bit 0–2 mıknatıs, bit 7 hazır; yarı adım 11,25°, tam adım 22,5°.
LED ekran199Sözcük, işaretli onluk gösterim.
Termometre125, 127Okuma + işaretli karşılaştırma + ısıtıcı aç/kapa.
Yazıcı130INT 21h/05h; kontrol karakterleri LF, CR, HT, FF.
Robot9, 10, 11Komut, veri, durum; meşgul/veri bitlerini yokla.
Test aygıtı110, 112Bayt ve sözcük G/Ç denemesi.
8255 PPI (gerçek)310h–313hKontrol sözcüğü (ör. 82h) port yönlerini belirler; port > 255 → DX.

Ortak desen: durum oku → bit test et → hazırsa veri yaz/oku → döngü. IN/OUT yalnızca AL/AX ile, port > 255 ise DX ile.

Özet

Alıştırmalar

  1. Tüm yönlerde yalnızca sarı lambaları yakan port 4 değeri nedir?
  2. 2,5 saniyelik bekleme için CX ve DX ne olmalıdır?
  3. LED ekranda −1 göstermek için AX'e hangi onaltılık değer yazılır?
  4. Termostatı 20–25 °C aralığına göre değiştirin; sıcaklık −10 °C iken JB kullanılsaydı ne olurdu?
  5. Step motor programında motoru yalnızca saat yönünde, tam adımla döndürmek için hangi satırlar değişmeli?
Cevaplar
  1. Bit 1, 4, 7, 10 → 0000_0100_1001_0010b = 0492h.
  2. 2 500 000 = 002625A0h → CX = 0026h, DX = 25A0h.
  3. FFFFh.
  4. cmp al, 20 / jl low / cmp al, 25 / jle ok / .... −10 = F6h; işaretsiz JB için 246 > 20 olur ve ısıtıcı açılmazdı.
  5. mov bx, offset datcw_fs ve tablo değiştiren kısım (inc cx … jmp next_step) kaldırılıp jmp next_step yazılır.

Özet

Alıştırmalar (devam)

  1. Yazıcıya “Merhaba” yazıp sayfayı çıkaran en kısa programı yazın.
  2. 8 MHz'lik bir 8086'da mov cx, N / loop ile yaklaşık 1 ms gecikme için N kaçtır?
  3. 8255'te A giriş, B çıkış, C'nin tamamı giriş (mod 0) için kontrol sözcüğü nedir?
  4. Ortak anotlu göstergede '5' ve 'H' harfinin kodları nedir (dp g f e d c b a sırası)?
Cevaplar
  1. Her karakter için MOV DL, 'M' / MOV AH, 5 / INT 21h (veya döngü), sonunda DL = 12 ile form feed.
  2. 17N − 8 = 8 000 → N ≈ 471 (7 999 saat turu).
  3. 1 00 1 1 0 0 1b = 99h.
  4. '5': CC 6Dh → CA 92h; 'H' (b c e f g): CC 76h → CA 89h.

Özet

Kaynaklar

  • emu8086 yardım belgeleri: I/O ports and hardware interrupts, Virtual devices ve örnek programlar (traffic_lights.asm, stepper_motor.asm, led_display_test.asm, thermometer.asm, printer.asm, robot.asm).
  • Intel, The 8086 Family User's Manual, 1979 — IN/OUT komutları, G/Ç adres uzayı ve komut süreleri.
  • Intel, 8255A Programmable Peripheral Interface veri sayfası; Texas Instruments, ULN2003A veri sayfası.
  • M. Bodur, Mikroişlemcilere Giriş: Assembler ile Yazılım ve Arayüz, EMO, 2014.
  • R. Brown, Ralf Brown's Interrupt List — INT 15h/86h, INT 21h/05h, INT 16h/00h.
  • B. B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009 — Bölüm 11 (Temel G/Ç arayüzü).

Son

Bölüm 10: Aygıt Kontrolü
Sonraki bölüm: Bölüm 11: Komut Kodlama ve Dizgi Komutları · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.