Mikroişlemciler · Ders Notu
Bölüm 2.1: 8086 Mimarisi
Assembly dilinde yazılan her satır, işlemcinin içindeki somut bir donanım parçasını çalıştırır: bir yazmaca değer yükler, ALU'ya toplama yaptırır ya da adres yoluna 20 bitlik bir adres koyar. Bu yüzden 8086'yı programlamadan önce içini tanımak gerekir. Bu not, Intel 8086'nın genel özellikleriyle başlar ve işlemcinin belleğe ve G/Ç aygıtlarına yollar üzerinden nasıl bağlandığını anlatır. Ardından iki iç birimi, yol arayüz birimini (BIU) ve yürütme birimini (EU), önden getirme kuyruğunu ve boru hattını inceler. ALU'nun işlemlerini ve komutların bellekteki bayt uzunluklarını kod izlemeleriyle gösterir. Son kesimler yazmaç kümesini ve 8086'nın en ayırt edici özelliği olan kesimli belleği ele alır: 16 bitlik iki değerden 20 bitlik fiziksel adresin nasıl üretildiğini, aynı baytın neden birçok adla anılabildiğini ve hangi erişimin hangi kesimi kullandığını.
Öğrenme çıktıları
- Genel özellikleri açıklamak
- 8086'nın veri yolu ve adres yolu genişliğini, adresleyebildiği bellek miktarını, x86 ailesindeki yerini ve bir 8086 sisteminin hangi yongalardan oluştuğunu söylemek.
- Yolları izlemek
- Adres, veri ve kontrol yollarının görevini ayırmak; bir bellek ya da G/Ç okuma ve yazma işleminde yollarda hangi değerlerin bulunduğunu kod üzerinde göstermek.
- İç yapıyı anlatmak
- BIU ve EU birimlerinin görevlerini, önden getirme kuyruğunun işleyişini, boru hattının kazancını ve dallanmanın kuyruğa etkisini açıklamak; bir komutun getirilip yürütülmesini blok diyagram üzerinde izlemek.
- Makine kodunu okumak
- Bir komutun işlem kodu, ModR/M baytı, yer değiştirme ve anlık veri alanlarını ayırmak; komut uzunluklarından IP'nin her adımdaki değerini bulmak.
- Yazmaçları gruplamak
- 14 yazmacı gruplarına ayırmak; kesim yazmaçlarının kullanım kurallarını ve IP'nin görevini açıklamak.
- Fiziksel adres hesaplamak
kesim × 10h + bağıl konumile 20 bitlik fiziksel adresi bulmak; bir adresi normalleştirmek; 1 MB sınırındaki sarmayı ve varsayılan kesim kurallarını kod izlemeleriyle göstermek.
2.1.18086'ya genel bakış
Intel 8086, 1978'de piyasaya çıkan 16 bitlik bir mikroişlemcidir. Bugün masaüstü ve dizüstü bilgisayarlarda çalışan x86 işlemci ailesinin ilk üyesidir. Kırk yılı aşkın sürede bu ailenin işlemcileri 32 ve 64 bite büyüdü, saat hızları binlerce kat arttı. Yine de her yeni üye, 8086 için yazılmış komutları çalıştırmayı sürdürdü. Bu yüzden 8086'nın yazmaçlarını, adres hesabını ve komut biçimini öğrenmek, bugünkü işlemcilerin en alt katmanını öğrenmek demektir.
Bu kesim önce 8086'nın temel sayılarını verir: kaç bitlik veriyle çalıştığını, ne kadar bellek adresleyebildiğini, hangi teknolojiyle üretildiğini. Ardından 8086'nın ailedeki yerini ve 20 bitlik adres yolunun neden seçildiğini anlatır. Son olarak bir mikroişlemcinin tek başına bir bilgisayar olmadığını, çevresinde hangi yongalara gerek duyduğunu gösterir.
2.1.1.1Temel özellikler
Bir işlemciyi “16 bitlik” diye anmak, onun aynı anda üzerinde çalışabildiği verinin genişliğini anlatır. 8086'nın genel amaçlı yazmaçları 16 bittir. Aritmetik-mantık birimi (ALU, arithmetic logic unit) iki 16 bitlik sayıyı tek işlemde toplar. Dış veri yolu da 16 hatlıdır, yani işlemci bellekle tek seferde 2 bayt alışverişi yapar. Bu üç genişliğin birbirine eşit olması 8086'yı “tamamen 16 bitlik” bir işlemci yapar.
Adres yolu ise 20 hatlıdır. Her hat bir bit taşıdığı için işlemci 220 farklı adres üretebilir. 220 = 1 048 576 bayttır, yani 1 MB. Adresler onaltılık olarak beş basamakla yazılır: en düşük adres 00000h, en yüksek adres FFFFFh'dir.
| Özellik | Değer | Anlamı |
|---|---|---|
| Veri yolu | 16 bit | bir yol döngüsünde en çok 2 bayt taşınır |
| Adres yolu | 20 bit | 220 bayt = 1 MB bellek adreslenir |
| Yazmaçlar, ALU | 16 bit | sözcük boyu 16 bittir |
| Paket | 40 pin DIP | çift sıralı plastik ya da seramik kılıf |
| Saat | 5–10 MHz | 8086: 5 MHz, 8086-2: 8 MHz, 8086-1: 10 MHz |
| Transistör | yaklaşık 29 000 | HMOS (yüksek yoğunluklu n kanallı MOS) teknolojisi |
| Besleme | +5 V | tek besleme gerilimi |
| Mimari | CISC | 1–6 bayt uzunlukta komutlar, bellek üzerinde işlem yapan komutlar |
Tablo 2.1.1 bu sayıları toplar. Saat hızı, işlemcinin içindeki bütün işlemleri eş zamanlayan kare dalganın frekansıdır. 5 MHz'lik bir saatin bir periyodu 1 / 5 000 000 s = 200 ns sürer. Bu süreye saat turu (clock cycle) denir. 8086'da en basit komut birkaç saat turunda biter; çarpma ve bölme gibi karmaşık komutlar yüzlerce tur sürebilir.
CISC (complex instruction set computer, karmaşık komut kümeli bilgisayar) tasarımında komutlar farklı uzunluklardadır ve bir komut doğrudan bellekteki bir işlenenle çalışabilir. Örneğin ADD AX, [BX] komutu bellekten bir sözcük okur ve AX'e ekler. Bu tasarım bellek pahalıyken programları kısa tutmayı amaçlıyordu: sık kullanılan işler tek bir komuta sığdırılırdı.
8086'nın bir de kardeşi vardır: 8088. 8088'in yazmaçları ve ALU'su 16 bittir, ama dış veri yolu 8 hatlıdır. Bir sözcüğü bellekten okumak için iki ayrı yol döngüsü yapar. IBM, 1981'deki ilk kişisel bilgisayarında 8088'i seçti; 8 bitlik yol, o yılların ucuz 8 bitlik çevre yongalarıyla kolayca birleşiyordu. Programcı açısından iki işlemci aynı komutları çalıştırır.
“16 bitlik işlemci 64 KB bellek adresler” düşüncesi yanlıştır. Veri yolunun genişliği bir seferde ne kadar veri taşındığını, adres yolunun genişliği ne kadar bellek seçilebildiğini belirler. İkisi birbirinden bağımsızdır. 8086'nın verisi 16 bit, adresi 20 bittir; bu yüzden 64 KB değil 1 MB adresler.
2.1.1.2x86 ailesindeki yeri
8086'dan sonra gelen işlemciler, öncekiler için yazılmış programları değiştirmeden çalıştırabilecek biçimde tasarlandı. Bu ilkeye geriye dönük uyumluluk (backward compatibility) denir. Tablo 2.1.2 ailenin ilk beş üyesini karşılaştırır.
| İşlemci | Yıl | İç / dış veri yolu | Adres yolu | Bellek | Belirgin özellik |
|---|---|---|---|---|---|
| 8086 | 1978 | 16 / 16 bit | 20 bit | 1 MB | 6 baytlık önden getirme kuyruğu |
| 8088 | 1979 | 16 / 8 bit | 20 bit | 1 MB | 4 baytlık kuyruk; IBM PC (1981) |
| 80186 | 1982 | 16 / 16 bit | 20 bit | 1 MB | tümleşik çevre birimleri |
| 80286 | 1982 | 16 / 16 bit | 24 bit | 16 MB | korumalı mod |
| 80386 | 1985 | 32 / 32 bit | 32 bit | 4 GB | 32 bitlik x86 (IA-32) |
Tablodaki bellek sütunu doğrudan adres yolundan gelir: 24 bit 224 = 16 777 216 bayt (16 MB), 32 bit 232 = 4 294 967 296 bayt (4 GB) eder. 80186, 8086'nın çekirdeğine saat üreteci, zamanlayıcı ve kesme denetleyicisi gibi çevre birimlerini ekleyerek gömülü sistemler için tek yongada daha çok iş toplar. 80286 korumalı modu getirir: bu modda programlar birbirinin belleğine erişemez ve 16 MB'ın tamamı kullanılabilir.
Gerçek mod (real mode), x86 işlemcilerin 8086 gibi davrandığı çalışma modudur: adresler 16 bitlik kesim ve bağıl konum çiftinden 20 bitlik fiziksel adres olarak hesaplanır, bellek koruması yoktur ve doğrudan erişilebilen alan 1 MB'tır. 80286'dan bu yana her x86 işlemci açıldığında gerçek modda başlar.
Bu derste emu8086 ile yazılan bütün programlar 8086 gerçek modunda çalışır. Bugünkü bir bilgisayarda da açılışın ilk anlarında işlemci gerçek moddadır; işletim sistemi daha sonra onu korumalı ya da 64 bitlik moda geçirir.
2.1.1.3Neden 20 bit adres?
Bellek, her biri bir bayt tutan hücrelerin sıralanmasıdır. Her hücrenin bir numarası, yani adresi vardır. İşlemci bir hücreye erişmek için onun adresini adres yoluna koyar. n hatlı bir adres yolu 2n farklı bit deseni taşıyabilir, bu yüzden 2n farklı bayt seçebilir.
16 ve 20 bitlik adres yollarının kapasitesini karşılaştıralım.
- 16 bit: 216 = 65 536 bayt. 1 KB = 210 = 1024 bayt olduğundan 65 536 / 1024 = 64 KB. Adresler
0000h–FFFFh. - 20 bit: 220 = 1 048 576 bayt. 1 MB = 220 bayt olduğundan tam 1 MB. Adresler
00000h–FFFFFh. - Oran: 220 / 216 = 24 = 16. Dört ek hat, adreslenebilen belleği 16 katına çıkarır.
Her onaltılık basamak dört bittir; 20 bit tam beş basamak eder. Bu yüzden fiziksel adresler hep beş basamakla yazılır.
8086'nın tasarımcıları burada bir çelişkiyle karşılaştı. 1978'de 64 KB bellek artık dar geliyordu; daha büyük bir adres alanı gerekiyordu. Ama işlemcinin yazmaçları 16 bitti ve tek bir yazmaç ancak 64 KB'lık bir aralığı gösterebilirdi. Yazmaçları 20 bite çıkarmak yongayı büyütür ve 8 bitlik işlemcilerden gelen yazılımla uyumu bozardı. Çözüm, adresi iki 16 bitlik değerden üretmek oldu: biri bir bellek bölgesinin, yani kesimin (segment) başlangıcını, öteki o bölge içindeki uzaklığı, yani bağıl konumu (offset) verir. İşlemci kesim değerini 16 ile çarpar ve bağıl konumu ekler. Bu hesap 20 bitlik bir sonuç verir. Şekil 2.1.1 bu fikri özetler.
2.1.1.4Mikroişlemci ve mikrodenetleyici
8086 bir mikroişlemcidir: merkezî işlem biriminin (CPU, central processing unit) bütün işlevlerini tek bir tümleşik devrede toplar. Ama içinde program ya da veri saklayacak bir bellek yoktur. Yonganın içinde yalnız yazmaçlar bulunur; ara ve son sonuçlar bu yazmaçlarda tutulur. Program kodu, değişkenler ve yığın dışarıdaki RAM ve ROM yongalarındadır. İşlemci bu belleğe ve G/Ç (giriş/çıkış) aygıtlarına sistem yolu üzerinden erişir.
Mikroişlemci, CPU'nun komut getirme, çözme ve yürütme işlevlerini tek yongada toplayan, ama bellek ve G/Ç birimlerini dışarıda bırakan tümleşik devredir. Mikrodenetleyici (MCU, microcontroller) ise CPU ile birlikte program belleğini (ROM ya da Flash), RAM'i, zamanlayıcıları ve G/Ç portlarını aynı yongada taşır.
İki yaklaşımın kullanım alanı farklıdır. Bir mikrodenetleyici (8051, AVR, PIC) tek başına bir sistem gibi çalışabilir: besleme ve bir kristal bağlanınca programını kendi belleğinden okur, portlarından lambaları yakar, sensör okur. Çamaşır makinesi, uzaktan kumanda ve sensör düğümü gibi gömülü uygulamalarda düşük maliyeti ve düşük güç tüketimi öne çıkar. İşlem gücü ise genellikle sınırlıdır. Mikroişlemci ise esnektir: bellek miktarı ve çevre birimleri uygulamaya göre seçilir, ama sistem birçok yongadan oluşur.
Şekil 2.1.2 en küçük 8086 sisteminin parçalarını gösterir. Her yonganın görevi şöyledir:
- 8284A saat üreteci 8086'ya saat sinyalini (CLK) verir. Dışarıdaki kristalin frekansını üçe böler: 15 MHz'lik bir kristal 5 MHz'lik saat üretir. Ayrıca RESET ve READY sinyallerini saatle eş zamanlar.
- Adres kilitleri (latch, 8282 ya da 74LS373) adresi yakalayıp yol döngüsü boyunca tutar. 8086'nın 40 pini her sinyale ayrı bir pin vermeye yetmez. Bu yüzden adresin alt 16 biti ile veri aynı pinlerden (AD0–AD15) farklı zamanlarda çıkar. Döngünün başında pinlerde adres vardır; işlemci ALE (address latch enable) darbesi üretir ve kilitler adresi yakalar. Sonra aynı pinler veriye geçer, ama bellek kilitteki adresi görmeye devam eder. 20 bit için 8 bitlik üç kilit gerekir.
- Veri yolu alıcı-vericileri (transceiver, 8286) veri hatlarını güçlendirir ve yönünü belirler: okumada bellekten işlemciye, yazmada işlemciden belleğe. 16 bit için iki tane kullanılır.
- Bellek (RAM ve ROM) program ve veriyi tutar; G/Ç birimleri klavye, ekran ve portlar gibi dış dünyayla bağlantıyı kurar.
Bu ek yongalar mikroişlemcinin bedelidir. Buna karşılık sistemin belleği 1 MB'a kadar büyütülebilir ve her türlü çevre birimi eklenebilir. Kişisel bilgisayarlar bu yolu seçti.
2.1.2Sistem yolları
İşlemci, bellek ve G/Ç aygıtları birbirine paralel tel demetleriyle bağlanır. Her demete yol (bus) denir. Bir yolun genişliği içindeki hat sayısıdır; her hat aynı anda bir bit taşır. Sistemde üç yol vardır ve her birinin görevi ayrıdır.
2.1.2.1Adres, veri ve kontrol yolu
Sistem yolu (system bus), CPU, bellek ve G/Ç aygıtlarını birbirine bağlayan üç yolun bütünüdür. Adres yolu erişilecek bellek konumunu ya da G/Ç portunu seçer ve yalnız işlemciden dışarı doğru çalışır. Veri yolu komut ve veri baytlarını iki yönde taşır. Kontrol yolu işlemin türünü (okuma, yazma, bellek ya da G/Ç) ve zamanlamasını bildiren sinyallerden oluşur.
| Yol | Ne taşır? | Yön | 8086'da |
|---|---|---|---|
| Adres | okunacak ya da yazılacak bellek konumu, G/Ç port numarası | CPU → dış | 20 bit → 1 MB bellek; G/Ç için 16 bit → 64 K port |
| Veri | işlemci ile bellek ya da G/Ç arasındaki komut ve veri baytları | çift yönlü | 16 bit, tek seferde bir sözcük (2 bayt) |
| Kontrol | okuma, yazma, bellek/G/Ç seçimi, kesme istekleri, durum bilgisi | sinyale göre | RD', WR', M/IO', ALE, INTR, READY … |
Adresi yalnız işlemci üretir; bellek ya da G/Ç aygıtı adres yoluna hiçbir şey koymaz. Bu yüzden adres yolu tek yönlüdür. Veri ise okumada dışarıdan işlemciye, yazmada işlemciden dışarıya akar; veri yolu iki yönlüdür. Kontrol yolundaki sinyallerin bir kısmını işlemci üretir (RD', WR', M/IO', ALE), bir kısmını dış aygıtlar üretir (INTR kesme isteği, READY hazır sinyali).
Sinyal adlarının sonundaki kesme işareti (') sinyalin etkin düşük olduğunu gösterir: sinyal, mantık 0 düzeyindeyken görevini yapar. RD' = 0 “şimdi oku”, WR' = 0 “şimdi yaz” anlamına gelir. M/IO' sinyali erişimin hedefini seçer: 1 iken bellek, 0 iken G/Ç. Bellek yongaları yalnız M/IO' = 1 iken, G/Ç aygıtları yalnız M/IO' = 0 iken yanıt verir. Böylece aynı adres ve veri hatları iki ayrı adres uzayına hizmet eder.
G/Ç adres uzayı bellekten küçüktür. G/Ç erişiminde adresin yalnız alt 16 biti (A15–A0) kullanılır, A19–A16 hatları 0 olur. 216 = 65 536 port numarası vardır. IN ve OUT komutları port numarasını ya komutun içinde 8 bitlik bir sabit olarak (0–FFh) ya da DX yazmacında (0–FFFFh) alır.
2.1.2.2Yol döngüsü
İşlemcinin bellekten ya da G/Ç'den bir kez okuması ya da bir kez yazması bir yol döngüsü (bus cycle) sürer. 8086'da bir yol döngüsü en az dört saat turundan oluşur. Bu turlara T durumları denir ve T1, T2, T3, T4 diye adlandırılır.
Yol döngüsü, bellek ya da G/Ç ile tek bir okuma veya yazma işleminin baştan sona sürdüğü zaman dilimidir. 8086'da dört T durumundan (T1–T4) oluşur; yavaş bir aygıt READY sinyalini 0 tutarak T3 ile T4 arasına bekleme durumları (Tw) ekletebilir.
Bir bellek okuma döngüsü şu sırayla ilerler:
- T1: İşlemci 20 bitlik adresi adres hatlarına koyar, M/IO' ile hedefi bildirir ve ALE darbesi verir. Kilitler adresi yakalar.
- T2: AD0–AD15 pinleri adresten çekilir ve veri için serbest kalır. İşlemci RD' sinyalini 0 yapar: “oku”.
- T3: Bellek, adresteki baytı ya da sözcüğü veri yoluna koyar. İşlemci READY'yi yoklar; aygıt hazırsa veriyi alır.
- T4: RD' yeniden 1 olur, bellek veri yolunu bırakır. Döngü biter.
Yazma döngüsünde sıra aynıdır; farkı, veriyi işlemcinin T2'den başlayarak veri yoluna koyması ve RD' yerine WR' sinyalini 0 yapmasıdır. Bellek, WR' etkinken veri yolundaki değeri hücresine yazar.
5 MHz'lik bir 8086 bekleme durumu olmadan bellekten 100 sözcük okuyor. En az ne kadar sürer?
- Bir saat turu: 1 / 5 MHz = 200 ns.
- Bir yol döngüsü: 4 × 200 ns = 800 ns.
- Sözcükler çift adreslerde duruyorsa her sözcük tek döngüde gelir: 100 × 800 ns = 80 000 ns = 80 µs.
Bu, yolun en yüksek aktarım hızının 2 bayt / 800 ns = 2,5 MB/s olduğunu gösterir. Sözcükler tek adreslerde dursaydı her biri iki döngü alır, süre 160 µs olurdu. 8086'nın belleği çift ve tek adresli iki bayt bankasına bölünmüştür. Tek adresten başlayan bir sözcüğün baytları farklı satırlarda kalır ve tek döngüde birlikte okunamaz.
Bu süreler yazmaçlarla karşılaştırılınca bir şey açıkça görülür: bellek yavaştır. Bir yazmaçtan yazmaca MOV AX, BX 8086'da 2 saat turu sürer. Aynı değeri bellekten okuyan MOV AX, [BX] ise adres hesabı ve yol döngüsüyle birlikte 13 tur sürer. Bu yüzden sık kullanılan değerler yazmaçlarda tutulur ve 8086'nın iç yapısı bellek beklemesini gizlemek için düzenlenmiştir.
2.1.2.3Kod izleme: yollar üzerinde bellek ve G/Ç
Aşağıdaki program dört erişim yapar: bellekten okur, G/Ç portuna yazar, G/Ç portundan okur ve belleğe yazar. Her erişimde yollarda hangi değerlerin bulunduğunu izlemek, adres, veri ve kontrol yollarının görevini somutlaştırır. Programın başında bellekte 10200h adresinde 5Ah, 51h numaralı G/Ç portunda 3Ch değerinin bulunduğu varsayılır.
org 100h
mov ax, 1000h
mov ds, ax
mov bx, 0200h
mov al, [bx] ; bellek oku
out 50h, al ; G/Ç yaz
in al, 51h ; G/Ç oku
mov [bx+1], al ; bellek yaz
retorg 100h bir komut değil, assembler'a verilen bir yönergedir. Programın .COM biçiminde, kesimin 100h bağıl konumundan başlayacağını bildirir. İlk iki komut DS yazmacına 1000h yükler. Değer önce AX'e, sonra AX'ten DS'ye taşınır; çünkü 8086'da bir kesim yazmacına doğrudan sabit yüklenemez. DS = 1000h olunca veri kesimi fiziksel 10000h adresinden başlar. mov bx, 0200h BX'e bağıl konumu koyar. Bu üç komut yalnız yazmaçları değiştirir; veri için yol kullanılmaz. Yollar yalnız komut baytlarının getirilmesi için çalışır.
mov al, [bx] ilk veri erişimidir. Köşeli parantez “BX'in gösterdiği bellek konumu” anlamına gelir. İşlemci fiziksel adresi DS × 10h + BX = 10000h + 0200h = 10200h olarak hesaplar ve bir bellek okuma döngüsü başlatır: adres yolunda 10200h, M/IO' = 1, RD' = 0. Bellek 5Ah'yi veri yoluna koyar, işlemci onu AL'ye yazar.
out 50h, al AL'deki değeri 50h numaralı porta gönderir. Bu bir G/Ç yazma döngüsüdür. Adres yolunda yalnız port numarası bulunur: 0050h. M/IO' = 0 olduğu için bellek yongaları bu döngüyü yok sayar; WR' = 0 ve veri yolunda 5Ah vardır. Port 50h'ye bağlı aygıt değeri alır.
in al, 51h bir G/Ç okuma döngüsüdür: adres 0051h, M/IO' = 0, RD' = 0. Aygıt 3Ch'yi veri yoluna koyar ve AL = 3Ch olur. Son veri komutu mov [bx+1], al belleğe yazar. Etkin adres BX + 1 = 0201h, fiziksel adres 10000h + 0201h = 10201h'dir. Döngüde M/IO' = 1, WR' = 0 ve veri yolunda 3Ch bulunur. ret programı bitirip denetimi işletim sistemine geri verir.
| Komut | AL | Adres yolu | Veri yolu | M/IO' | RD' | WR' |
|---|---|---|---|---|---|---|
mov ax,1000h / mov ds,ax | 00h | — | — | — | — | — |
mov bx,0200h | 00h | — | — | — | — | — |
mov al,[bx] | 5Ah | 10200h | 5Ah (bellekten) | 1 | 0 | 1 |
out 50h,al | 5Ah | 0050h | 5Ah (dışarı) | 0 | 1 | 0 |
in al,51h | 3Ch | 0051h | 3Ch (aygıttan) | 0 | 0 | 1 |
mov [bx+1],al | 3Ch | 10201h | 3Ch (dışarı) | 1 | 1 | 0 |
mov al,[bx]): adres 10200h, M/IO' = 1, RD' = 0. Sağda G/Ç yazma (out 50h,al): adres 0050h, M/IO' = 0, WR' = 0.in al,51h): aygıt 3Ch'yi veri yoluna koyar. Sağda bellek yazma (mov [bx+1],al): 3Ch, 10201h adresine yazılır.Tablo 2.1.4, Şekil 2.1.4 ve Şekil 2.1.5 dört erişimin ortak noktasını gösterir: hepsi aynı adres ve veri hatlarını kullanır. Bellek ile G/Ç'yi M/IO', okuma ile yazmayı RD' ve WR' ayırır. Bellek erişiminde adres yolunda 20 bitlik fiziksel adres, G/Ç erişiminde 16 bitlik port numarası bulunur. Program emu8086'da çalıştırıldığında da AL'nin son değeri 3Ch, 10201h'deki bayt 3Ch ve port 50h'ye yazılan değer 5Ah çıkar.
out 50h, al komutunun 50h adresli bellek hücresine yazdığını düşünmek yanlıştır. Port numarası ile bellek adresi farklı adres uzaylarındadır. M/IO' = 0 olduğu için bellek yongaları bu döngüye hiç yanıt vermez; 00050h'deki bellek baytı değişmez. 8088'de bu sinyalin adı ve kutbu terstir (IO/M'), ama ayrım ilkesi aynıdır.
2.1.3İç yapı: BIU ve EU
Basit bir işlemci her komut için aynı üç adımı sırayla yapar: komutu bellekten getirir, ne yapacağını çözer ve yürütür. Getirme sırasında işlemcinin hesap birimleri boş bekler; yürütme sırasında ise yol boş kalır. 8086 bu boşluğu kapatmak için içini iki bağımsız birime böler. Biri yolla ilgili bütün işleri yapar, öteki komutları yürütür. İki birim aynı anda çalışabildiği için bir komut yürütülürken sonraki komutun baytları getirilebilir.
2.1.3.1İki temel birim
Yol arayüz birimi (BIU, bus interface unit), 8086'nın dış dünyayla bütün iletişimini yürüten birimdir: komutları bellekten getirir, 20 bitlik fiziksel adresi hesaplar, işlenenleri okur ve sonuçları yazar. Yürütme birimi (EU, execution unit) ise komutları çözen ve yürüten birimdir: ALU'yu, genel amaçlı yazmaçları ve bayrakları içerir, dış yollara doğrudan bağlı değildir.
İki birim arasındaki köprü, önden getirme kuyruğudur. BIU bellekten getirdiği komut baytlarını kuyruğun sonuna ekler; EU sıradaki komutun baytlarını kuyruğun başından alır. EU'nun bellekte bir işlenene ihtiyacı olursa, örneğin ADD AX, [BX] yürütülürken, adresin bağıl konumunu hesaplar ve okuma işini BIU'dan ister. BIU yol döngüsünü yapar ve gelen veriyi EU'ya iletir. EU hiçbir zaman adres yoluna kendisi bir şey koymaz.
Bu iş bölümü sayesinde iki birim paralel çalışır. EU bir toplama yaparken BIU sonraki komutun baytlarını getirir. Getirme ile yürütmenin zaman içinde örtüşmesine boru hattı denir. 8086'nın boru hattı yalnız iki aşamalıdır, ama 1978 için önemli bir hız kazancı sağlıyordu.
2.1.3.2Blok diyagram
Şekil 2.1.7 işlemcinin içini iki yarıya ayırır. Sol yarıdaki EU'da en üstte dört genel amaçlı yazmaç durur: AX, BX, CX, DX. Her biri iki 8 bitlik yarıya bölünebilir (AH-AL, BH-BL, CH-CL, DH-DL). Altlarında işaretçi ve indis yazmaçları vardır: SP, BP, SI, DI. Bütün bu yazmaçlar 16 bitlik ALU veri yoluna bağlıdır. ALU, işlenenlerini geçici yazmaçlardan alır; programcı bu geçici yazmaçları göremez. ALU'nun çıkışı veri yoluna geri döner ve sonucu bir yazmaca götürür. Aynı anda işlemin sonucuna göre bayrak yazmacı güncellenir. EU'nun kontrol sistemi kuyruktan gelen işlem kodunu çözer ve bütün bu parçaları sırayla çalıştıran sinyalleri üretir.
Sağ yarıdaki BIU'nun en belirgin parçası adres toplayıcıdır (Σ). Bir kesim yazmacındaki değeri 16 ile çarpar ve bir bağıl konumla toplar; sonuç 20 bitlik fiziksel adrestir ve adres yoluna çıkar. Toplayıcının altında dört kesim yazmacı (CS, DS, SS, ES) ve komut işaretçisi IP bulunur. İç iletişim yazmaçları EU ile BIU arasında taşınan veriyi geçici olarak tutar. Yol kontrol mantığı dış yollara bağlanır ve yol döngülerini yürütür. Bellekten gelen komut baytları 6 baytlık komut kuyruğuna yazılır; EU bu baytları 8 bitlik Q yolu üzerinden alır.
Yazmaçların hangi birimde bulunduğu, görevleri hakkında da bilgi verir. Kesim yazmaçları ve IP BIU'dadır, çünkü ikisi de adres üretmek içindir. Veri üzerinde işlem yapan yazmaçlar ve bayraklar EU'dadır, çünkü yürütmenin parçasıdırlar.
2.1.3.3Bir komutun yolculuğu
İki birimin birlikte nasıl çalıştığını görmek için tek bir komutu, ADD AX, BX'i, bellekten alınmasından sonucun yazılmasına kadar izleyelim.
- BIU, getirilecek komutun fiziksel adresini adres toplayıcıda hesaplar: CS × 10h + IP.
- 20 bitlik adres dış adres yoluna konur; yol kontrol mantığı bir bellek okuma döngüsü başlatır.
- Gelen komut baytları 6 baytlık kuyruğa yazılır. Getirilen bayt sayısı kadar IP ilerler.
- Sıra bu komuta gelince EU, Q yolu üzerinden işlem kodunu alır. Kontrol sistemi komutu çözer: işlem toplama, işlenenler AX ve BX'tir.
- Kontrol sinyalleri AX ve BX'i ALU veri yolundan geçici yazmaçlara, oradan ALU'ya taşır. ALU toplar.
- Sonuç AX'e yazılır; bayraklar (CF, ZF, SF, OF, PF, AF) sonuca göre güncellenir. Bu sırada BIU sonraki baytları getirmeyi sürdürür.
Adımların ilk üçü BIU'da, son üçü EU'da geçer (Şekil 2.1.8, Şekil 2.1.9). Bu sınır, boru hattının temelidir. EU dördüncü adımda kuyruktan bir komut aldığı anda kuyrukta yer açılır. BIU, EU'nun beşinci ve altıncı adımlarını beklemeden yeni bir getirme döngüsüne başlar. ADD AX, BX bellek işleneni kullanmadığı için EU yürütme boyunca yola hiç ihtiyaç duymaz ve yol bütünüyle önden getirmeye ayrılır.
2.1.3.4Yol arayüz birimi (BIU)
BIU'nun görevlerini topluca sıralamak, onun neden ayrı bir birim olduğunu açıklar:
- Bellek ve G/Ç aygıtlarıyla sistem yolu üzerinden arayüz kurar; bütün yol döngülerini o yürütür.
- Kesim yazmacı ve bağıl konumdan 20 bitlik fiziksel adresi adres toplayıcıda üretir.
- Komutları bellekten getirir ve kuyruğa yazar.
- EU'nun istediği işlenenleri bellekten ya da G/Ç'den okur, sonuçları yazar.
- 6 baytlık önden getirme kuyruğunu yönetir; boru hattını bu kuyruk mümkün kılar.
BIU'nun içinde kesim yazmaçları (CS, DS, SS, ES), komut işaretçisi (IP), adres toplayıcı, 6 baytlık komut kuyruğu ve yol kontrol mantığı bulunur. EU bir bellek işleneni istediğinde BIU, o sırada süren getirme döngüsünü bitirir ve ardından EU'nun isteğini yerine getirir. EU'nun isteği önden getirmeden önce gelir; çünkü EU o veri gelmeden ilerleyemez, kuyruk ise biraz bekleyebilir.
2.1.4Önden getirme kuyruğu ve boru hattı
BIU ile EU'nun paralel çalışabilmesi, ikisinin arasında baytları biriktiren bir tampon olmasına bağlıdır. Bu tampon olmasaydı BIU getirdiği baytı EU alana kadar bekletmek zorunda kalırdı. Kuyruk iki birimi birbirinden ayırır: BIU kuyruğu doldurur, EU boşaltır ve her biri kendi hızında çalışır.
2.1.4.1Kuyruğun işleyişi
Önden getirme (prefetch), komut baytlarını yürütülmelerinden önce bellekten alıp bekletmektir. 8086'nın önden getirme kuyruğu (prefetch queue), BIU'nun getirdiği komut baytlarını tutan 6 baytlık bir FIFO (first in, first out, ilk giren ilk çıkar) tampondur: baytlar getirildikleri sırayla tüketilir.
Kuyruğun davranışını dört kural belirler:
- Getirme kuralı. Kuyrukta en az 2 bayt boş yer açıldığında ve EU yolu istemiyorsa BIU sıradaki sözcüğü (2 bayt) getirir. 16 bitlik veri yolu tek döngüde iki bayt taşıdığı için getirme birimi sözcüktür.
- Tüketme kuralı. EU sıradaki komutun baytlarını kuyruğun başından alır. Kuyruk boşsa EU, ilk bayt gelene kadar bekler.
- Dolu kuyruk. Kuyruk doluysa ve EU bir bellek işleneni istemiyorsa BIU boş durur. Bu durumda yol döngüsü yapılmaz.
- Dallanma kuralı. Bir dallanma (JMP, CALL, RET, koşullu atlama, kesme) yürütülünce kuyruk temizlenir. Önden getirilmiş baytlar sıradaki adreslerden gelmiştir; program ise artık başka bir adresten devam eder. BIU yeni adresten getirmeye başlar.
Kuyruğun 6 bayt olması rastgele değildir. 8086 komutları öneksiz olarak 1 ile 6 bayt arasındadır. 6 baytlık bir kuyruk en uzun komutu da tümüyle tutabilir. 8088'in dış veri yolu 8 bit olduğu için bir döngüde yalnız bir bayt gelir; kuyruğu 4 bayttır ve 1 bayt boşalınca getirmeye başlar.
Kuyruğun kazancı, EU'nun çoğu zaman beklemeden komut bulmasıdır. Bellek erişim süresi, EU yürütürken arka planda geçer ve programcıya görünmez. Kaybı ise dallanmada ortaya çıkar: kuyruk boşaltılır, yeniden dolana kadar EU bekler. Döngülerle ve koşullu atlamalarla dolu programlarda bu kayıp önemli bir payı tutar.
2.1.4.2Boru hattı
Boru hattı (pipeline), ardışık komutların farklı aşamalarının aynı anda işlendiği düzendir. 8086'da iki aşama vardır: BIU'daki getirme (G) ve EU'daki çözme ile yürütme (Y). EU bir komutu yürütürken BIU sonraki komutu getirir.
Boru hattının kazancını görmek için basit bir model kullanalım: her getirme 2 zaman birimi, her çözme ile yürütme de 2 zaman birimi sürsün. Gerçekte komutların süreleri farklıdır, ama model fikri açıkça gösterir.
Sıralı düzende (Şekil 2.1.11) her komut 2 + 2 = 4 birim sürer ve n komut 4n birim tutar. Boru hattında (Şekil 2.1.12) ilk getirme 2 birim sürer; ondan sonra her 2 birimde bir komut biter. n komut 2 + 2n birim tutar. Komut sayısı arttıkça oran 4n / (2n + 2) değeri 2'ye yaklaşır: verim yaklaşık iki katına çıkar.
Aynı modelle 5 komutun süresini üç durumda hesaplayalım.
- Boru hattı yok: 5 × (2 + 2) = 20 birim.
- Boru hattı var: 2 + 5 × 2 = 12 birim. G1 0–2, Y1 2–4 (G2 aynı anda), Y2 4–6, Y3 6–8, Y4 8–10, Y5 10–12.
- Üçüncü komut bir JMP: Y3 sırasında (6–8) önden getirilen dördüncü komut yanlış yoldadır ve atılır. Hedef ancak Y3 bitince getirilebilir: G4 8–10, Y4 10–12, Y5 12–14. Toplam 14 birim.
Dallanma, boru hattının kazancından 2 birim geri alır. 100 komutluk bir programda boru hattı 400 birimi 202 birime indirir; her atlama bu sayıya yeniden 2 birim ekler.
Şekil 2.1.13 bu kaybı zaman çizelgesinde gösterir. Modern işlemciler aynı sorunu dallanma tahminiyle hafifletir: atlamanın sonucunu önceden kestirir ve hedeften getirmeye erken başlar. 8086'da böyle bir düzenek yoktur; her alınan dallanma kuyruğu sıfırlar.
2.1.4.3Kuyruk adım adım
Kuyruğun kurallarını bir program üzerinde izlemek, bayt düzeyinde neler olduğunu gösterir. Program CS:0100h'den başlar ve bellekte şu baytları tutar:
0100: B8 34 12 mov ax, 1234h
0103: 01 D8 add ax, bx
0105: 41 inc cx
0106: EB 05 jmp short 010Dh
0108: 90 90 90 90 90 ; beş NOP
010D: B0 ... mov al, ...Her satırın başındaki sayı komutun kod kesimindeki bağıl konumudur. B8 “AX'e 16 bitlik sabit yükle” işlem kodudur ve sabit, düşük baytı önce gelecek biçimde (34 12) ardından gelir. 01 D8, ADD AX, BX'in makine kodudur. 41 tek baytlık INC CX'tir. EB 05 kısa atlamadır: atlamadan sonraki komutun adresine 5 eklenir. 90 hiçbir şey yapmayan NOP komutudur.
| Adım | Kuyruk | EU | Sıradaki komutun IP'si | Olay |
|---|---|---|---|---|
| 1 | (boş) | bekliyor | 0100h | başlangıç ya da dallanma sonrası |
| 2 | B8 34 12 01 D8 41 | MOV AX,1234h çözülüyor | 0100h | BIU üç sözcük getirdi (B8 34, 12 01, D8 41) |
| 3 | 01 D8 41 | MOV AX,1234h | 0103h | EU 3 bayt çekti; 3 boş yer var |
| 4 | 01 D8 41 EB 05 | MOV AX,1234h | 0103h | BIU EB 05'i getirdi; EU beklemedi |
| 5 | 41 EB 05 90 90 | ADD AX,BX | 0105h | EU 01 D8'i aldı; BIU 90 90'ı getirdi |
| 6 | EB 05 90 90 90 90 | INC CX | 0106h | EU 41'i aldı; BIU iki NOP daha getirdi, kuyruk dolu |
| 7 | (temizlendi) | JMP SHORT 010Dh | 010Dh | IP = 0108h + 5 = 010Dh; dört 90 atıldı |
| 8 | B0 | bekliyor | 010Dh | BIU 010Dh'den getirir; tek adres olduğu için önce 1 bayt |
Tablo 2.1.5 birkaç ayrıntıyı ortaya koyar. İkinci adımda EU, kuyruk tümüyle dolmadan çalışmaya başlar; ilk bayt gelince çözme başlayabilir. Üçüncü adımda EU, 3 baytlık komutu kuyruktan çekince 3 boş yer açılır. Kural “en az 2 boş yer” olduğu için BIU hemen bir sözcük getirir. Bundan sonra BIU, EU'nun hep önünde kalır: dördüncü ve altıncı adımlarda EU hiç beklemez.
Yedinci adımda atlama yürütülür (Şekil 2.1.15). Kısa atlamanın uzaklığı, atlamadan sonraki komutun adresine göre hesaplanır. JMP 0106h'de başlayıp iki bayt sürdüğü için sonraki adres 0108h'dir; 0108h + 5 = 010Dh. Kuyrukta bekleyen dört 90 baytı 0108h–010Bh adreslerinden gelmiştir ve artık yürütülmeyecektir. Kuyruk temizlenir. Sekizinci adımda BIU 010Dh'den getirmeye başlar. 010Dh tek bir adrestir; 8086 bir sözcüğü tek döngüde ancak çift adresten okuyabildiği için önce yalnız bir bayt (B0) getirir, sonraki getirmeler yeniden çift adreslerden sözcük sözcük ilerler. EU bu sürede bekler; bedel dallanmanın bedelidir.
ADD AX, BX'in burada 01 D8 olarak kodlandığına dikkat etmek gerekir. 8086'da iki yazmaç arasındaki bir işlem iki biçimde kodlanabilir. 01 işlem kodu “yazmacı r/m alanına ekle”, 03 işlem kodu “r/m alanını yazmaca ekle” anlamındadır. Hedef de kaynak da yazmaç olunca ikisi aynı işi yapar: 01 D8 ile 03 C3 eşdeğerdir. Çoğu assembler, emu8086 da dahil, ikinci biçimi üretir.
2.1.4.4Önden getirme ve çözme işlevleri
Önden getirme ve çözme, işlemci tasarımında iki ayrı işlev olarak ele alınır. Önden getirme işlevi komutları bellekten getirip bir tamponda saklar. Bir program sayacı, getirilecek sonraki baytın adresini tutar. 8086'da bu iş IP ve BIU'nun içindeki bir sayaçla yapılır: IP programcının gördüğü “sıradaki komut” adresidir, BIU'nun sayacı ise kuyruğa girecek sıradaki baytı gösterir. Kuyruk dolu olduğunda bu sayaç IP'nin birkaç bayt önündedir. EU komutları bellek yerine tampondan aldığı için bellek erişim süresi gizlenir ve birim zamanda daha çok komut yürütülür.
Çözme işlevi makine kodunu kontrol sinyallerine ve mikro işlemlere çevirir. Bir işlem kodunun hangi işlemi, hangi işlenenleri ve hangi adresleme modunu istediğini belirler. Yazmaçtan yazmaca, bellekten yazmaca aktarımları ve koşullu atlama, CALL, RET gibi karmaşık komutları adım adım yönlendirir. Çözme de önden getirmeyle paralel çalışır.
8086'da bu işlevler ayrı birimler değildir. Önden getirme BIU'da, çözme EU'nun kontrol sisteminde yapılır. Kontrol sistemi mikrokod tabanlıdır: her makine komutu, yonganın içindeki bir ROM'da saklanan kısa bir mikro işlem dizisine karşılık gelir. Karmaşık bir komut, örneğin bölme, uzun bir mikro işlem dizisi çalıştırır; bu yüzden yüzlerce saat turu sürer. Ayrı önden getirme ve çözme birimleri 80286 ile ortaya çıktı; 80286'da adres hesabı ve komut çözme kendi birimlerine taşındı ve boru hattı dört aşamaya çıktı.
2.1.5Yürütme birimi
EU, komutların gerçekten “yapıldığı” yerdir. Kuyruktan gelen baytları çözer, işlenenleri yazmaçlardan alır, ALU'ya işlem yaptırır ve sonucu geri yazar. Bu kesim EU'nun parçalarını, ALU'nun yaptığı işlemleri ve EU'yu yöneten kontrol birimini anlatır.
2.1.5.1EU'nun bileşenleri
EU'nun başlıca bileşenleri şunlardır:
- Genel amaçlı yazmaçlar (AX, BX, CX, DX): veri saklar, aritmetik ve mantık işlemlerine katılır.
- Aritmetik-mantık birimi (ALU): 8 ve 16 bitlik hesapları yapar.
- İşaretçi ve indis yazmaçları (SP, BP, SI, DI): yığın ve bellek adreslemesinde bağıl konum tutar.
- Komut yazmacı ve komut çözücü: kuyruktan alınan işlem kodunu tutar ve çözer.
- Bayrak yazmacı (FLAGS): son işlemin sonucunu özetleyen durum bitlerini ve işlemcinin davranışını belirleyen kontrol bitlerini tutar.
- Kontrol sistemi: bütün bu parçaları çalıştıran sinyalleri sırasıyla üretir.
2.1.5.2Aritmetik-mantık birimi
Aritmetik-mantık birimi (ALU), iki işlenen üzerinde aritmetik ya da mantıksal bir işlem yapıp sonucu üreten birimdir. 8086'nın ALU'su 8 ve 16 bitlik işlenenlerle çalışır ve her işlemden sonra sonuca göre durum bayraklarını günceller.
ALU'nun yaptığı işler iki gruba ayrılır. Aritmetik işlemler toplama, çıkarma, çarpma, bölme, bir artırma, bir azaltma ve karşılaştırmadır. Mantık işlemleri AND, OR, XOR ve NOT ile bitleri sola ya da sağa kaydırma ve döndürmedir. Karşılaştırma (CMP) aslında bir çıkarmadır; sonucu bir yere yazılmaz, yalnız bayraklar kurulur.
| Komut | İşlem | Boyut |
|---|---|---|
ADD AX, BX | AX ← AX + BX | 16 bit |
SUB AL, 5 | AL ← AL − 5 | 8 bit |
MUL BL | AX ← AL × BL | 8 → 16 bit |
DIV CX | AX ← DX:AX ÷ CX, DX ← kalan | 32 → 16 bit |
AND AL, 0Fh | AL'nin üst 4 biti sıfırlanır | 8 bit |
XOR AX, AX | AX ← 0 (ZF = 1) | 16 bit |
Çarpma ve bölmenin boyut sütunu dikkat ister. İki 8 bitlik sayının çarpımı 16 bite kadar büyüyebilir: 255 × 255 = 65 025. Bu yüzden MUL BL sonucu AL'ye değil, AX'in tamamına yazar. Bölmede tersi geçerlidir: 16 bitlik bir bölme 32 bitlik bir bölünenle başlar. Bölünenin üst yarısı DX'te, alt yarısı AX'tedir ve bu çift DX:AX diye yazılır. Bölüm AX'e, kalan DX'e gider.
Bayraklar ALU'nun her işlemden sonra bıraktığı izdir. Altı durum bayrağı vardır:
- CF (elde bayrağı): işaretsiz işlemde en üst bitten elde ya da ödünç çıktıysa 1.
- ZF (sıfır bayrağı): sonuç sıfırsa 1.
- SF (işaret bayrağı): sonucun en anlamlı biti; işaretli yorumda negatifse 1.
- OF (taşma bayrağı): işaretli işlemin sonucu hedefe sığmadıysa 1.
- PF (eşlik bayrağı): sonucun düşük baytında çift sayıda 1 varsa 1.
- AF (yardımcı elde bayrağı): bit 3'ten bit 4'e elde ya da ödünç olduysa 1.
Bunlara ek olarak programcının kurduğu üç kontrol bayrağı (TF, IF, DF) vardır; bunlar ALU sonucundan etkilenmez. Her komut bütün bayrakları değiştirmez: MOV hiçbirine dokunmaz, INC ve DEC CF'yi korur, MUL ve DIV sonrası bazı bayraklar tanımsızdır. Tanımsız bir bayrak işlemcide 0 ya da 1 olabilir, ama değerine güvenilemez; program ona bakarak karar vermemelidir.
2.1.5.3Kod izleme: ALU ne yapar?
Aşağıdaki program Tablo 2.1.6'daki işlemleri sırayla çalıştırır. Her adımda hangi yazmacın değiştiği ve bayrakların ne olduğu izlenir.
org 100h
mov ax, 0010h
mov bx, 0030h
add ax, bx ; AX ← AX + BX
sub al, 5 ; AL ← AL − 5
mov bl, 4
mul bl ; AX ← AL × BL
mov dx, 0
mov cx, 3
div cx ; AX ← DX:AX ÷ CX
and al, 0Fh ; üst 4 biti sil
xor ax, ax ; AX ← 0
retİlk iki MOV işlenenleri yazmaçlara yükler: AX = 0010h, BX = 0030h. MOV ALU'yu kullanmaz; değer yalnız bir yerden ötekine kopyalanır ve bayraklar değişmez. add ax, bx 16 bitlik toplamadır: 0010h + 0030h = 0040h. Onluk olarak 16 + 48 = 64'tür. En üst bitten elde çıkmaz (CF = 0), sonuç sıfır değildir (ZF = 0), en üst bit 0'dır (SF = 0).
sub al, 5 8 bitlik bir çıkarmadır ve yalnız AL'yi etkiler. AL = 40h'dir; 40h − 05h = 3Bh (64 − 5 = 59). AH değişmez, AX = 003Bh olur. Sonuç işaretsiz olarak sığdığı için ödünç gerekmez ve CF = 0 kalır. Düşük nibble'da 0 − 5 işlemi bit 4'ten ödünç aldığı için AF = 1 olur.
mov bl, 4 yalnız BX'in düşük yarısını değiştirir: BH = 00h zaten 0 olduğu için BX = 0004h olur. mul bl AL ile BL'yi çarpar: 3Bh × 04h = ECh, yani 59 × 4 = 236. Sonuç 16 bit olarak AX'e yazılır: AX = 00ECh. Sonucun üst yarısı (AH) sıfır olduğu için CF = OF = 0 olur; bu iki bayrak “sonuç AL'ye sığdı” bilgisini verir. SF, ZF, AF ve PF ise MUL sonrası tanımsızdır.
Bölmeye hazırlık iki satır sürer. mov dx, 0 bölünenin üst yarısını sıfırlar; böylece DX:AX = 0000 00ECh = 236 olur. mov cx, 3 böleni yükler. div cx 236'yı 3'e böler: bölüm 78 = 004Eh AX'e, kalan 2 = 0002h DX'e yazılır. Sağlama: 78 × 3 + 2 = 236. DIV sonrası altı durum bayrağının hepsi tanımsızdır.
and al, 0Fh bir maskeleme işlemidir. 4Eh = 0100 1110, 0Fh = 0000 1111'dir; AND bitleri tek tek çarpar: 0000 1110 = 0Eh. Maskenin 0 olduğu üst dört bit silinir, 1 olduğu alt dört bit korunur. AND her zaman CF = OF = 0 yapar. Son komut xor ax, ax her biti kendisiyle XOR'lar. Aynı iki bitin XOR'u 0 olduğu için AX = 0000h ve ZF = 1 olur. Bu, mov ax, 0'dan kısa bir sıfırlama yoludur: 33 C0 iki bayt, B8 00 00 üç bayttır. Farkı da vardır: XOR bayrakları değiştirir, MOV değiştirmez.
| Satır | AX | BX | CX | DX | CF | ZF | SF | OF |
|---|---|---|---|---|---|---|---|---|
2–3 mov ax / mov bx | 0010h | 0030h | 0000h | 0000h | 0 | 0 | 0 | 0 |
4 add ax, bx | 0040h | 0030h | 0000h | 0000h | 0 | 0 | 0 | 0 |
5 sub al, 5 | 003Bh | 0030h | 0000h | 0000h | 0 | 0 | 0 | 0 |
6–7 mov bl / mul bl | 00ECh | 0004h | 0000h | 0000h | 0 | ? | ? | 0 |
8–9 mov dx / mov cx | 00ECh | 0004h | 0003h | 0000h | 0 | ? | ? | 0 |
10 div cx | 004Eh | 0004h | 0003h | 0002h | ? | ? | ? | ? |
11 and al, 0Fh | 000Eh | 0004h | 0003h | 0002h | 0 | 0 | 0 | 0 |
12 xor ax, ax | 0000h | 0004h | 0003h | 0002h | 0 | 1 | 0 | 0 |
add ax, bx: 16 bitlik toplama, AX = 0040h. Sağda mul bl: 8 bitlik işlenenlerin 16 bitlik çarpımı, AX = 00ECh; ZF ve SF tanımsız.div cx: DX:AX = 236, bölüm AX = 004Eh, kalan DX = 0002h; bütün durum bayrakları tanımsız. Sağda xor ax, ax: AX = 0000h, ZF = 1.div cx'ten önce DX'i sıfırlamayı unutmak sık görülür. 16 bitlik DIV her zaman DX:AX çiftini böler. DX'te örneğin 0005h kalmışsa bölünen 5 × 65 536 + 236 = 327 916 olur. Bu sayının 3'e bölümü 109 305'tir ve 16 bite sığmaz. İşlemci bu durumda bir bölme hatası kesmesi (INT 0) üretir ve program durur.
Bu komutların süreleri de çok farklıdır. 8086'da ADD AX, BX 3 saat turu sürer. MUL BL 70–77 tur, DIV CX 144–162 tur alır; çünkü mikrokod çarpma ve bölmeyi bit bit kaydırıp toplayarak yapar. 5 MHz'de tek bir 16 bitlik bölme 30 µs'ye yaklaşır. Bölen 2'nin bir kuvvetiyse bölme yerine kaydırma komutları çok daha hızlıdır.
2.1.5.4Komut yazmacı, çözücü ve kontrol birimi
EU'nun içinde, programcının hiç görmediği ama her komutta çalışan üç parça vardır.
- Komut yazmacı: EU kuyruktan işletilecek komutu alır; işlem kodu çözülürken burada geçici olarak tutulur. Programcı bu yazmaca erişemez.
- Komut çözücü: işlem kodunu çözer. Hangi işlemin yapılacağını, işlenenlerin nerede olduğunu ve hangi adresleme modunun kullanıldığını belirler ve bu bilgiyi kontrol devresine gönderir.
- Kontrol birimi: komut ve verinin işlemci içindeki akışını yönetir. Getir–çöz–yürüt döngüsünü sıralar ve diğer bileşenlerin ne zaman ne yapacağını belirler.
Kontrol biriminin görevleri bir döngü olarak özetlenebilir: komutu BIU aracılığıyla getirmek, çözmek, yürütmek, işlemcinin durumunu (yazmaçlar, bayraklar) güncellemek ve her komutun sonunda kesme isteklerini denetlemek. İstek iki hattan gelebilir: INTR'den maskelenebilir (yalnız IF = 1 iken kabul edilir), NMI'dan maskelenemeyen istek. Bir istek varsa işlemci sıradaki komuta geçmeden kesme hizmet programına dallanır. Bazı hata durumları da kesme üretir; sıfıra bölme ya da sığmayan bölüm INT 0'ı tetikler.
8086'nın kontrol birimi mikrokod tabanlıdır. Güç yönetimi gibi özellikler 8086'da yoktur; bunlar çok sonraki işlemcilerle, örneğin 386SL ile gelmiştir. 8086 ya çalışır ya da HLT komutuyla bir kesme gelene kadar durur.
2.1.6Komut uzunlukları ve makine kodu
Bellekte duran bir program, assembly satırları değil, bayt dizisidir. Her komut, işlemcinin çözdüğü bir veya daha çok bayta çevrilir. 8086'da bu bayt sayısı komuttan komuta değişir. Uzunluğu bilmek, kuyruğun ve IP'nin davranışını anlamanın anahtarıdır: IP her komutta tam o komutun uzunluğu kadar ilerler.
2.1.6.1Komut biçimi
Bir 8086 makine komutu şu alanlardan oluşur: işlem kodu (opcode, 1 bayt; hangi işlemin yapılacağını belirtir), varsa ModR/M baytı (işlenenleri ve adresleme modunu belirtir), varsa 8 ya da 16 bitlik yer değiştirme (displacement; bellek adresine eklenen sabit) ve varsa 8 ya da 16 bitlik anlık değer (immediate; komutun içindeki sabit işlenen). Öneksiz bir komut 1 ile 6 bayt arasındadır.
| Komut | Makine kodu | Bayt | Yapı |
|---|---|---|---|
INC CX | 41 | 1 | yalnız işlem kodu |
MOV AX, BX | 8B C3 | 2 | işlem kodu + ModR/M |
ADD AL, 7Ch | 04 7C | 2 | AL'ye özel kısa kod + 8 bitlik anlık |
MOV BX, 4050h | BB 50 40 | 3 | işlem kodu + 16 bitlik anlık |
MOV WORD PTR [BX+1234h], 5678h | C7 87 34 12 78 56 | 6 | işlem kodu + ModR/M + 16 bitlik yer değiştirme + 16 bitlik anlık |
Tablo 2.1.8'daki en kısa komut INC CX'tir. 8086'da 16 bitlik bir yazmacı bir artıran komutların işlem kodu 40h'den başlar ve yazmaç numarası işlem koduna eklenir: AX için 40, CX için 41, DX için 42, BX için 43. Yazmaç işlem kodunun içinde olduğu için ayrı bir bayt gerekmez. Benzer biçimde MOV BX, 4050h'de BB işlem kodu “BX'e 16 bitlik sabit yükle” anlamına gelir (B8 + 3, BX'in numarası). Sabit ardından gelir.
Anlık değerler belleğe little-endian düzende yazılır: önce düşük bayt, sonra yüksek bayt. 4050h, bellekte 50 40 sırasıyla durur. Aynı kural yer değiştirmeler için de geçerlidir: 1234h yer değiştirmesi 34 12, 5678h anlık değeri 78 56 olarak yazılır.
ADD AL, 7Ch için 8086'nın AL ve AX'e ayrılmış kısa kodlarından biri kullanılır. Genel biçim 80 C0 7C diye üç bayt sürerdi; AL'ye özel 04 işlem kodu ModR/M baytına gerek bırakmaz ve komut iki bayta iner. Akümülatörün (AX/AL) bu ayrıcalığı, sık yapılan işlemleri kısaltmak içindir.
İşlenenlerden biri genel bir yazmaç ya da bellek olduğunda ModR/M baytı devreye girer. Bu bayt üç alana bölünür:
ModR/M = mod (2 bit) · reg (3 bit) · r/m (3 bit)
- mod r/m alanının nasıl yorumlanacağını söyler: 11 ise r/m bir yazmaçtır; 00, 01, 10 ise bellek işlenenidir ve sırasıyla yer değiştirme yok, 8 bitlik ya da 16 bitlik yer değiştirme vardır.
- reg işlenenlerden birinin yazmacını verir: 000 AX, 001 CX, 010 DX, 011 BX, 100 SP, 101 BP, 110 SI, 111 DI (8 bitlik komutlarda AL, CL, DL, BL, AH, CH, DH, BH).
- r/m mod = 11 ise ikinci yazmacı, değilse adres biçimini verir: 000 [BX+SI], 001 [BX+DI], 010 [BP+SI], 011 [BP+DI], 100 [SI], 101 [DI], 110 [BP] (mod = 00 iken doğrudan adres), 111 [BX].
İki ModR/M baytını çözelim.
8B C3: 8B işlem kodu “r/m16'yı reg16'ya taşı” (MOV r16, r/m16) anlamındadır. C3h = 1100 0011 = 11 000 011. mod = 11 (yazmaç), reg = 000 (AX), r/m = 011 (BX). KomutMOV AX, BX'tir.C7 87 …: C7 işlem kodu “r/m16'ya 16 bitlik sabit yaz” anlamındadır; reg alanı burada yazmaç değil, işlemin alt türüdür ve 000 olmalıdır. 87h = 1000 0111 = 10 000 111. mod = 10 (16 bitlik yer değiştirme), r/m = 111 ([BX]). Ardından yer değiştirme34 12= 1234h ve anlık değer78 56= 5678h gelir. KomutMOV WORD PTR [BX+1234h], 5678h'tir.
Aynı mantıkla 89 D8 çözülürse: 89 “reg16'yı r/m16'ya taşı”, D8h = 11 011 000, reg = BX, r/m = AX. Bu da MOV AX, BX'tir. Yazmaçtan yazmaca bir MOV'un iki eşdeğer kodlaması vardır.
2.1.6.2Kod izleme: baytlar ve IP
Aşağıdaki program Tablo 2.1.8'daki komutları sırayla çalıştırır. İzlemenin amacı, her komutun bellekte kaç bayt tuttuğunu ve IP'nin buna göre nasıl ilerlediğini görmektir.
org 100h
inc cx
mov bx, 4050h
mov ax, bx
add al, 7Ch
mov word ptr [bx+1234h], 5678h
retProgram 0100h'den başlar ve kod kesiminin 0100h–010Eh aralığını, toplam 15 baytı kaplar: 41 BB 50 40 8B C3 04 7C C7 87 34 12 78 56 C3. inc cx yalnız işlem kodundan oluşur; CX = 1 olur ve IP 0101h'ye ilerler. mov bx, 4050h üç bayttır (BB 50 40); IP = 0104h. mov ax, bx iki bayttır (8B C3); AX = 4050h, IP = 0106h.
add al, 7Ch AL'ye özel kısa koddur (04 7C). AL = 50h + 7Ch = CCh olur; onluk olarak 80 + 124 = 204. AH değişmediği için AX = 40CCh'dir. IP = 0108h. Altı baytlık mov word ptr [bx+1234h], 5678h etkin adresi BX + 1234h = 4050h + 1234h = 5284h olarak hesaplar ve oraya 5678h yazar. Bellekte DS:5284h'de 78, DS:5285h'te 56 durur. IP = 010Eh. Son komut ret tek bayttır (C3).
| Komut | Bayt | Uzunluk | IP | CX | BX | AX | Bellek |
|---|---|---|---|---|---|---|---|
inc cx | 41 | 1 | 0101h | 0001h | 0000h | 0000h | — |
mov bx, 4050h | BB 50 40 | 3 | 0104h | 0001h | 4050h | 0000h | — |
mov ax, bx | 8B C3 | 2 | 0106h | 0001h | 4050h | 4050h | — |
add al, 7Ch | 04 7C | 2 | 0108h | 0001h | 4050h | 40CCh | — |
mov word ptr [bx+1234h], 5678h | C7 87 34 12 78 56 | 6 | 010Eh | 0001h | 4050h | 40CCh | DS:5284h = 78, DS:5285h = 56 |
ret | C3 | 1 | 0000h | 0001h | 4050h | 40CCh | — |
mov bx, 4050h: 3 bayt, IP 0101h'den 0104h'ye. Sağda altı baytlık mov word ptr [bx+1234h], 5678h: IP 0108h'den 010Eh'ye; 5678h, DS:5284h'ye little-endian yazılır.Tablo 2.1.9'nin IP sütunu, her komutun uzunluğunun bir önceki IP'ye eklenmesiyle elde edilir: 0100h + 1 = 0101h, + 3 = 0104h, + 2 = 0106h, + 2 = 0108h, + 6 = 010Eh. Son satırda ise IP 0000h olur. RET bir dallanmadır: IP'ye ardışık bir değer değil, yığının tepesindeki sözcüğü yükler. .COM programı başlarken DOS yığına 0000h koyar; kesimin 0000h bağıl konumunda programın önündeki 256 baytlık PSP başlığı vardır ve onun ilk komutu programı sonlandırır. Böylece RET denetimi işletim sistemine geri verir.
Altı komut 15 bayt tuttu: uzunluklar 1 ile 6 bayt arasında değişti. Kuyruğun 6 bayt olması bu yüzden yeterlidir. emu8086'nın ürettiği makine kodu listesi ve izleme, tablodaki baytları ve değerleri birebir verir.
Makine kodunu okurken BB 50 40'ı “BX'e 5040h yükle” diye yorumlamak yanlıştır. 8086 little-endian'dır: ilk gelen bayt düşük bayttır. Doğru okuma 4050h'dir. Aynı hata bellek dökümlerinde de yapılır: DS:5284h'den başlayan 78 56 baytları sözcük olarak 5678h'dir.
2.1.7Yazmaç kümesi
Bir assembly programcısının elindeki en önemli araç yazmaçlardır. Her komut ya bir yazmaçtan okur, ya bir yazmaca yazar, ya da bir yazmacın gösterdiği bellek konumuna erişir. Bu kesim 8086'nın yazmaçlarını gruplarına ayırır ve sözcük boyunun anlamını açıklar. Adres üretiminde rol oynayan iki grup, kesim yazmaçları ve IP, ayrıntılı ele alınır.
2.1.7.114 yazmaç
Yazmaç (register), işlemcinin içinde bulunan, çok hızlı, küçük bir bellek hücresidir. Bir işlemcinin programcıya sunduğu yazmaçların tümüne yazmaç kümesi (register set) denir. 8086'nın yazmaç kümesinde 16 bitlik 14 yazmaç vardır.
Şekil 2.1.20 yazmaçları dört gruba ayırır: 4 + 4 + 4 + 2 = 14.
- Genel amaçlı yazmaçlar (AX, BX, CX, DX) veri saklar ve aritmetik ile mantık işlemlerine katılır. Her biri 8 bitlik iki yarıya bölünebilir: AX'in yüksek yarısı AH, düşük yarısı AL'dir. AX'e akümülatör denir; çarpma, bölme ve G/Ç komutları onu kullanır. BX taban yazmacıdır ve bellek adreslemede bağıl konum tutabilir. CX sayaçtır; döngü ve yineleme komutları onu azaltır. DX veri yazmacıdır; çarpma ve bölmede AX'in üst yarısı olur, G/Ç'de port numarasını tutar.
- İşaretçi ve indis yazmaçları (SP, BP, SI, DI) bellekteki konumları gösterir. SP yığın işaretçisidir; yığının tepesinin bağıl konumunu tutar. BP taban işaretçisidir; yığındaki parametre ve yerel değişkenlere erişir. SI kaynak indisi, DI hedef indisidir; dizi ve dizgi işlemlerinde kullanılır. Bu yazmaçlar ikiye bölünemez.
- Kesim yazmaçları (CS, DS, SS, ES) bellekteki dört etkin kesimin başlangıcını gösterir.
- Özel yazmaçlar: IP sıradaki komutu, FLAGS son işlemin sonucunu ve işlemcinin kontrol bitlerini gösterir.
Genel amaçlı yazmaçların ikiye bölünebilmesi önemli bir ayrıntıdır. AL'ye yazılan bir değer AX'in düşük baytını değiştirir, AH'yi değiştirmez. Önceki kod izlemelerinde bu davranış görüldü: sub al, 5 yalnız AL'yi, mov bl, 4 yalnız BL'yi değiştirdi. Yazmaç adları da bu yapıyı anlatır: H yüksek (high), L düşük (low) baytı gösterir.
2.1.7.2Sözcük boyu
8086, 16 bitlik bir tamsayı işlemcisidir. Her komut tek bir veri öğesi üzerinde çalışır; aynı anda birden çok veriyi işleyen vektör komutları yoktur. Kayan noktalı sayılarla hesap da donanımda yoktur; bu iş için ayrı bir yardımcı işlemci, 8087, sisteme eklenebilir. 8087 yoksa kayan nokta işlemleri yazılımla, tamsayı komutlarından kurulan uzun alt programlarla yapılır.
Yonga içindeki yazmaçların genişliği, işlemcinin aynı anda üzerinde çalışabileceği veri miktarını, yani sözcük boyunu belirler. 8086'da sözcük 16 bittir. Bu genişlik değer aralıklarını da belirler:
| Genişlik | Örnek | İşaretsiz aralık | İşaretli aralık |
|---|---|---|---|
| 8 bit | AL, BH | 0 … 255 (FFh) | −128 … +127 |
| 16 bit | AX, SI | 0 … 65 535 (FFFFh) | −32 768 … +32 767 |
| 32 bit | DX:AX | 0 … 4 294 967 295 | −2 147 483 648 … +2 147 483 647 |
32 bitlik bir değer tek bir yazmaca sığmaz; DX:AX gibi iki yazmaçlık bir çiftte tutulur. Çarpma ve bölme bu çifti kendiliğinden kullanır. Toplama ve çıkarmada ise iki adımla yapılır: önce düşük sözcükler ADD ile, sonra yüksek sözcükler elde ile birlikte ADC ile toplanır.
Yazmaçlar işlemcinin içindeki en hızlı depolama alanıdır. Bir yazmaca erişmek için yol döngüsü gerekmez; değer iç veri yolunda hemen hazırdır. Belleğe erişim ise en az bir yol döngüsü, yani en az dört saat turu ister. Bu fark, iyi bir assembly programında sık kullanılan değerlerin yazmaçlarda tutulmasının nedenidir.
2.1.7.3Kesim yazmaçları
Kesim (segment), 8086 belleğinde 16 baytlık bir sınırda başlayan ve en çok 64 KB uzunluğunda olan bellek bloğudur. Kesim yazmacı (segment register), bir kesimin başlangıç adresinin 16'ya bölümünü tutar; kesimin fiziksel başlangıcı, yani kesim tabanı, yazmaçtaki değerin 10h ile çarpımıdır.
Kesimler bellektedir; kesim yazmaçları işlemcinin içindedir. Bu ayrım önemlidir: kesim yazmacı bir bellek bölgesini “gösterir”, o bölgeyi içermez. Yazmaç değiştirilince gösterilen bölge kayar, ama bellekteki baytlar yerinde kalır. Dört kesim yazmacının her birinin belirli bir görevi vardır:
| Yazmaç | Adı | Gösterdiği kesim | Birlikte kullanıldığı bağıl konum |
|---|---|---|---|
| CS | kod kesimi (code segment) | programın komutları | IP (CS:IP sıradaki komut) |
| DS | veri kesimi (data segment) | değişkenler ve veriler | BX, SI, DI, doğrudan adres |
| SS | yığın kesimi (stack segment) | yığın | SP, BP (SS:SP, SS:BP) |
| ES | ek kesim (extra segment) | ek veri; dizgi hedefi | DI (ES:DI) |
Kesim yazmaçlarının kullanımında üç kural vardır. Bu kurallar, kesim yazmaçlarının ALU'ya değil BIU'ya bağlı olmasından ve komut kodlamasında onlara ayrılan yerin dar olmasından gelir.
- Anlık değer yüklenemez.
MOV DS, 2000hgeçersizdir; 8086'nın komut kümesinde kesim yazmacına sabit yükleyen bir işlem kodu yoktur. Değer önce genel bir yazmaçtan geçer:MOV AX, 2000h, ardındanMOV DS, AX. Değer bellekten de alınabilir:MOV DS, [BX]geçerlidir. - CS, MOV ile değiştirilmez. CS değişince bir sonraki komut başka bir yerden alınır; bu bir dallanmadır. CS yalnız uzak JMP, uzak CALL, RETF, INT ve IRET ile değişir; bu komutlar IP'yi de aynı anda ayarlar. Assembler
MOV CS, AXsatırını kabul etmez. - Kesimden kesime doğrudan MOV yoktur.
MOV ES, DSgeçersizdir. Değer ya genel bir yazmaçtan (MOV AX, DS/MOV ES, AX) ya da yığından (PUSH DS/POP ES) geçer.
Veri kesimini ayarlamak için MOV DS, 1000h yazmak derlenmez. Assembler bu satırda hata verir. Doğru yazım iki satırdır: MOV AX, 1000h ve MOV DS, AX. Bu kalıp, bütün kesim ayarlamalarında görülür ve kod izlemelerinin hepsinde kesim yazmaçlarına değerin AX üzerinden gitmesinin nedenidir.
2.1.7.4Komut işaretçisi (IP)
Komut işaretçisi (IP, instruction pointer), kod kesiminde yürütülecek sonraki komutun bağıl konumunu tutan 16 bitlik yazmaçtır. Sonraki komutun fiziksel adresi CS × 10h + IP'dir.
IP her komut getirildikçe ilerler; bir komut yürütüldüğünde IP o komutun uzunluğu kadar artmış olur. Komut uzunlukları izlemesinde bu davranış görüldü: 1 baytlık INC CX IP'yi 1, 6 baytlık MOV 6 artırdı. Dallanma komutları ise (JMP, koşullu atlamalar, CALL, RET, LOOP, INT) IP'ye ardışık olmayan yeni bir değer yükler. Programın akışı bu değerle değişir.
Programcı IP'yi doğrudan okuyamaz ve yazamaz; MOV IP, … diye bir komut yoktur. IP'yi değiştirmenin tek yolu dallanmadır. IP'nin değerini öğrenmek için ise küçük bir hile kullanılır: CALL komutu dönüş adresini, yani sonraki komutun IP'sini yığına iter; hemen ardından POP ile bu değer bir yazmaca alınabilir.
CS = 4321h ve IP = 1000h ise sonraki komut hangi fiziksel adrestedir?
- CS × 10h: onaltılık bir sayıyı 10h ile çarpmak, sağına bir 0 eklemektir. 4321h × 10h = 43210h.
- IP'yi sağa hizalayarak ekle: 43210h + 01000h.
- Basamaklar sağdan toplanır: 0 + 0 = 0, 1 + 0 = 1, 2 + 0 = 2, 3 + 1 = 4, 4 + 0 = 4. Sonuç 44210h; elde oluşmadı.
Sonraki komut 44210h fiziksel adresindedir. Bu adres 20 bittir ve doğrudan adres yoluna çıkar.
2.1.8Kesimli bellek
8086'yı öteki birçok işlemciden ayıran özellik, belleği kesimler üzerinden adreslemesidir. Bir programcı hiçbir zaman 20 bitlik bir adresi doğrudan yazmaz; her bellek erişimi bir kesim yazmacı ile bir bağıl konumun birleşiminden doğar. Bu kesim, bu birleşimin nasıl yapıldığını, aynı baytın neden birçok adla anılabildiğini, 1 MB sınırında ne olduğunu ve hangi erişimin hangi kesimi kullandığını anlatır.
2.1.8.1Mantıksal ve fiziksel adres
8086 belleği kesimli (segmented) olarak adresler. Her bellek adresi iki 16 bitlik parçayla verilir: kesim ve bağıl konum. Yazılışta iki parça iki nokta üst üste ile ayrılır: 2000h:0010h. Kesim yazmacı kesimin başlangıcını gösterir; bağıl konum istenen baytın kesimin başından itibaren uzaklığıdır ve 0000h ile FFFFh arasında değişir. İki parça BIU'daki adres toplayıcıda birleştirilerek 20 bitlik fiziksel adres elde edilir.
Mantıksal adres, programın kullandığı kesim:bağıl konum çiftidir. Fiziksel adres (FA), adres yoluna çıkan gerçek 20 bitlik adrestir ve şöyle hesaplanır:
FA = kesim × 10h + bağıl konum
Toplam 20 biti aşarsa 8086 yalnız alt 20 biti kullanır.
10h ile çarpma, ikili sayıda 4 bit sola kaydırmaya eşittir; donanımda bir çarpıcıya gerek yoktur. Kesim değerinin bitleri toplayıcının girişine dört konum kaydırılmış olarak bağlanır ve sağdan dört 0 eklenir. Böylece 16 bitlik kesim değeri 20 bitlik bir tabana dönüşür. Bağıl konum ise kaydırılmadan, sağa hizalı olarak eklenir. Şekil 2.1.21 bu düzeni gösterir.
Kaydırmanın sonucunda kesim tabanının son onaltılık basamağı her zaman 0'dır. Kesim tabanları bu yüzden 16'nın katlarıdır. Bellekte 16 baytlık bu sınırlara paragraf denir. Bir kesim yazmacının alabileceği 65 536 değerin her biri bir paragraf sınırını gösterir: 1 048 576 / 16 = 65 536.
2.1.8.2Fiziksel adres hesabı adım adım
Hesap her zaman üç adımda yapılır: kesim değerinin sağına bir 0 eklenir, bağıl konum sağa hizalanarak altına yazılır ve iki sayı onaltılık olarak toplanır.
Kesim yazmacı 1000h, bağıl konum F000h olsun.
- Kesim tabanı: 1000h × 10h = 10000h.
- Bağıl konum F000h, yani 0F000h.
- Toplam: 10000h + 0F000h = 1F000h.
Bağıl konum en çok FFFFh olabildiği için bu kesim 10000h–1FFFFh aralığını kapsar. Aralığın uzunluğu 10000h bayt, yani 64 KB'tır.
CS = F000h ve IP = FFF0h ise komutun fiziksel adresi nedir?
- F000h × 10h = F0000h.
- IP = FFF0h sağa hizalanır: 0FFF0h.
- F0000h + 0FFF0h = FFFF0h.
FFFF0h, 1 MB'ın son 16 baytının başıdır. 8086 sıfırlandığında CS = FFFFh ve IP = 0000h yükler: FFFF0h + 0000h = FFFF0h. Farklı iki çift aynı baytı gösterir; işlemci ilk komutunu her durumda buradan alır. Bilgisayarlarda bu adres BIOS ROM'undadır ve orada BIOS'un başlangıç koduna uzak bir atlama bulunur.
İki hata sık görülür. Birincisi kesim değerini 10h ile çarpmayı unutup 4321h + 1000h = 5321h bulmaktır; bu 16 bitlik bir sayıdır ve fiziksel adres olamaz. İkincisi kaydırmayı yanlış parçaya uygulamaktır: bağıl konumu kaydırıp 4321h + 10000h = 14321h bulmak. Kural tektir: kesim kaydırılır, bağıl konum olduğu gibi eklenir.
2.1.8.3Fiziksel adres hesaplayıcı
Sunumdaki etkileşimli hesaplayıcı ve Kesim:Bağıl Konum Hesaplayıcı simülatörü, girilen herhangi bir kesim ve bağıl konum için aynı üç satırı üretir: kesim, kesim × 10h ve toplam. Ayrıca 1 MB'lık bellek haritası üzerinde kesimin 64 KB'lık aralığını ve fiziksel adresin konumunu çizer, adresin normalleştirilmiş yazımını verir. Örneğin 4321h:1000h için kesim aralığı 43210h–5320Fh, fiziksel adres 44210h ve normalleştirilmiş yazım 4421h:0000h'dir. Toplam 1 MB'ı aşarsa hesaplayıcı 21. biti atar ve sonucun başa sardığını gösterir.
2.1.8.4Bellek kesimleme
20 bitlik adres yolu 1 MB'ı adresler; bir kesim ise en fazla 64 KB'tır, çünkü bağıl konum 16 bittir. Herhangi bir anda dört kesim etkindir: CS, DS, SS ve ES'nin gösterdikleri. Kesim yazmaçları değiştirilmeden en çok 4 × 64 KB = 256 KB'a doğrudan erişilebilir. Belleğin başka bir bölgesine erişmek için bir kesim yazmacına yeni değer yüklenir.
Kesimler belleği sabit 16 parçaya bölmez. 1 MB / 64 KB = 16 yalnız bir hesaptır; 8086'da kesim başlangıçları sabit değildir. Bir kesim her paragraf sınırında başlayabilir; 65 536 olası başlangıç vardır. Bu yüzden kesimler ayrık olabileceği gibi çakışabilir de. Şekil 2.1.24'de ES = 2800h kesimi 28000h'de başlar ve 37FFFh'de biter. Bu aralığın ilk yarısı DS kesiminin ikinci yarısıyla (28000h–2FFFFh), ikinci yarısı SS kesiminin ilk yarısıyla (30000h–37FFFh) aynı baytlardır. Aynı bayta hem DS hem ES üzerinden, farklı bağıl konumlarla erişilebilir: fiziksel 2A000h, DS:A000h ile de ES:2000h ile de okunur.
ES = 2800h kesiminin aralığını bulalım ve 30010h adresine ES ile erişilip erişilemeyeceğine bakalım.
- Kesim tabanı: 2800h × 10h = 28000h.
- Son bayt: 28000h + FFFFh = 37FFFh.
- 30010h bu aralıktadır. Bağıl konum: 30010h − 28000h = 8010h. FFFFh'den küçük olduğu için geçerlidir:
ES:8010h.
Aynı bayt SS = 3000h ile SS:0010h olarak da yazılır. DS = 2000h ile ise erişilemez: 30010h − 20000h = 10010h, 16 bite sığmaz.
2.1.8.5Neden kesimleme?
Kesimleme, 16 bitlik bir işlemcide 1 MB adreslemenin ucuz bir yoluydu. Ama getirdiği kolaylıkların yanında yükleri de vardır.
| Artıları | Eksileri |
|---|---|
| 16 bitlik yazmaçlarla 20 bitlik (1 MB) bellek adreslenir. | Tek bir dizi ya da yapı 64 KB'ı aşamaz; aşarsa kesim değiştirmek gerekir. |
| Kod, veri ve yığın birbirinden ayrılır; program düzeni netleşir. | Aynı fiziksel adresin birçok kesim:bağıl konum yazımı vardır; işaretçi karşılaştırması zorlaşır. |
| Yeniden konumlanabilirlik: yalnız kesim yazmaçları değiştirilerek program bellekte başka yere yüklenebilir. | Kesimler arasında koruma yoktur; hatalı bir yazma başka bir kesimi bozabilir. |
| Komutlar kısa kalır: çoğu adres 16 bitlik bağıl konumla yazılır. | Adres hesabı programcıya ek bir zihinsel yük getirir. |
Yeniden konumlanabilirlik özellikle değerlidir. Bir .COM programı içindeki bütün adresleri kesim başından itibaren bağıl konumla kullanır. İşletim sistemi programı hangi paragrafa yüklerse yüklesin, CS, DS, ES ve SS'yi o paragrafa ayarlaması yeter; programın hiçbir baytını değiştirmeye gerek kalmaz. emu8086 .COM programlarını 0700h kesimine yükler: CS = DS = ES = SS = 0700h ve program 0700h:0100h'den başlar.
Eksiler ise zamanla ağırlaştı. 64 KB'tan büyük veri yapıları için programcılar kesimleri elle değiştirmek zorunda kaldı; derleyiciler “yakın” ve “uzak” işaretçi türleri tanımladı. Koruma eksikliği çok görevli işletim sistemlerini zorlaştırdı. 80286'nın korumalı modu ve 80386'nın 32 bitlik düz adres alanı bu sorunları çözmek için geldi.
2.1.8.6Aynı adres, farklı yazımlar
Kesimler çakışabildiği için bir fiziksel adres tek bir mantıksal adresle gösterilmez. Kesim bir paragraf artırılırsa taban 16 bayt ilerler; bağıl konum 16 azaltılırsa toplam değişmez. Tablo 2.1.13 bunu sayılarla gösterir.
| Mantıksal adres | Hesap | Fiziksel adres |
|---|---|---|
1234h:0005h | 12340h + 0005h | 12345h |
1000h:2345h | 10000h + 2345h | 12345h |
1200h:0345h | 12000h + 0345h | 12345h |
0234h:FFF5h | 02340h + FFF5h | 12335h (12345h değil) |
FFFFh:0010h | FFFF0h + 0010h = 100000h | 00000h (8086'da 20 bite sarar) |
İlk üç satır aynı baytı gösterir. Dördüncü satır yanıltıcıdır: kesim 0234h, 1234h'den 1000h küçüktür, yani taban 10000h bayt geridedir. Aynı bayta ulaşmak için bağıl konumun 10005h olması gerekirdi, ama bu 16 bite sığmaz. FFF5h ile 16 bayt geride kalınır. Son satırda toplam 1 MB'ı aşar ve 20 bite sarar.
Normalleştirilmiş adres, bağıl konumu 0h–Fh arasında olan mantıksal adrestir. Beş basamaklı fiziksel adresin ilk dört basamağı kesimi, son basamağı bağıl konumu verir: 12345h → 1234h:0005h.
Bir fiziksel adresin en çok 4096 farklı yazımı vardır. Bağıl konum 16'şar azaltılırken kesim birer artırılır; bağıl konum 0000h–FFFFh aralığında kaldığı sürece her adım geçerli bir yazım verir. Bağıl konumun son basamağı sabit kaldığı için seçilebilecek değer sayısı 65 536 / 16 = 4096'dır. 12345h için yazımlar 0235h:FFF5h'den 1234h:0005h'ye kadar uzanır: 1234h − 0235h + 1 = 1000h = 4096. Belleğin en başına yakın adreslerde yazım sayısı daha azdır; çünkü kesim 0'ın altına inemez.
3A2C5h fiziksel adresini normalleştirelim ve DS = 3000h ise gereken bağıl konumu bulalım.
- İlk dört basamak kesim, son basamak bağıl konum:
3A2Ch:0005h. Sağlama: 3A2C0h + 5h = 3A2C5h. - DS = 3000h ise kesim tabanı 30000h'dir. Bağıl konum = 3A2C5h − 30000h = A2C5h.
- A2C5h ≤ FFFFh olduğu için geçerlidir:
3000h:A2C5h.
Aynı soru CS = 2F00h ve IP = 01A4h için tersinden sorulabilir: FA = 2F000h + 01A4h = 2F1A4h; normalleştirilmiş yazım 2F1Ah:0004h'tür. emu8086'da 2F00h:01A4h adresine yazılan bir bayt, ES = 2F1Ah iken ES:[0004h] ile aynen okunur.
2.1.8.7Kod izleme: 1 MB sınırında adres başa sarar
Kesim × 10h + bağıl konum toplamı FFFFFh'yi aşabilir: en büyük durum FFFF0h + FFFFh = 10FFEFh'dir ve 21 bit tutar. 8086'nın yalnız 20 adres hattı (A19–A0) vardır. 21. bit adres yoluna çıkmaz, yani atılır. Sonuç olarak adres belleğin başına sarar. Aşağıdaki program bu davranışı gösterir.
org 100h
mov ax, 0
mov ds, ax
mov byte ptr [0500h], 77h
mov ax, 0FFFFh
mov ds, ax
mov bl, [0510h] ; FFFF:0510
retİlk iki komut DS = 0000h yapar; kesim belleğin en başındadır. mov byte ptr [0500h], 77h 0000h:0500h adresine, yani fiziksel 00500h'ye 77h yazar. byte ptr belirteci yazılacak verinin bir bayt olduğunu bildirir; sabit 77h tek başına bunu belirlemez. Ardından DS = FFFFh yapılır. Bu kesimin tabanı FFFF0h'dir, yani 1 MB'ın son 16 baytı. mov bl, [0510h] fiziksel adresi FFFF0h + 0510h = 100500h olarak hesaplar. Bu sayı 21 bittir. 8086'nın 20 adres hattı yalnız 00500h'yi taşır ve işlemci, ilk adımda 77h yazılan baytın aynısını okur: BL = 77h.
| Satır | DS | BL | Hesap | 00500h'deki bayt |
|---|---|---|---|---|
2–3 mov ax,0 / mov ds,ax | 0000h | 00h | — | 00h |
4 mov byte ptr [0500h], 77h | 0000h | 00h | 00000h + 0500h = 00500h | 77h |
5–6 mov ax,0FFFFh / mov ds,ax | FFFFh | 00h | taban FFFF0h | 77h |
7 mov bl, [0510h] | FFFFh | 77h | FFFF0h + 0510h = 100500h → 00500h | 77h |
mov bl, [0510h]: FFFF0h + 0510h = 100500h. 21. bit atılır, adres 00500h'ye sarar ve BL = 77h olur.Bu kural, FFFFh kesiminde FFFFh:0010h'den FFFFh:FFFFh'ye kadarki bütün adreslerin belleğin başındaki 00000h–0FFEFh bölgesine düştüğü anlamına gelir. Sarma, 8086'da bir hata değil, 20 bitlik adres yolunun doğal sonucudur. Bazı eski programlar bu davranışa güvenerek yazıldı.
Durum 80286 ile değişti. 80286'nın 24 adres hattı vardır ve gerçek modda bile 21. hat (A20) açık olabilir. Bu durumda FFFFh:0510h gerçekten 100500h'ye, 1 MB'ın hemen üstüne ulaşır. Eski programlarla uyumu korumak için IBM PC/AT bilgisayarlarında A20 hattını kapatıp açan bir devre eklendi. A20 açıkken FFFFh kesimiyle 1 MB'ın üstündeki 65 520 bayta (FFFF0h + FFFFh − FFFFFh = FFF0h) gerçek modda erişilebilir.
FFFFh:0510h için 100500h'yi fiziksel adres olarak yazmak 8086'da yanlıştır; bu sayı 20 bite sığmaz. Toplam 1 MB'ı aşarsa en üst bit atılır ve 100000h çıkarılır: 100500h → 00500h. Aynı kontrol her fiziksel adres hesabının sonunda yapılmalıdır.
2.1.8.8Varsayılan kesimler ve kesim öneki
Bir komut yalnız bağıl konum yazdığında, örneğin mov al, [bx], hangi kesim yazmacının kullanılacağına işlemci kendisi karar verir. Bu karar erişimin türüne ve adres hesabında kullanılan yazmaca bağlıdır.
Varsayılan kesim (default segment), bir bellek erişiminde kesim belirtilmemişse işlemcinin kullandığı kesimdir. Kesim öneki (segment override prefix), komutun başına eklenen ve varsayılan kesim yerine başka bir kesim yazmacını seçtiren bir baytlık önektir: ES için 26h, CS için 2Eh, SS için 36h, DS için 3Eh.
| Erişim türü | Kesim | Bağıl konum kaynağı | Önekle değiştirilebilir mi? |
|---|---|---|---|
| Komut getirme | CS | IP | hayır |
| Yığın işlemleri (PUSH, POP, CALL, RET) | SS | SP | hayır |
BP ile adresleme [BP+…] | SS | etkin adres | evet: DS:[BP] |
Genel veri [BX], [SI], [DI], [1234h] | DS | etkin adres | evet: ES:[BX] |
| Dizgi kaynağı (MOVSB, LODSB) | DS | SI | evet |
| Dizgi hedefi (MOVSB, STOSB) | ES | DI | hayır |
Tablo 2.1.15'daki kuralların mantığı yazmaçların görevinden gelir. Komutlar her zaman kod kesimindedir. Yığın her zaman yığın kesimindedir. BP yığındaki parametrelere ve yerel değişkenlere erişmek için tasarlandığından, BP içeren her adres varsayılan olarak SS'yi kullanır: [BP], [BP+SI], [BP+DI+4]. Geri kalan bütün veri erişimleri DS'yi kullanır. Dizgi komutları kaynağı DS:SI'den okur, hedefe ES:DI üzerinden yazar; böylece iki farklı kesim arasında blok kopyalanabilir.
Varsayılanı değiştirmek için kesim öneki yazılır: MOV AL, ES:[BX] fiziksel adresi ES × 10h + BX olarak hesaplar. Önek komuta bir bayt ekler (burada 26h) ve yürütmeyi iki saat turu uzatır. Komut getirme, yığın işlemleri ve dizgi hedefi önekle değiştirilemez; işlemci bu erişimlerde önekin yokmuş gibi davranır.
SS = 2000h, DS = 3000h, BP = 0100h ve SI = 0020h iken mov byte ptr [bp+si+4], 0AAh hangi adrese yazar? Aynı komut ds: önekiyle yazılırsa ne değişir?
- Etkin adres: BP + SI + 4 = 0100h + 0020h + 0004h = 0124h.
- Adreste BP vardır; varsayılan kesim SS'dir. FA = 20000h + 0124h = 20124h.
ds:önekiyle FA = 30000h + 0124h = 30124h olur. Makine koduC6 42 04 AA'dan3E C6 42 04 AA'ya uzar.
emu8086 iki komutun 20124h ve 30124h adreslerine yazdığını ve önekli komutun 5 bayt tuttuğunu gösterir.
[BX] ile [BP]'nin aynı kesimi kullandığını düşünmek yaygın bir hatadır. BX ve BP aynı değeri tutsa bile [BX] DS'ye, [BP] SS'ye göre hesaplanır ve iki komut farklı baytlara erişir. Bir .COM programında DS = SS olduğu için fark görünmez; kesimler ayrı ayarlanınca hata ortaya çıkar.
2.1.8.9Kod izleme: aynı bağıl konum, üç kesim
Aşağıdaki program aynı bağıl konumu, 0010h'yi, üç farklı kesimle kullanır ve üç farklı bayta erişir. Program bir .COM programı olarak başladığı için başlangıçta CS = DS = ES = SS = 0700h'dir.
org 100h
mov ax, 2000h
mov ds, ax
mov ax, 3000h
mov es, ax
mov bx, 0010h
mov bp, 0010h
mov byte ptr [bx], 11h ; DS
mov byte ptr [bp], 22h ; SS
mov byte ptr es:[bx], 33h ; ES
mov al, [bx] ; DS
mov ah, [bp] ; SS
retİlk dört komut DS = 2000h ve ES = 3000h yapar; değerler AX üzerinden geçer. SS dokunulmadan 0700h kalır. Böylece üç farklı kesim tabanı oluşur: 07000h (SS), 20000h (DS), 30000h (ES). BX ve BP aynı bağıl konumu, 0010h'yi tutar. Hangi bayta erişileceğini bağıl konum değil, kullanılan kesim belirleyecektir.
mov byte ptr [bx], 11h varsayılan olarak DS'yi kullanır: 20000h + 0010h = 20010h adresine 11h yazar. mov byte ptr [bp], 22h BP içerdiği için SS'yi kullanır: 07000h + 0010h = 07010h adresine 22h yazar. mov byte ptr es:[bx], 33h'teki es: öneki DS yerine ES'yi seçtirir: 30000h + 0010h = 30010h adresine 33h yazar; makine kodunun başında 26h öneki vardır. Son iki komut okur: mov al, [bx] yine DS:0010h'yi okur ve AL = 11h olur, ES:0010h'deki 33h değil. mov ah, [bp] SS:0010h'yi okur ve AH = 22h olur. Sonuç AX = 2211h'dir.
| Satır | Kesim | Fiziksel adres | İşlem | AX |
|---|---|---|---|---|
| 2–5 | — | — | DS = 2000h, ES = 3000h, SS = 0700h | 3000h |
| 6–7 | — | — | BX = BP = 0010h | 3000h |
8 [bx] ← 11h | DS | 20010h | yaz 11h | 3000h |
9 [bp] ← 22h | SS | 07010h | yaz 22h | 3000h |
10 es:[bx] ← 33h | ES | 30010h | yaz 33h | 3000h |
11 al ← [bx] | DS | 20010h | oku 11h → AL | 3011h |
12 ah ← [bp] | SS | 07010h | oku 22h → AH | 2211h |
[bp]: SS × 10h + BP = 07010h'ye 22h yazılır. Sağda es:[bx]: önek ES'yi seçer, 30010h'ye 33h yazılır. Aynı bağıl konum üç ayrı bayta karşılık gelir.11. satırdan sonra AX = 3011h olur: AL yeni değeri aldı, AH ise önceki mov ax, 3000h'den kalan 30h'yi korudu. 12. satır AH'yi 22h yapar. Bu ayrıntı, 8 bitlik bir yazmaca yazmanın 16 bitlik yazmacın öteki yarısına dokunmadığını bir kez daha gösterir.
2.1.8.10Kod izleme: kesim:bağıl konum ile erişim
Son izleme, aynı baytın iki farklı mantıksal adresle okunabildiğini ve bir kesimin son baytının nerede olduğunu gösterir.
mov ax, 2000h
mov ds, ax ; DS = 2000h
mov bx, 0010h
mov byte ptr [bx], 41h
mov ax, 2001h
mov ds, ax ; +16 bayt
mov bx, 0000h
mov al, [bx] ; aynı bayt
mov si, 0FFFFh
mov ah, [si] ; son baytDS = 2000h iken veri kesimi 20000h–2FFFFh aralığıdır. mov byte ptr [bx], 41h 20000h + 0010h = 20010h adresine 41h yazar; 41h, 'A' karakterinin ASCII kodudur. Ardından DS = 2001h yapılır. Kesim değeri 1 arttı, ama taban 16 bayt, yani bir paragraf ilerledi: yeni kesim 20010h–3000Fh aralığıdır. BX = 0000h ile mov al, [bx] 20010h + 0000h = 20010h'yi okur ve AL = 41h olur. 2000h:0010h ile 2001h:0000h aynı bayttır. Son iki komut SI = FFFFh ile kesimin en büyük bağıl konumunu kullanır: 20010h + FFFFh = 3000Fh. Bu, DS = 2001h kesiminin son baytıdır ve AH oradaki değeri alır.
| Satır | AX | DS | BX | SI | FA | [20010h] |
|---|---|---|---|---|---|---|
1 mov ax, 2000h | 2000h | ? | 0000h | 0000h | — | ? |
2 mov ds, ax | 2000h | 2000h | 0000h | 0000h | — | ? |
3 mov bx, 0010h | 2000h | 2000h | 0010h | 0000h | — | ? |
4 mov byte ptr [bx], 41h | 2000h | 2000h | 0010h | 0000h | 20010h | 41h |
5 mov ax, 2001h | 2001h | 2000h | 0010h | 0000h | — | 41h |
6 mov ds, ax | 2001h | 2001h | 0010h | 0000h | — | 41h |
7 mov bx, 0000h | 2001h | 2001h | 0000h | 0000h | — | 41h |
8 mov al, [bx] | 2041h | 2001h | 0000h | 0000h | 20010h | 41h |
9 mov si, 0FFFFh | 2041h | 2001h | 0000h | FFFFh | — | 41h |
10 mov ah, [si] | ??41h | 2001h | 0000h | FFFFh | 3000Fh | 41h |
Doğrulayıcıda 3000Fh'ye önceden 99h konduğunda program AX = 9941h ile biter; AH gerçekten 3000Fh'deki baytı alır. Sekizinci satırda AX'in 2041h olması da aynı ilkeyi gösterir: AL 41h oldu, AH beşinci satırdan kalan 20h'yi korudu.
2.1.9Özet
- 8086, 1978'de çıkan 16 bitlik bir mikroişlemcidir ve x86 ailesinin ilk üyesidir. Yazmaçları, ALU'su ve veri yolu 16 bit, adres yolu 20 bittir: 220 bayt = 1 MB bellek adresler. CISC tasarımıdır; komutları 1–6 bayt uzunluğundadır. Sonraki bütün x86 işlemciler açılışta gerçek modda 8086 gibi çalışır.
- Mikroişlemcinin içinde bellek yoktur; çalışması için 8284A saat üreteci, adres kilitleri (8282), veri yolu alıcı-vericileri (8286), bellek ve G/Ç birimleri gerekir. Mikrodenetleyici bunları tek yongada toplar.
- Sistem yolu üç yoldan oluşur: tek yönlü 20 bitlik adres yolu, çift yönlü 16 bitlik veri yolu ve kontrol yolu (RD', WR', M/IO', ALE, INTR, READY). M/IO' bellek ile G/Ç'yi ayırır; G/Ç portları 16 bitlik ayrı bir adres uzayındadır.
- Bir yol döngüsü en az dört saat turu (T1–T4) sürer; 5 MHz'de 800 ns. Bellek, yazmaçlardan çok yavaştır.
- 8086 iki birimden oluşur. BIU adres üretir, komutları getirir ve bütün yol döngülerini yürütür; kesim yazmaçları, IP, adres toplayıcı ve kuyruk ondadır. EU komutları çözer ve yürütür; genel yazmaçlar, ALU, bayraklar ve kontrol sistemi ondadır.
- 6 baytlık önden getirme kuyruğu bir FIFO'dur. En az 2 bayt boşalınca BIU bir sözcük getirir. Getirme ile yürütmenin örtüşmesi iki aşamalı bir boru hattıdır ve verimi yaklaşık iki katına çıkarır. Dallanma kuyruğu temizler ve bu kazancın bir kısmını geri alır.
- ALU 8 ve 16 bitlik aritmetik ve mantık işlemleri yapar ve durum bayraklarını (CF, ZF, SF, OF, PF, AF) günceller.
MULsonucu genişletir (AL × BL → AX),DIVDX:AX'i böler;MOVbayrakları değiştirmez. - Bir makine komutu işlem kodu, ModR/M baytı (mod · reg · r/m), yer değiştirme ve anlık değerden oluşur. Çok baytlı sabitler little-endian yazılır. IP her komutta o komutun uzunluğu kadar ilerler; dallanmalar IP'ye yeni değer yükler.
- 8086'nın 14 yazmacı vardır: AX, BX, CX, DX · SP, BP, SI, DI · CS, DS, SS, ES · IP, FLAGS. Kesim yazmacına anlık değer yüklenemez, CS MOV ile değişmez, kesimden kesime doğrudan MOV yoktur.
- Fiziksel adres = kesim × 10h + bağıl konum. Kesim en çok 64 KB'tır, bir paragraf (16 bayt) sınırında başlar ve kesimler çakışabilir. Aynı adresin en çok 4096 yazımı vardır; normalleştirilmiş yazımda bağıl konum 0h–Fh arasındadır.
- Toplam 1 MB'ı aşarsa 8086'da 21. bit atılır ve adres başa sarar (FFFFh:0510h → 00500h). A20 hattı açık bir 80286'da aynı adres 1 MB'ın üstüne ulaşır.
- Varsayılan kesimler: komut getirme CS:IP, yığın SS:SP, BP'li adresler SS, öteki veri erişimleri DS, dizgi hedefi ES:DI. Kesim öneki (26h, 2Eh, 36h, 3Eh) veri erişimlerinde varsayılanı değiştirir.
2.1.10Kavram listesi
Terimlerin İngilizce karşılıkları ve öteki bölümlerdeki kullanımları terim sözlüğünde bulunur.
- mikroişlemci microprocessor
- mikrodenetleyici (MCU) microcontroller
- CISC complex instruction set computer
- gerçek mod real mode
- saat turu clock cycle
- saat üreteci clock generator
- kilit latch
- tampon buffer (bus transceiver)
- yol bus
- sistem yolu system bus
- adres yolu address bus
- veri yolu data bus
- kontrol yolu control bus
- yol döngüsü bus cycle
- yol arayüz birimi (BIU) bus interface unit
- yürütme birimi (EU) execution unit
- önden getirme prefetch
- önden getirme kuyruğu prefetch queue
- boru hattı pipeline
- aritmetik-mantık birimi (ALU) arithmetic logic unit
- bayrak flag
- durum bayrağı status flag
- komut yazmacı instruction register
- komut çözücü instruction decoder
- kontrol birimi control unit
- işlem kodu opcode
- ModR/M baytı ModR/M byte
- yer değiştirme displacement
- anlık değer immediate value
- etkin adres (EA) effective address
- little-endian little-endian
- yazmaç register
- yazmaç kümesi register set
- genel amaçlı yazmaç general-purpose register
- sözcük word
- kesim segment
- kesim yazmacı segment register
- kod / veri / yığın / ek kesim code / data / stack / extra segment
- bağıl konum offset
- kesim:bağıl konum (mantıksal adres) segment:offset
- fiziksel adres physical address
- paragraf paragraph
- kesimli bellek segmented memory
- kesimleme segmentation
- komut işaretçisi (IP) instruction pointer
- varsayılan kesim default segment
- kesim öneki segment override prefix
2.1.11Kendini Dene
80286'nın adres yolu 24 bittir. Kaç bayt adresler ve en yüksek adresi onaltılık olarak nasıl yazılır? 8086'nın adres alanının kaç katıdır?
Cevap
224 = 16 777 216 bayt = 16 MB. En yüksek adres altı onaltılık basamakla FFFFFFh'dir. 224 / 220 = 24 = 16 kat.
8 MHz'lik bir 8086-2, bekleme durumu olmadan bir yol döngüsünü kaç nanosaniyede tamamlar? Bu hızda tek adreslerden başlayan 50 sözcüğü okumak en az ne kadar sürer?
Cevap
Saat turu 1 / 8 MHz = 125 ns; yol döngüsü 4 × 125 = 500 ns. Tek adresten başlayan bir sözcük iki döngü ister: 50 × 2 × 500 ns = 50 000 ns = 50 µs. Sözcükler çift adreste olsaydı süre 25 µs olurdu.
Getirme 2, çözme ile yürütme 2 zaman birimi süren modelde 8 komut çalışıyor ve dördüncü komut bir JMP. Boru hattı olmadan ve boru hattıyla toplam süreler nedir?
Cevap
Boru hattı olmadan 8 × 4 = 32 birim. Boru hattıyla dallanma olmasaydı 2 + 8 × 2 = 18 birim olurdu. JMP Y4 sırasında (8–10) getirilen beşinci komutu geçersiz kılar; hedef 10–12'de getirilir ve Y5 12–14, Y6 14–16, Y7 16–18, Y8 18–20 olur. Toplam 20 birim.
ADD CX, [BX+SI+10h]komutunun makine kodu03 48 10'dur. ModR/M baytını alanlarına ayırın ve her alanın anlamını yazın.Cevap
48h = 0100 1000 = 01 001 000. mod = 01: bellek işleneni, 8 bitlik yer değiştirme var (10h). reg = 001: CX. r/m = 000: [BX+SI]. 03 işlem kodu “r/m16'yı reg16'ya ekle” olduğu için komut CX ← CX + [BX+SI+10h]'dir; adreste BP olmadığından kesim DS'dir. Komut 3 bayttır.
SS = 9000h ve SP = FFFEh iken
PUSH AXçalışıyor (AX = 1234h). SP'nin yeni değeri nedir ve 34h ile 12h baytları hangi fiziksel adreslere yazılır?Cevap
PUSH önce SP'yi 2 azaltır: SP = FFFCh. Sözcük SS:FFFCh'ye little-endian yazılır. Taban 90000h olduğundan 34h → 9FFFCh, 12h → 9FFFDh.
0ABCDh:1234hmantıksal adresinin fiziksel adresini bulun ve normalleştirin.Cevap
ABCD0h + 01234h = ACF04h. Toplam FFFFFh'yi aşmaz. Normalleştirilmiş yazım: ilk dört basamak kesim, son basamak bağıl konum →
ACF0h:0004h.F800h:9000hadresi 8086'da hangi fiziksel adrese karşılık gelir? A20 hattı açık bir 80286'da ne değişir?Cevap
F8000h + 09000h = 101000h; 21 bit. 8086'da 21. bit atılır ve adres 01000h'ye sarar. A20 açık bir 80286'da adres gerçekten 101000h'dir, yani 1 MB'ın 4 KB üstü.
SS = 2000h, DS = 3000h, BP = 0100h, SI = 0020h.
MOV AL, [BP+SI+4]hangi fiziksel adresi okur? Aynı veriyi DS kesiminden okumak için komut nasıl yazılır ve kaç bayt uzar?Cevap
Etkin adres 0124h; BP içerdiği için varsayılan kesim SS: 20000h + 0124h = 20124h. DS'den okumak için kesim öneki yazılır:
MOV AL, DS:[BP+SI+4]→ 30124h. Önek (3Eh) komuta bir bayt ekler.DS ile ES'nin değerlerini, genel amaçlı yazmaçları bozmadan değiştirmek isteniyor.
MOV ES, DSneden kullanılamaz? Yığınla çalışan bir çözüm yazın.Cevap
8086'da kesimden kesime doğrudan MOV yoktur. Yığınla:
PUSH DS,PUSH ES,POP DS,POP ES. Yığın LIFO olduğu için önce ES'nin değeri DS'ye, sonra DS'nin eski değeri ES'ye çıkar. DS = 1111h, ES = 2222h ile başlanırsa sonuç DS = 2222h, ES = 1111h olur.
2.1.12İleri okuma
- Intel, The 8086 Family User's Manual (1979), Bölüm 2: BIU ve EU, kuyruk, kesimleme ve komut kodlaması tasarımcının kendi anlatımıyla, zamanlama çizelgeleriyle birlikte verilir.
- B. B. Brey, The Intel Microprocessors (8. baskı), Bölüm 2 ve 3: gerçek mod bellek adreslemesi, varsayılan kesimler ve adresleme modları bol örnekle ele alınır.
- M. A. Mazidi, J. G. Mazidi ve D. Causey, The x86 PC: Assembly Language, Design, and Interfacing (5. baskı), Bölüm 1: 8086'nın iç yapısı, boru hattı ve kesim:bağıl konum hesabı DEBUG örnekleriyle anlatılır.
2.1.13Kaynaklar
- Intel, 8086 16-Bit HMOS Microprocessor, veri sayfası (231455).
- Intel, The 8086 Family User's Manual, 1979.
- Barry B. Brey, The Intel Microprocessors, 8. baskı, Pearson, 2009.
- Muhammad Ali Mazidi, Janice Gillispie Mazidi, Danny Causey, The x86 PC: Assembly Language, Design, and Interfacing, 5. baskı, Pearson, 2010.
- emu8086 belgeleri ve komut kümesi başvurusu.
İlgili sayfalar: Bölüm 2.1 sunumu · Çalışma soruları · Terim sözlüğü · © Sercan Külcü. Tüm hakları saklıdır.