FaTaL Yönetici
Ruh Hali : Mesaj Sayısı : 626 Rep Puanı : 12348 Teşekkür Aldı : 18 Kayıt tarihi : 24/10/09 Nerden : Kocaeli İş/Hobiler : 3D / Maya / After Efect Lakap : Fatal
| Konu: Assembly Giriş-2 Cuma Ekim 30, 2009 9:09 am | |
| ASSEMBLY PROGRAMLAMA DİLİ (BÖLÜM -2 )
REGISTERLER :
Evet arkadaşlar geldik registerler (Namı diğer Yazmaçlar nedense bu kelimeyi görünce sinir oluyorum ben buna kaydedici demeyi uygun buluyorum ama bilmeniz açısından yazdım ) konusuna, bu konuda oldukça kolay arkadaşlar.Makaleyi okudukta sonra anlayacağınızdan eminim.Registerleri kısaca şöyle tarif edebiliriz, programlamayla ilgilenen arkadaşlar bilirler,hani program yazarken değişken dediğimiz ,(a=53 , b= ”atmaca” gibi)değer atama durumları vardır ya hani,işte registerleri de bu değişkenlere benzetebiliriz.Örneğin b=”atmaca” değişkenimize başka herhangi bir değer atamadığınız sürece “b” ‘nin değeri hep “atmaca olacaktır.Taki bir değer atarsanız ,mesela 42 derseniz o zaman “b” ‘nin taşıdığı değer 42 olur.Bunun gibi registerler de (yani kaydediciler) CPU’ nun her türlü işlemlerini yerine getirmesi için bu görevi yerine getirirler. Kısaca şöyle de diyebiliriz ,işlemci yani CPU register adı verilen bölmelerden oluşur ve bu registerler de mikroişlemcinin en temel bileşenlerinden biridir .Bu registerleri ben 4 bölüme ayırmayı uygun buluyorum kimileri 3 yada 5 bölüm olarak inceleyebiliyor.
1-GENEL AMAÇLI REGİSTERLER AX = Accumulator Register BX = Base (Taban )Register CX = Counter (Sayaç )Register DX = Data (Veri )Register 2-SEGMENT REGİSTERLERİ CS = Code Segment Register DS = Data Segment Register SS = Stack Segment Register ES = Extra Segment Register 3-OFFSET REGİTERLERİ IP = Instraction Pointer Register SP = Stack Pointer Register BP = Base Pointer Register a-)İndex Registerler
SI = Source (Kaynak )Index Register DI = Destination (Hedef)Index Register
4-FLAG (BAYRAK )REGİSTERLERİ O = Overflow flag D = Direction flag I = Interrupt flag T = Trace flag S = Sign flag Z = Zero flag A = Auxilary Carry flag P = Parity flag C = Carry flag
Evet registerlerimiz bunlar,siz şimdilik hepsini de ezberlemeye kalkmayın zamanla programlar üzerinde durdukça öğreneceksiniz,bunlardan özellikle flag (bayrak )registerleri sadece bilgi almak açısından kullanırız ,yoksa bunlar üzerinde işlem yapamayız.İşlem sonunda eşitlik var mı yok mu,veya işlem sonunda taşma oluyor mu ya da olmuyor mu; gibi bilgileri görmek için kullanırız.Ben yine de mümkün olduğu kadar karşılarına Türkçe karşılıklarını da yazdım ki zorlanmayasınız.Bunların bir kısmını ayrıntılı olarak sonraki konularda anlatacağım zaten.
1-GENEL AMAÇLI REGİSTERLER :
Yukarıda görmüş olduğunuz (ax ,bx ,cx ve dx )registerleri eski 8 ve 16 bit işlemciler ( 8086,80186 gibi) için bu şekilde kullanılıyordu.Fakat bu işlemciler günümüzde pek kalmadı ve yeni 32 bit işlemciler daha yaygın bir şekilde kullanılıyor.Bunun içinde bu register isimlerinin başına Extended (Genişletilmiş ) kelimesinin “e” harfi getirildi.Yani EAX-EBX-ECX-EDX şeklinde oldular.Bizde bundan sonra bu Genel Registerler ,Segment Registerler ,Ofset ve İndex registerleri yazarken bu şekildeyazacağız.EBX-EDI-ESI-ESP vs gibi.. Bir ornek ;
Mov eax,24 Mov ebx, 10 Add eax , ebx Sonuç = 34
Dönelim bu genel kaydedicilere ,bunlar kendi aralarında 2’ye bölünerek 8 adet olurlar.Şöyle ki;
EAX = AH - AL (32 BİT)= (16 BİT) - (16 BİT) EBX = BH - BL (32 BİT)= (16 BİT) - (16 BİT) ECX = CH - CL (32 BİT)= (16 BİT) - (16 BİT) EDX = DH - DL
Eğer bunlar 16 bit lik registerler olsaydı o zaman da 8 bit AH , 8 bit AL olarak değişecekti.Sonlarına eklenen H ve L harfleri “H” High (Yüksek)- “L” ise Low (Düşük) kelimelerinden gelmiştir. 16 bitlik bir register en fazla 65535 değerini alırken 32 bitlik bir register 4294836225 değerine kadar alır.
EAX register programlarda en çok kullanılan yazmaçlardan biridir. Accumulator’ün kısaltılması sonunda oluşan EAX yazmacı bütün giriş ve çıkış işlemlerinde ve bazı aritmetik işlemlerde kullanılır.
EBX Registeri Base register olarak da bilinir. RAM işlemlerinde adreslemede kullanılır. Register adresleme işlemlerinde daha çok offset degerlerini tutar. Ayrıca hesaplama işlemlerinde de kullanılır.
ECX Registeri Counter registeridir. Döngü işlemlerinde ve kaydırma işlemlerinde sayaç olarak kullanılırız.
EDX Register bazı giriş çıkış işlemlerinde ve matematiksel işlemlerde kullanılır.Daha çok çarpma ve bölme işlemlerinde büyük sayıları saklamak için AX registerinin bir parçasıymış gibi kullanılır.
2-SEGMENT REGİSTERLERİ :
Segment register’ ları (ECS, EDS, ESS ve ES) programımız bilgisayarın belleğine yüklendiği zaman bellek içerisinde oluşturulan bölümlerin (Segment) başlangıç adreslerini tutarlar. Yani bu register’lar için bir çeşit yer göstergeci diyebiliriz. ECS, programımızın çalıştırılabilir kodlarını barındıran (Code Segment) bölgesinin başlangıç adresini tutar. Yani ECS ile gösterilen yerde makine dili kodlarımız vardır. EDS ise, programımız içerisindeki değişkenlerin saklı tutulduğu bölümdür. ESS (Stack), bellekte programımız için ayrılan stack bölümünün ( ki bu bölümü ayrı bir şekilde aşağıda anlatacağım ) başlangıç adresini tutar.ES (Extra segment) ise daha çok dizi yani string (Numerik olmayan) işlemleri için kullanılırız.
3-OFFSET VE İNDEX REGİTERLERİ :
Offset ve index register’ları bellek içerisindeki herhangi bir noktaya erişim sağlamak için kullanılır.Bu işlem için erişmek istediğimiz bölgenin offset ve segment adresleri gerekli register’lara aktarılır bizde bu şekilde işlemi gerçekleştirmiş oluruz.. Instruction Pointer register’ı ise CPU tarafından işlenecek olan bir sonraki komutun bellekteki adresini tutar. Bu register üzerinde programcının hiçbir eylemi olamaz. Her komut icra edildikten sonra CPU otomatik olarak kullanılan komuta göre gerekli değeri bu register’a atar.Arkadaşlar belki biraz ağır bir anlatım gibi görünebilir fakat bunların başka bir izah şeklini bulamadım yani şu an aklıma gelmiyor.
4-FLAG (BAYRAK )REGİSTERLERİ : Arkadaşlar bunları detaylı bir şekilde anlatmadan önce şunu hatırlatmak istiyorum.Bayrak kaydedicisindeki her bir bitin 1 olma durumuna SET, 0 olma durumuna da RESET denir. İşlemcinin ürettiği bu sonuçlar hakkında programcı bunlara bakarak işlem durumunu analiz eder. Overflow flag (OF): Biz buna taşma biti de diyebiliriz. İşaretli (negatif)sayı üzerinde meydana gelen taşma durumunu tespit etmek amacıyla kullanılır. Yani işlem sonucunda işaret biti değişmişse bu flag set edilir,yani 1 değerini alır. Direction flag(DF):Bizim kullanmadığımız bir bayraktır.String işlemlerini yapan komutlar için kullanılır.Yani bir stringi hafızanın bir yerinden diğer bir yerine kopyalarken CPU tarafından kullanılmaktadır. İşlemci bu bayrağa bakarak transferin yönünü belirler. Interrupt flag (IF):Buna kesme bayrağı da diyebiliriz. CPU’nun çeşitli aygıtlardan gelen kesme isteklerini dikkate alıp almayacağını bildirir. 0 olması durumunda istekler dikkate alınmaz,1 olursa alır. Trace flag (TF) : Trace biti de diyebileceğimiz bu bayrak CPU nun sadece 1 komut çalıştırma yapması için kullanılır.Hani Debugger ile bir programı açıp programda adım adım ilerliyoruz ya ,işte CPU bunu ,bu bayrağın durumuna göre yapar 1 olursa işletilmeye hazırdır demektir.. Sign flag (SF): Yapılan işlem sonucunda elde edilen sayının en solundaki bit 1 ise bu negatif bir sayıdır demektir ve bu bayrakta 1 değerini döndürür.Eğer ki 0 ise pozitiftir ve bayrak 0 değerini yansıtır.Kısaca bu bayrak sayının negatif veya pozitif olduğunu gösterir.
ADD EAX, EBX
Eğer SF nin değeri 1 ise o zaman EAX deki sayı negatif bir sayı deriz. Zero flag (ZF) :Bir işlemin toplam sonucu 0 ise bu flag set edilir yani 1, değilse reset yani 0 edilir.Bu bayrağı karıştırmayın arkadaşlar tekrar ediyorum eğer işlem sonunda sonuç 0 ise ,bu bayrak 1 değerini döndürüyor.Mesela;
SUB EAX, EBX
işleminde iki register’ın değerleri eşitse sonuç 0 olacağı için ZF set (1)edilecektir.Aşağıdaki Olly debugger ile aldığım örnek resim olayı kavramanıza yardımcı olacak.
Yukarıdaki resimde JE (jump if equal)komutunu görüyorsunuz burada bir üstündeki OR komutuyla (Daha sonra detaylı şekilde anlatacağım)işlem sonu kontrol ediliyor ve eşitlik var ise JE ile gösterilen adrese atla deniyor.Ancak aşağıdaki resimde gösterdiğim gibi Z bayrağı 0 (sıfır)gösterdiği için atlama gerçekleşmeyecektir.
Auxilary Carry flag (AF) : Dördüncü bit’ten beşinci bit’e doğru oluşan elde durumunda set edilir. Elde yoksa reset edilir. Özellikle BCD (binary coded decimal) işlemleri için düşünülmüştür.Zaten sizin sık kullanacağınız bir şey değil o nedenle fazla üstünde durmuyorum.
Parity flag (PF) : 16 bitlik bir işlem sonrasında düşük anlamlı byte içerisindeki 1’lerin sayısı çift ise bu bit set edilir 1 olur , tek ise reset edilir o olur. Yani düşük seviyeli bayt bölümündeki 1’lerin sayısı iki ile tam bölünüyorsa bu bayrağa 1 aksi taktirde 0 atanır.
Carry flag (CF) : Bu bayrak da Overflow bayrağına benzer ,ancak aralarında ki önemli fark şu arkadaşlar.Overflow bayrağı işaretli yani negatif sayılar için kullanılır demiştik.Carry (elde)bayrağı da işaretsiz pozitif sayılar için kullanılır.Yine aynı işi yapar yani bir işlem sonunda CPU taşma ile karşılaşırsa carry flag’ın değerini 1 yapar set eder.
ADRESLEMELER :
Bildiğiniz gibi programları oluşturan kodlar ve veriler hafızaya yüklendikten sonra işlemci tarafından satır-satır icra edilirler. Ayrıca CPU tüm giriş-çıkış işlemlerini de hafızaya erişerek yapar. Bazen hafızadan doğrudan bir kod ya da veri alır, işler. Bazen hafızaya bir veri gönderdiğinizde birde bakmışsınız bu bir yazıcıdan belge olarak çıkmış . İşte bilgisayarın donanım ve yazılım olayın da yaptığı bunca çeşitli iş için CPU hafızaya değişik yollardan erişme ihtiyacı duyar. Sizlerde programlarınızı yazarken CPU’nun hafızaya nasıl erişeceğini yazdığınız kodlarla belirtmek zorundasınız. Assembly dilinin bir basamağı olan adresleme modları da bu konuları kapsıyor ve bence iyi bilinmesi gereken bir konu.
Başlıca adreslemeler:
Register (Kaydedici) adreslemesi : Adından anlaşılacağı gibi kaydediciden kaydediciye yapılan işlemlerde bu adresleme modları kullanılır. En hızlı adresleme modu’dur, çünkü işlem hafızada (Bellekte) değil işlemcinin içinde gerçekleşir
mov eax, ebx ; EBX teki değeri EAX’e kopyalar mov dl, al ; AL teki değeri DL’ye kopyalar (Açılımları yukarda söylemiştik) mov esi, edx ; EDX teki değeri ESI’ya kopyalar Kaydedici adreslemede en çok dikkat etmeniz gereken husus hedef ve kaynağın boyutlarıdır. Örneğin 16 bitlik bir kaydediciden 8 bitlik bir kaydediciye taşıma yapılamaz!
mov cx, al ; Yanlış kullanım, AL(8 bit) ile CX(16 bit) eşit boyutta değil.
Hafıza bölgesi adreslemesi : Bu adresleme ile register hafızanın herhangi bir bölgesi işaretlenir. Bunun için MOV komutu yerine LEA (ilerde bahsedeceğim)komutunu kullanabiliriz. MOV komutu registere verilen değeri yükler yada adresler. LEA komutu da aynı işi yapar. Ancak MOV komutundan önemli bir farkı vardır. Verdiğiniz yerdeki değeri değil adresi yükleme yapar. Örneğin:
debug ’Yazi1’,01
lea eax, debug şeklinde verilince EAX registere ’Yazi’ değişkeninin değeri değil bulunduğu yerin adresi yüklenir. Böylece biz bu verinin başından itibaren istediğimiz gibi çalışma yapabiliriz.
Dolaysız adresleme :Bu adresleme registerler arasındaki değerlerin hafıza adresi olarak kullanılması ile oluşan adreslemedir. Buna göre elimizde hiçbir değer yok sadece registerler vardır.
mov dword ptr [esi] ,eax =EAX deki değeri-ESI ile işaretlenen 32 bit hafıza bölgesine yaz
mov byte ptr [eax],bl = Aynı şekilde fakat burada ki değer 8 bit
mov dword ptr [esi],ebx =İlk örnek ile aynı
Burada şu ana kadar bahsetmediğim birkaç kelime var onları anlatmak istiyorum arkadaşlar.Örneğin byte ptr ve [ ] parentez şimdi bunları kısaca açıklayacağım.
byte ptr : Açılımı arkadaşlar (byte pointer) demektir.Eğer yükleyeceğiniz değer 1 byte (8 Bit) cinsinden bir değer ise bunu işlemciye bildirmek zorundasınız ,aksi takdirde hata verir. word ptr : Bu da arkadaşlar (word pointer) anlamındadır.Ve 16 bittir.Yükleyeceğiniz değer16 bitlik ise yine CPU ya bildirmek zorundasınız…
dword ptr : Bunun açılımı da arkadaşlar (double word pointer) demektir ,yani 16 bitlik 2 sayı anlamındadır.Doğal olarak da 32 bitlik (4 bayt) lık bir değeri temsil eder.
[ ] Parentez : Bu ise arkadaşlar kullanıldığı yerin bir hafıza (bellek) adresi olduğunu gösterir.Bir [ ] köşeli parentez görürseniz o gösterilen yerin hafıza adresi olduğunu bilin..
Dolaylı Adresleme :Bu adreslemede arkadaşlar ileride göreceğimiz PUSH ve POP komutuna benzer olarak istenilen bir hafıza adresine saklama işlemi yapılır. Bu bir register olabileceği gibi bağımsız bir değerde olabilir.Örneğin :
mov dword ptr [deneme],ebx mov word ptr [00364010] ,4252h
Böylece Registerler ve adreslemeler konusunu da bitirmiş oluyoruz.Ama siz başka makalelerde okuyarak bilginizi sağlamlaştırın derim çünkü değişik kaynaklar her zaman iyidir ama bu kadar anlaşılır olmayabilir .Bundan sonra stack olayına da değinip ,komutlara geçeceğiz.Stack olayı da iyi bilinmeli ve anlaşılmalı arkadaşlar bu nedenle buna da değinmek istiyorum.
STACK ( YIĞIN ) NEDİR :
Gelelim arkadaşlar Stack dediğimiz Yığın konusuna.Bu konuda oldukça basit bir konu yeter ki bu yazdıklarımı dikkatli okuyun.Şimdi program yazan arkadaşlar bilirler ,program yazarken bir değişken kullanırız.Mesela deriz ki; sayi= 24 bu bizim değişkenimizdir.Ve değiştirilmediği sürece hep 24 değerini saklayacak.Ama biz bu değişkene başka değerlerde almak ve 24 değerinin de kaybolmamasını istiyoruz.İşte böyle bir durumda CPU bilgileri geçici olarak saklamak için hem registerleri hem de stack dediğimiz bu bölgeyi geçici yerleşim bölgesi gibi kullanır.Yani bilgilerimizi geçici olarak bu yığına atar ve geri alır.Kısaca Stack, bilgilerin geçici olarak depolandığı bir bölümdür deriz.
Bu yığına giden bilgiler arkadaşlar word uzunluğunda olup en az 2 byte (16 bit) ‘dir.Bu stack alanının bilgisini SP (Stack Pointer) tutar ve buraya gelen verilerin uzunluğuna göre SP kendi değerini azaltır.Buradan değerler geri alındığında ise SP kendi değerini alınan verinin uzunluğu kadar artırır.Bu biraz karmaşık görünebilir ama değil çünkü biraz sonra bunu da bir örnekle anlatacağım .Bu yığına veriler PUSH ve POP komutları ile atılır ve geri alınır.Atarken PUSH komutunu ,alırken de POP komutunu kullanırız.Bunları komutlar bölümünde inceleyeceğiz zaten.
Gelelim şimdi SP in veri alırken değerini azaltması olayına.Arkadaşlar şimdi bir çok bölmelerden oluşan bir kitaplık düşünün (Bu bizim Satck ‘ımız yani yığın bölgemiz).Bu kitaplığımız boş haliyle 100 adet kitap alabiliyor.Biz bu kitaplığa tutar da,5 adet kitap korsak ne olur?Kitaplığımızın %5 ‘i dolmuş olur ,yani boş alanı %95 ‘ e düşmüş yani azalmış oldu değil mi.Kitap alabilme yeri azaldı.İşte Stack ‘ta veri aldıkça boş olan yerleri azalıyor.Şimdi anladınız değil mi.
NOT: Birde unutmadan arkadaşlar bu stack’a atılan veriler ,en sondan başlayarak geri alınır.Yani Son giren veri ilk çıkar.Şöyle diyelim hani biz kitaplığa 5 adet kitap koymuştuk ya,işte bu kitapları geri alırken de ilk önce 5. kitabı sonra 4. sonra 3.-2. ve 1. kitabı alabiliriz.Stack ta da bu böyledir.Tıpkı iç içe açılan For –next döngüsü gibi.En son açılan döngü ilk önce kapatılır. VB ‘ ci olduğum için aklıma bu örnek geldi. | |
|