SİTE
İÇİ ARAMA |
|
Blogroll |
|
|
|
İşlemci Durum Kaydedicisi |
|
Gönderiliyor lütfen bekleyin... |
|
|
Mikroişlemci içinde
yapılan işlemlerin durumlarını programcıya bildiren bir kaydedici mevcuttur. Tüm
karar alma mekanizmaları bu kaydedicide gösterilen sonuçlar baz alınarak
yapılır.
İŞLEMCİ DURUM KAYDEDİCİSİ (PROCESSOR STATUS REGISTER)
Diyelim ki klavyeden
girilen iki adet değişken var bunlar eşit ise ekrana "eşit" eşit değilse "eşit
değil" yazdırmak istiyoruz. Bunu üst seviye programlama dillerinde basit bir
şekilde if-else mantığıyla yapabilirsiniz. Peki mikroişlemci bu değerlerin eşit
olup olmadığını nasıl gösterecek bize. Cevabı basit bu değerlerin farkını
alarak, sonuç sıfırsa girilen değerler eşittir aksi taktirde eşit değildir. İyi
ama assembly programcısı bu sonuç sıfır değerini nereden okuyacak?
Bir işlemin
sonucunun sıfır, negatif, pozitif veya elde ürettiği veya işlemin
gerçekleştirilmesi için borç alındığı gibi durumları gösteren kaydediciye
işlemci durum kaydedicisi diyoruz. Turbo debugger ile işlemci durum
kaydedicisinin içeriğini gözlemleyebilirsiniz.
Şekil 1 -
8086da işlemci durum kaydedicisi.
Şekilde kırmızı
çerçeve içine alınmış kısım işlemci durum kaydedicisini bitsel olarak
gösteriyor. Diğer kaydedicilerin aksine işlemci durum kaydedicisi programcı için
bitsel olarak anlamlıdır. Ve bu bitlerin her birinin bir adı vardır. Örneğin C
biti Carry yani taşıma biti veya Z biti Zero yani sıfır bitidir. Terminolojide
genellikle bu bitler "flag" yani bayrak olarak adlandırılır. Aslında assembly
programcıları işlemci durum kaydedicisi yerine bayrak kaydedicisi terimini daha
çok kullanırlar. Örneğin Z için Zero Flag yani sıfır bayrağı denir.
8086, 80286, 80386,
80486 ve Pentium işlemcilerin bayrak kaydedicileri biraz farklıdır, daha doğrusu
işlemciler geliştikçe ek bayraklar eklenmiştir, mesela 80286dan itibaren
işletim sistemlerinin yazımı için gerekli olan ayrıcalıklı mod bayrağı
eklenmiştir. Yukarıdaki şekilde
8086nın 8 bitlik bayrak kaydedicisini görmektesiniz, aşağıdaki şekilde ise
8086dan 80486ya kadar olan
işlemcilerin sahip olduğu bayrakları görebilirsiniz.
Şekil 2 - x86 işlemci durum (bayrak) kaydedicisi.
Bayrak
kaydedicisindeki her bir bitin 1 olma durumuna SET, 0 olma durumuna da RESET
denir. İşlemcinin ürettiği sonuçlar hakkında programcıyı uyaran bayrak
kaydedicisindeki durumlar görecelidir. Örneğin carry (taşıma) bayrağı 1
olduğunda bazen işlemin elde ürettiğini bazen de borç alındığını ifade edebilir.
Bazen de iki bayrağın durumu birlikte değerlendirilerek bazı sonuçlara varılır.
Örneğin;
MOV
AX, 0FFFEh ; FFFE = 65534
işaretsiz sayıyı temsil ederse
ADD AX, 3
; C = 1, O = 0 olur ve bu bir boyut taşmasını gösterir.
Bu örneği biraz daha
açıklayacağım fakat daha önce matematik dersinde gördüğümüz bazı olayları
hatırlatmak istiyorum. Hani bir fonksiyonun çözümü için sorularda "her x gerçel
sayısı için" gibi ifadeler geçer ya, işte bu tür kabullenmeler assembly dilinde
çok önemlidir. Çünkü 1 ve 0ları ancak bu şekilde yorumlayabilirsiniz, yani
baştan evrensel kümenizi kafanızda tanımlamanız gerekir. Bu örnekte de FFFE=65534
değerini gösterirse diye başlıyoruz işe, nitekim FFFE işaretli sayı olarak kabul
edilseydi -2 değerini gösterecekti. Ama burada işaretli değil sadece pozitif
tamsayılarla işlem yapıldığı varsayılıyor. Bu işlemin sonucu AX kaydedicisinde
0001 olarak görülür. İşlemci sayıların işaretli veya işaretsiz olduğuna bakmadan
FFFE ye 3 ekler ve FFFE değeri önce FFFF sonra 0000 ve daha sonrada 0001 olur.
Tabi ki 65534 + 3, işleminin sonucu 1e eşit değildir. İşlemin doğru sonucu olan 65537 değeri 2 bytelık AX kaydedicisinin içine sığmadığından bu sonuç üretilmiştir. Bu toplama
işlemi sürecinde sayı FFFFden 0000a dönerken C=1 olur, bunu elde olarak
düşünebilirsiniz (tabi ki pozitif tamsayılar kümesi baz alınarak işlem
yapılıyorsa) Aslında 0001 sonucunun başına bu elde getirildiğinde yani sonuç C
biti ile birlikte okunursa 10001 olur ve bu gerçektende 65537 değerine eşittir.
Fakat programcı doğal olarak AX kaydedicisini içindeki değeri yani 0001i sonuç olarak
alacaktır. Burada sonuç anlamlı aralık olan 0...65535 arasında olduğundan O=0
olmuştur. Özetle sonuç anlamlı aralıkta yanlış bir değerdir, bu durumu programcı
iki bayrağa birden bakarak anlayabilir.
Yukarıdaki gibi bir
durumda programcı işlem yapıldıktan sonra bazı özel komutlarla C ve O (overflow-taşma)
bitlerinide kontrol eder ve bu bitler sırasıyla 1 ve 0 ise bir boyut taşması
olmuş demektir. Bu durumda programcı kullanıcı ekranına "sonuç çok büyük" gibi
bir mesaj gönderebilir. Hesap makinelerinin belli bir değere kadar işlem
yapabildiğini hatırlayın.
Bu örnek için en
başta FFFE işaretli bir saydır deseydik herhangi bir taşma söz konusu
olmayacaktı. İşlemci yine aynı sonucu üretecek fakat bu sefer programcı bunu
-2+3 olarak değerlendireceğinden sonuç doğal olarak 1 ve AXte 0001 değeri doğru
sonuç olacaktı. Yine C=1 ve O=0 olsa da programcı için bu durum bir taşmayı
göstermeyecektir.
İşte assembly
programlama dili matematiğin bu basit gibi görünen temellerine bağlıdır.
Hafızadaki 1 ve 0ları nasıl yorumlarsanız öyle şekil alırlar. Bazen bu 1 ve
0lar bir resim, bazen bir mp3 bazen de bir kelime oluveririler. Hani matrix
filminde herkes kodlara bakıyor ama sadece Neo olayı idrak edebiliyordu ya, işte
o misal :)
Şekil
3 - bilgisayarlar aslında 1ler ve 0lar dünyasıdır.
8086 için bayrak
kaydedicisi 16 bitliktir ve bu 16 bitte sadece 9 adet bayrak mevcuttur. 386 ve
sonrası işlemcilerde ise bayrak kaydedicisi 32 bitliktir ve bu 32 bitin her
biri bir bayrağı temsil etmez, aralarda hiçbir şeyi ifade etmeyen boş bitler
mevcuttur. Şu anda gerçek mod programları yani 8086 için programlar
yazdığımızdan bu 9 adet bayrağın ne anlama geldiklerini incelememiz yeterlidir.
Overflow Flag (OF) (Taşma Bayrağı): İşaret taşması olduğunda olduğunda
set (1) olur, mesela 1 bytelık işaretli sayılarda 100+50=150dir, fakat
sonuç -128...127 aralığında değildir.
Direction Flag (DF) (Yön bayrağı): String işlemlerini yapan komutlar için
kullanılır. 1 olduğunda index kaydedicisi otomatik olarak azalır. 0 ise index
kaydedicisi otomatik olarak artar. (mesela bir string hafızanın bir bölgesinden
başka bir bölgeye kopyalanırken işlemin stringin sonundanmı yoksa başındanmı
yapılacağını D flag ile belirleyebilirsiniz)
Interrupt-enable Flag (IF) (Kesme Yetki bayrağı): 1 olduğunda
maskelenebilir kesmeler kullanılabilir. (kesmeler hakkında ayrıntı sonraki
makalelerimizde!)
Single-step Flag or Trace (TF) (Tek Adım veya İzleme Bayrağı): Genelde
debugger programları için kullanılır, 1 olduğunda bir anda sadece 1 komut
işlenir.
Sign Flag (SF) (İşaret Bayrağı): MSB biti (en soldaki bit) 1 olduğunda bu
bayrakta 1 olur.
Zero Flag (ZF) (Sıfır Bayrağı): Sonuç sıfır olduğunda 1 olur.
Auxiliary carry Flag (AF) (Ara Elde Bayrağı): AL kaydedicisinin 0-3
arasındaki bitlerinde yapılan işlemde elde veya borç üretilirse 1 olur.
Parity Flag (PF) (Eşlik Bayrağı): 1 olduğunda sonucun düşük değerlikli
baytındaki (mesela 127Fh gibi word boyutunda bir sonuç üretilmişse bunun 7F
kısmı için) 1lerin sayısının çift olduğunu gösterir.
Carry Flag (CF) (Taşıma Bayrağı): 1 olduğunda elde üretildiğini veya borç
alındığını belirtir.
Bayrak Kaydedicisini
özetleyecek olursak,
1- İşlemcinin
yaptığı işlemlerin özel durumlarını gösterirler
2- Bazı işlemler
yapılmadan önce bazı bayrakların 1 yada 0 yapılması gerekebilir
3- Programcılar bazı
işlemleri anlayabilmeleri için bazen birden fazla bayrağın birlikte ürettikleri
durumları göz önüne almak zorundadırlar.
Uzun bir süre bu
bayraklardan OF, SF, ZF, CF olanları bizim için önemli olacak. Bayrakların geri
kalan kısımları ve bayrakları etkilen komutları sonraki makalelerimizde yeri
geldikçe açıklamaya çalışacağım. İsterseniz şimdi bayrak kaydedicisi ve
bayraklarla ilgili kafanızda daha belirgin bir şeklin oluşabilmesi için
makalemizin başında bahsettiğimiz örneği hayata geçirelim.
Şimdi yapacağımız
programda kullanıcı klavyeden 2 adet değer girecek ve bu değerler eşitse ekrana
"Girilen Degerler Esittir" yazacak değilse "Girilen Degerler Esit Degildir"
yazacak. İlk bakışta kullanıcı sayıları bilmiyor mu kardeşim ne gerek var böyle
bir programa diyebilirsiniz :) Fakat değerlerin klavyeden değilde paralel
porttan alındığını ve bu portun bir klimaya bağlı olduğunu ve hava sıcaklığının
24C0 ye eşit olup olmadığını test eden ve eşitse klimayı durduran
değilse çalıştıran bir programında bundan pek farklı olmayacağını tahmin
edebilirsiniz.
Bu örnekte henüz
işlemediğimiz konulardan olan "ekran ve klavye işlemleri" ve "şartlı
dallanmalar" konularını kapsayan komutlar kullanacağız. Bunların ayrıntılarını
daha sonra anlatacağımdan şimdilik fazla önemsemeyin. Bu komutlar aşağıdaki
gibidir.
MOV
AH,01
INT 21h |
Bu
komutlardan sonra program kullanıcı giriş yapana kadar durur ve
kullanıcı klavyeden değer girdiğinde o değerin ASCII kod karşılığı AL
kaydedicisine yerleştirilir. |
JMP
HedefAdres |
Bu komut
ile hedef adrese dallanma gerçekleştirilir. |
JE
HedefAdres |
Bu komut
ile hedef adrese Z bayrağı 1 ise dallanma gerçekleştirilir. |
CMP BL,
AL |
Bu komut
BL ile AL kaydedicisini karşılaştırır. |
Şekil 4 - Klavyeden girilen değerleri test eden program.
Yukarıdaki programın
kaynak kodlarını buradan download edin
ve TASM ile derleyin. Bu programı çalıştırdığınızda sizden iki adet değer
girmenizi isteyecek, değerleri girerken enter tuşuna basmanıza gerek yok. Şayet
girilen değerler eşitse ekranda "Girilen Degerler Esittir" değilse "Girilen
Degerler Esit Degildir" mesajını göreceksiniz.
Şekil 5 - Programın ekran çıktısı.
Değerlerin eşit olup
olmama durumunu belirleyen işlemci durum kaydedicisinin Z biti (Z bayrağı) dir.
Bu bayrağın durumu karşılaştırma komutundan sonra girilen değerlere göre 1 yada
0 olur. Şayet girilen değerler eşit ise, eşit olan bu değerler karşılaştırılır
ve sonuç sıfır elde edilir, bu durumda Z=1 olur. JE komutu ise ancak Z=1
olduğunda, operandında belirtilen adrese dallanma işlemini geçekleştirir. Aksi
durumda işlemci klasik yolunu izler ve bir sonraki komutu işler.
Şekil 6 - Z=1 olduğunda 0024h offset adresine dallanılacak.
Klavyeden farklı
değerler girildiğinde ise, karşılaştırma işleminin sonucunda z=0 olur. Bu
durumda dallanma gerçekleşmez ve işlemci normal seyrini sürdürerek bir sonraki
komutu işler.
Şekil 7 - Z=0 olduğunda dallanma gerçekleşmeyecek, program sonraki komutu takip
edecektir.
Bayrakların
durumları bayrakları etkileyen bir komut işlendiğinde değişir, her komut
bayrakları etkilemez. Burada CMP komutu 6 adet bayrağı etkiliyor. Hangi komutun
hangi bayrakları etkilediğine Intelin komut
setinden bakabilirsiniz. Komut setinden CMP komutunu bulursanız bu 6
bayrağın neler olduğunu görebilirsiniz.
Şekil 8 - CMP ile AF, CF, OF, PF, SF, ZF bayrakları etkilenir.
İsterseniz Şekil7
deki etkilenen tüm bayrakları ve neden dolayı 1 yada 0 olduklarını inceleyelim.
Burada yapılan işlem "CMP BL, AL" dir ve BL=33, AL=34dür. BL-AL yani 33h-34h
işlemini yapan CMP komutu aşağıdaki nedenlerden dolayı bu bayrakları
etkilemiştir.
1- 33-34 işlemi için
borç gerektiğinden (Küçük sayı büyük sayıdan çıkartılıyor) CF=1,
2- Bu işlemin sonucu
sıfır olmadığından ZF=0,
3- İşlemin sonucu
negatif olduğundan SF=1,
4- İşlem sonucunda
bir işaret taşması olmadığından OF=0,
5- Sonuçta elde
edilen -1 yani FFh, başka bir deyişle 11111111b değerindeki 1lerin sayısı sekiz
adet yani çift olduğundan PF=1,
6- Binary olarak
çıkartma işleminde daha 2. bitte 0dan 1 çıkarılırken
|
|
borç
alındığından AF=1 olmuştur. |
Bizim programımızda
sadece Z bayrağının durumu önemli olduğundan bu bayrağın durumuna göre programın
akışını kontrol eden JE komutunu kullandık. Aslında burada JE komutu ile
ilerleyen makalelerde ele alacağımız if-else mantığını oluşturduk.
Gördüğünüz gibi
program akış kontrolünde bayraklar hayati önem taşır. İşlemci durum
kaydedicisinde bulunan bu bayraklar şu anda aklınızın alamayacağı bir çok
işlemde bizlere yardımcı olacak.
Bu konuyu daha iyi
anlamak için Turbo Debuggerda programın her komutunu adım-adım çalıştırın ve
komut setinden faydalanarak, çalıştırdığınız komutun etkilediği bayrak varsa
bunun nedenini araştırın.
Şu anda saatim
23:57yi gösteriyor ve sabah erken kalkmam gerekiyor, sabah kalktığımda Z
bayrağımın 1 olmaması için yatağıma Jump yapmalıyım :)
Bir sonraki
makalemizde görüşmek dileğiyle...
Makale:
İşlemci Durum Kaydedicisi Assembly ve X86 Programlama Eren Erener
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|