P. 1
Assembly Ders Notlari

Assembly Ders Notlari

|Views: 1,657|Likes:
Yayınlayan: ce10ur

More info:

Published by: ce10ur on Dec 07, 2011
Telif Hakkı:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

05/04/2013

pdf

text

original

Bu yazıda X86 işlemcilerine giriş yapıp Assembly programlama ile ilgili giriş bilgisi vermeye çalışacağım.

X86 NEDĐR ? X86 Intel’in ilk mikroişlemcilerinden olan 8086 ile ilgili programlama kurallarını ifade eden bir tanımlamadır. Intel’in önemli özelliklerinden biri olan "geriye dönük yazılım uyumluluğu" böyle bir tanımlamanın oluşmasını sağlamış. Şöyle ki; 8086 mikroişlemcisi olan bir bilgisayar sisteminde hazırladığınız herhangi bir assembly programı X86 uyumlu tüm bilgisayarlarda çalışır. 80286, 386, 486 SX veya DX, Pentium, Pentium III, AMD nin 286, 386 işlemcilerinde veya Nexgen, Cyrix’in aynı tür işlemcilerinde ve diğerlerinde bu program çalışacaktır. Bu demek oluyor ki yukarıda saydığımız tüm mikroişlemciler ve uyumlu olan diğerlerinin ortak bir yönü var. Bu ortak yönler ortak program kodların olması ve mikroişlemcilerinin temel mimarileri birbirinin aynı olmasıdır. Yeni bir mikroişlemci üretildiğinde, eski mikroişlemcilere uyumlu olması büyük bir avantajdır. Öyle olmasaydı bugün dünyada %90 oranında PC, X86 uyumlu işlemci kullanıyor olmazdı. Bu yüzden mikroişlemci pazarının bu büyük dilimini birkaç firma paylaşıyor, aslan payını Intel, daha sonra AMD geliyor, Cyrix ve Nexgen gibi diğer mikroişlemci üreten firmaların isimlerini pek duymuyoruz. X86 tabanlı sistemlerin mimarisi birbirine benzer. Birde X86 tabanlı olmayan sistemler vardır. Apple firmasının iMAC bilgisayarları, yada SUN Microsystems firmasının sistemleri X86 tabanlı mikroişlemciler kullanmadıkları için bu tür bilgisayarda çalışan programlar X86 tabanlı sistemlerde çalışmazlar. Şunu unutmayalım; dünyada yaklaşık %90 oranında X86 uyumlu PC sistemi kullanılıyor. Bu yüzden bu X86 assembly dili diğer assembly dillerinden daha geçerli bir programlama dilidir. ASSEMBLY PROGRAMA DĐLĐ VE DĐĞERLERĐ ? Assembly programlama dilini 3 kelime ile tanımlayacak olursak bunlar; GÜÇLÜ, HIZLI ve KISA olurdu. Bu demek oluyor ki aynı programı assembly dili ile ve C++ programlama dili ile yaparsak, iki programın boyutlarına baktığımızda assembly ile yazılan daha kısa olduğunu görürüz, aynı zamanda mikroişlemciyi ve hafızayı daha verimli kullandığı için assembly dilinde yazılan program diğerlerine nazaran daha güçlü olacaktır, son olarak assembly dilinde yazılan program diğerine oranla çok daha hızlı çalışır. Son zamanlarda mikroişlemcilerin hızları GHz’ler (giga hertz ciga herz diye okunur) mertebesine çıktığından assembly dilinin en büyük özelliği olan hızlılığı artık pek popüler değildir. Kullanıcıya, 2GHz hızındaki bir CPU da hemen hemen her uygulama aynı hızda çalışıyor gibi görünür. Buna rağmen C gibi yüksek düzey programlama dilleri ile hazırlanan büyük projelerde işlemciyi çok fazla meşgul edecek olan kod bölümleri assembly rutinleri çağrılarak yapılmaktadır.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

NEDEN ASSEMBLY? X86 Assembly dilini öğrenmek kolaydır ama bu dilde proje hazırlamak insanı çileden çıkartabilir. Bu yüzden günümüzde X86 assembly dili yerine, daha çok endüstriyel alanda kullanılan microcontroller chip’lerin assembly dili kullanılmaktadır. Bir programcı assembly dilinde büyük uygulamalar hazırlamaz (genellikle). Bunun nedeni üst düzey programlama dilleri olan delphi, C, C++, Pascal’a göre daha dikkat gerektirir ve kod yazımı daha zordur. Programcı assembly dilinde proje hazırlayacaksa kullandığı sistemin mikroişlemcisini ve hafıza haritasının yanında, sistemin donanımında iyi bilmesi gerekir. Her şeyden önemlisi zamandır ki sadece assembly dili ile PC uygulamaları geliştirmek iğne ile kuyu açmaya benzer. Assembly alt düzey bir programlama dilidir yalnız alt düzey kelimesini yanlış anlamayın, bu kelime bu dilin işlemciye ve hafızaya olan yakınlığını belirtir, üst düzey diller ise daha çok programcıya yani insana yakındır. Bu yüzden assembly dilinin özel kullanım alanları vardır. Kısaca bunları söyle sıralayabiliriz. 1234567Bilgisayar sistemini yakından tanımak için, Device driver (cihaz sürücüleri) yazmak için, Chip’lere program yüklemek için (PIC, microcontroller gibi...) Đşletim sistemlerinin yapımında (OS), Şifre kırma ve Hacking işlemleri için, Virüs programları yazmak için, Elektronik tablo’lama (Excel gibi) programlarında.

ĐLK X86 ASSEMBLY KODLARIMIZ PC platformunda doğrudan hafızaya sembolik kod kullanmadan yazacağımız bu programcık için herhangi bir editör ve derleyici download etmenize gerek yok. DOS veya Windows işletim sistemine sahip bir PC kullanmanız kafidir. Sırasıyla şunları yapın; 1- Başlat menüsünden çalıştır’ı tıklayıp cmd programını çalıştırın. Şayet Windows 98 kullanıyorsanız başlat menüsünden MSDOS komut istemini çalıştırmanız gerekiyor. Hala DOS işletim sistemini kullanıyorsanız bilgisayarınızın power butonuna basmanız yeterlidir :) yani halihazırda komut isteminde olan bir trex siniz.

2- Komut istemindeyken cd\ yazın ve root dizinine geçin burada kendinize md asm yazarak asm adında bir klasör oluşturun ve cd asm komutu ile klasörün içine girin. Tabi ki klasör oluşturmak için bu kadar eziyet çekmenize gerek yok,

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

amacımız biraz nostalji. Maksat projemiz bir klasörde oluşsun.

3- Debug yazıp enter tuşuna basın. Resimdeki görüldüğü gibi debug programı çalıştırıldığında ekranın solunda bir - simgesi görülür ve bu programla harikalar yapabilirsiniz :)

4- E 0100 yazıp enter tuşuna basınız.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

ba 0b 01 cd 21 b4 4c cd 21 4d 45 52 48 41 42 41 20 41 53 53 45 4d 42 4c 59 24 değerleri içinde aynı işlemi tekrar edin :) Şayet arada bir yerlerde hata yaparsanız klavyeden enter tuşuna basıp 4.5. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . adımdan itibaren yeniden başlayın. adımdaki gibi olunca g tuşuna basıp ardından son olarak enter tuşuna tekrar basın.b4 yazıp boşluk tuşuna (space bar) basın. 6. Đşlem bitince ekran görüntüsü aşağıdaki gibi olacaktır. 09 yazıp boşluk tuşuna basın.Klavyeden Enter tuşuna basın ve ekran görüntüsü 3.

Bunu yaparken kod yazacağımız adreste hali hazırda hangi kod’un olduğunu görme gibi bir lükse de sahiptik. düzenlememizi sağlayan bir programdır. Adresler her zaman bizim onları doldurmamız veya erişmemiz için hali hazırda beklerler. Đnsan oğlu rahatına pek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . komut isteminin en solunda 152F:0100 gibi bazı rakamlar gördünüz. Biraz önce Debug programının kendisi içinde kullanacağımız e (enter) ve g (go) komutlarını kullandık. ama 0100 aynıdır. CPU programcının sadık kölesi olduğundan aynen denileni yapar. silinir. değiştirilir fakat bu süreçte değişmeyen tek şey hafıza adresidir. Hala hevesiniz kırılmadıysa :) neler yaptığımızı tek-tek açıklayalım. işte : simgesi ile ikiye ayrılmış bu 8 rakam hafızanın adresidir. En fazla 2 makale sonra Debug programını kullanmayı bırakıp daha jan-jan lı debuger programları kullanacağız. Çok ilkel bir program olmasına rağmen beynimizin derinliklerine PC’nin yapısını kazıyacak olan ve bir assembly programcısının bilgisayara ne şekilde bakması gerektiği konusunda yardımcı olacak yegane programlardandır. Daha sonra hexadecimal gösterimin anlaşılması zor olduğundan sembolik kodlar ile yazılan Assembly programlama dili geliştirilmiştir. ta ki ev yıkılana kadar :) E komutu ile bu örnekte hafızanın 152F:0100 adresi ile 152F:011B adresleri arasını makine kodları ile doldurduk. Zamanla binary gösterim biraz fazla yer kapladığından hexadecimal gösterim benimsenmiştir. buradaki 152F sizin bilgisayarınızda farklı olabilir. tesadüfen hepsi 00’dı. "Ey CPU yazdığım bu kodları sırasıyla çalıştır bakayım".Yukarıdaki ekran çıktısında görüldüğü gibi konsol ekranına MERHABA ASSEMBLY yazdırdık ve debug programından çıkıp komut istemine geri döndük. Eve anne gelir baba gelir arkadaş gelir bazen tatilde boş kalır yani evin içindekiler değişkendir ama ama ev adresi her zaman sabit kalır. hafıza ve CPU’nun içindekileri görmemizi. E komutu ile hafızaya giriş yaptığımızı söyledik. şimdilik böyle idare edelim. e komutu hafızaya kod girişi yapmamızı sağlar ve g komutu ise CPU’ya şu sihirli kelimeyi söylememizi sağlar. Kodlar hafızaya yazılır. bunu evinizin adresine benzetebilirsiniz. Makine kodları CPU’nun anlayacağı yegane kodlardır ve 2’lik (binary) yada 16’lık (hexadecimal) gösterimle ifade edilirler. Debug programı Microsoft’un tüm işletim sistemlerinde bulunan.

daha çok donanımla alakalıdır. Đşte biz buna halk dilinde program çalışıyor diyoruz.düşkün olduğundan :) daha sonra. Bu söz her adrese en fazla 1 byte’lık kod yazabileceğinizi anlatır. Dosya oluşturma işlemi için ilk önce CPU’nun CX kaydedicisine (CX ne yahu. Ama çok istek gelirse bu şarkıyıda sizler için söyleyebilirim :) BU KODLARI ÇOK SEVDĐYSENĐZ GELĐN BUNLARI SAKLAMAK ĐÇĐN BĐR PROGRAM DOSYASI OLUŞTURALIM Bu işlemi yapmak için öncelikle programda ne kadar kod kullandığımızı bilmemiz yani programın byte cinsinden uzunluğunu bilmemiz gerekir. toplam 28 hafıza konumuna (memory location) kod yazdık ve göreceksiniz biraz sonra programı derleyip dosya haline getirince dosya boyutu 28 byte olacak. X86 PC’lerin hafızası byte adreslenebilir diye bir programcı ata sözü vardır. kaydedicide ne demek kardeşim dediğinizi duyar gibiyim merak etmeyin bu terimler ileride hiç ağzınızdan düşmeyecek) 28’in hex. Programı mikroişlemci (CPU) çalıştırır ve programcı tarafından kısmen kullanılabilir.adıma geri dönmeniz gerekiyor çünkü kodlar hafızadan silinmiş olabilir) HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bu süreç programcıları fazla ilgilendirmez. (Bu sıralamada Assembly programlama dilide A oluyor tabi ki) Programlama dilleri ABC diye devam derken C harfini çok seven programcılar buna ++ ve # gibi aksesuarlar takarak değişik varyasyonlar denemişler ve çokta başarılı olmuşlardır :) Neyse lafı fazla uzatmadan ve "ey programcı geçmişini bilmeyen geleceğinden bir haberdardır" diyerek konumuz geri dönelim. Kodları kendi elimizle teker teker girdiğimizden uzunluğunun 28 byte olduğunu biliyoruz. kod yazması ve anlaşılması daha kolay olan B Programlama dilini geliştirmiş bu da yetmemiş C dilini geliştirmiştir. bu yüzden ayrıntıya girmiyorum.icra et sürecini başlatır. Daha sonra debug’ın N komutu ile dosyaya isim vereceğiz ve son olarak W komutu ile harddiskimize kayıt yapacağız. Lütfen aşağıdaki şekli inceleyiniz.kodunu çöz . (Yalnız komut istemi penceresini kapattıysanız işiniz yaş 1. adımdaki şekilden faydalanınız. Bizde burada öyle yaptık zaten. Son olarak debug’tan çıkıp komut istemine geri döneceğiz ve oluşturduğumuz programı çalıştıracağız. Debug’ın g komutu ise meşhur fetch-decode-execute sürecini yani hafızadan al getir . Emin olmak için 5. karşılığı olan 1C’yi yazacağız.

Programımızı bir dosya haline getirdik. çünkü bir sonraki makalemizde bu dosyadan faydalanıp sembolik kodlardan oluşan assembly diline geçiş yapacağız ve eksik kalan noktaları tamamlayacağız. Siz bu arada HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Microsoft’un işletim sistemlerinde 2 tür program dosyası mevcuttur ve bunlar dosya ismini takip eden EXE ve COM uzantıları (file extensions) ile tanınırlar. o zaman hemen çalıştıralım. Programımız konsol ekranına MERHABA ASSEMBLY yazdı ve işletim sistemi tarafından sonlandırıldı.com adlı dosyamız oluşturuldu ve çalıştırılmaya hazır. Bir burada COM olanından oluşturduk. sabretmek lazım :) Bu programı bir sonraki makalemize kadar silmeyin. endişelenmeye gerek yok EXE uzantılı dosya’da oluşturacağız ve COM ile EXE arasında ne gibi farklar var onları da göreceğiz fakat bunlar bizim için henüz çok ileri konular.Meşhur DOS komutlarından olan "dir" ile tekrar bir nostalji yapıp dosyamızı görelim :) Görüldüğü üzere 28 byte’lık merhaba.

işareti göreceksiniz ve başka hiçbir şey olmamış görünecek ama aslında merhaba. Assembly programlama dilinde ayrıntılar çok önemlidir ve her bir ayrıntı kendi çapında bir araştırma konusu olabilir.boş durmayıp bu kodlar üzerinde oynamalar yapabilirsiniz özellikle 12. Ayrıca Debug programının diğer komutlarını görmek için işaretinin görüldüğü modda ? yazıp enter tuşuna basınız. program simgesinin üzerine gelip mouse ile tık-tık yapıldığı andan itibaren. Sonra bu programı yine debug ile bir dosya haline getirmiştik. programın yüklenip çalıştırılmasına kadar sistemde neler ve nasıl yapılıyor? Öyle değil mi? Nelerin yapıldığını geçen HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Geçen makalemizde debug programını tanımış ve makine kodları ile küçük bir program hazırlamıştık. Şimdi bu dosya ile biraz daha yakından ilgilenelim. Şekil 1 . Yine komut istemine geçiş yapıp debug programını şekildeki gibi çalıştıralım. programın simgesine mouse ile tıklayarak yapıyorlar ve hatta bu şekilde program hafızaya yüklendikten sonra birde işletim sistemi tarafından çalıştırılıyor. Şimdi aklınıza şu soru gelmeli. Başka bir programlama dili biliyorsanız aynı yazıyı yazan programı o programa dili ile yazıp dosya boyutunu buradaki ile karşılaştırınız. koddan itibaren son koda kadar olanları değiştirin (son kod hariç) çünkü bunlar MERHABA ASSEMBLY yazısının ASCII kod karşılığıdır.Debug ile program yükleme Ekranın solunda bir . Bunun için ASCII kod tablosundan faydalanabilirsiniz.com adlı program dosyasını oluşturan makine kodlarını çoktan hafızaya yüklediniz bile. örneğin burada yaptığınız program yükleme işlemini windows kullanıcıları. Bir sonraki makaleye kadar esen kalın ve kendinize iyi davranın. Not:Geçen makalemizdeki dosyayı kaybettiyseniz buradan indirin ve C:\ dizininde asm adında bir klasör oluşturun ve bu dosyayı oraya kopyalayın. Makine kodlarını görmeden önce sizlere küçük bir tavsiye vermek istiyorum.

Bizde burada kodları ekranda gösterdik. Neden 0100h adresinden itibaren hafızaya yerleşti? sorusunun yanıtı program dosyasının . program şu anda hafızada ve 0100h offset adresinden itibaren yüklenmiş durumda.Debug’ın "d" komutu Debug’ın d komutu "dump" anlamına gelip programlama aleminde kodları ekrana yada kağıda dökmek gibi bir anlamı vardır.com uzantılı olmasından kaynaklanır ve geçen makalemizde açıkladığımız gibi sonraki makalelerde ele alınacak bir konudur. Tabi ki ekrana yazdırılacak olan MERHABA ASSEMBLY burada data sınıfına giriyor peki komutlar nerede? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Hemen kodları görelim o zaman.makalemizi takip ettiyseniz tahmin edebilirsiniz ama nasıl yapıldığına gelince o iş biraz sistem programcılığına giriyor yani bizim için biraz erken. Burada önemli olan husus sizin 0100 offset adresi ile 010B offset adresleri arasında kalan makine kodlarından bazılarının komut kodları bazılarının ise data (veri) kodları olduğunu bilmenizdir. Şekil 2 . Neyse biz konumuza geri dönelim.

Kırmızı ile işaretli olan kısımdan öncekiler (dikkat bu kısımdan sonraki kodlar bizi ilgilendirmiyor) yani 0100h ile 010Ah adresleri arasında kalan kısım naçizane komut kodlarımızdır. Kodları HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Şekil 3 . Tabi ki assembly dili bizlere daha yakın bir dildir. Assembly dilindeki bu gösterim aynı zamanda sembolik kodlar olarak ta bilinir.. Tabi ki bu şekli ile bize pek bir şey çağrıştırmıyorlar şayet bunlar bizlerin anlayabileceği dile biraz yakın olsaydı anlardık. Şekil 4 .Makine ve Assembly Dili Yan yana Yukarıdaki şekilde makine kodlarını sarı assembly kodlarını kırmızı çerçevede görebilirsiniz.Datalarımız..

010B için operand kısmı makine dilinde 0B01 olarak ters bir biçimdedir? Opcode BA Operand 0B 01 Tablo 2 : Opcode ve Operand Bu sorların cevabı X86 uyumlu mikroişlemci mimarisini anlayarak bulabilirsiniz. 2 byte’lık olan opcode’ları 0F ile başlar. BA0B01 MOV DX. Bunlar opcode ve operand alanlarıdır.010B Burda 3 byte’lık bir komut satırı. birincisi neden MOV komutunun makine dilinde 2 tane farklı opcode’u var? (yani B4 ve BA’dan bahsediyoruz ve aslında MOV komutunun makine kod karşılığı 2 den de fazladır) ve ikinci soru neden MOV DX. Intel’in opcode uzunluğu 1 yada 2 byte’lıktır. Bu tür konuları öğrencilik yıllarımdayken HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Böylece ortaya karma karışık bir komut seti çıkar. yani biz burada 0100h-010Ah offset adresleri arasınındaki makine kodlarını assembly dilinde görmüş olduk. bunlar kitaplarda little endian byte ordering ve big endian byte ordering olarak geçer. bu yüzdende Intel’in x86 ailesi CISC (Complex Instruction Set Computers) olarak anılırlar.4 veya 8 byte’lık olabilir. Şimdi yukarıdaki şekilde gördüğümüz makine ve assembly kodlarını karşılaştıralım. Đlk olarak B4 veya BA MOV’un karşılığı gibi görünse de öyle değildir.2. Tabi ki birde düz olarak byte’ları yerleştirme olayı var. opcode 1 byte’lık operand 2 byte’lık. Operandlar ise herzaman opcode’lardan sonra gelir ve X86 mimarisinde 1. Ama şimdi kafamızda 2 tane soru işareti var. Đkinci sorunun cevabı ise x86 ailesindeki işlemcilerin hafızaya erişme şekillerinin ters sıralı olmasından kaynaklanır. B409 MOV AH. u dan sonra gelen 0100 010A ise hafıza aralığıdır. B4= MOV AH’ın BA=MOV DX’in opcode karşılığıdır. Burada sadece opcode ile operandı ayırmanız yeterlidir assembly dilindeki ifadeleri ne anlama geldiğini şimdilik önemsemeyin.09 Assembly dilindeki MOV AH. Yani ikisi de farklı assembly ifadeleridir ve farklı opcode’larının olması son derece normaldir.09’un makine dilindeki karşılığının B409 olduğu görülüyor ve assembly programcıları "B409" ile gösterilen makine dilindeki bu ifadeyi iki kısıma ayırırlar.assembly dilinde görmek için debug’ın "u" (unassembly) komutunu kullandık. Opcode B4 Operand 09 Tablo 1 : Opcode ve Operand Buradaki B4 opcode’u işlenecek olan asıl emirdir ve ancak mikroişlemci (CPU) tarafından kodu çözüldükten sonra 09 operanıda komut işleme sürecine katılır. Aslında byte düzenleri çok çok ileri seviyede önemli konulardır ayrıca opcode’ları gösterirken seçilen bu hexadecimal değerlerde (B4 ve BA gibi) rastgele seçilmiş değerler değildir. Biz şimdilik hep 1 byte’lık opcodelar ile çalışacağız.

araştırmıştım, gerçekten epey zevkli konular, genellikle yüksek lisans ve doktora sınıflarında instruction anatomy (komut anatomisi) başlığı altında incelenen konulardır. Programcılık açısından ise sadece byte düzeni önemlidir. Bu yüzden burada sadece bun iki kavramı açıklayacağım. Little Endian Byte Ordering: Hafızda yüklenecek olan byte’lar düşük değerlikli kısmından itibaren yazılır. Örneğin 1234 gibi iki byte’lık bir veriyi hafızaya 0100 offset adresinden itibaren yazdığınızı düşünelim, bu işlem bitip hafızaya baktığınızda göreceğiniz şey 0100=34, 0101=12 olacaktır.

Şekil 5 - Little endian byte düzeni

Burada debug’ın "a" (assembly) komutunu vererek assembly dilinde program yazma moduna geçtik ve dw talimatı ile hafızaya 1234 değerini girdik ve hafızaya, önce bu sayının düşük değerlikli byte’ı sonrada yüksek değerlikli byte’ı yazıldı. Big Endian Byte Ordering: Hafızaya yüklenecek byte’lar en yüksek değerlikli kısmından itibaren yazılır aynen bizim kağıt üstüne sayıları yazdığımız gibi. Sizlere burada bir tanede big endian örneği vermek isterdim fakat şu anda elimde bir Apple PowerPC olmasına rağmen MAC OSX işletim sistemi için debugger yok :( Aşağıdaki tablo hangi sistemlerin hangi byte düzenini kullandığını gösteriyor. Đşletim Sistemi Tru64 UNIX HP-UX AIX Byte Düzeni littleendian bigendian bigendian

Đşlemci Türü Digital Alpha AXP Hewlett Packard PARISC IBM RS/6000

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

Linux Intel x86 Windows Solaris x86 Motorola PowerPC Macintosh OS X SunOS Sun SPARC Solaris SGI R4000 Irix

littleendian littleendian littleendian bigendian bigendian bigendian bigendian

Tablo 3 : Üreticilerin çoğu big-endian tercih ederken dünyada en çok kullanılan little-endian byte düzeni :)

CD21 INT 21 B44C MOV AH,4C CD21 INT 21 INT 21’de bir byte’lık opcode’u ve bir byte’lık operandı olan başka bir komut satırı. Bu arada MOV AH,4C nin opcode’u ile yukarıda açıkladığımız MOV AH,09’un opcode’larının aynı olduğuna dikkatinizi çekerim. Buraya kadar ; 1- Neo’nun Matrix’i gördüğü gibi bizlerde hafızaya baktığımızda orada gördüğümüz byte’ları nasıl yorumlayacağımızı gördük, bu yolda kendinizi geliştirmeye kalkarsanız sizde belki bir gün Matrix’i görebilirsiniz :) Yıllardan beri ben hafıza dökümlerine bakarım onlarda ekrandan doğru bana bakarlar ama program boyutu 10Kb’ı geçince insan halüsülasyonlar görmeye başlıyor onuda belirteyim :) 2- Makine kodları ile assembly kodları arasındaki bağıntıyı gördük, Borland gibi bir derleyici (compiler) yazan bir firma kurmak isterseniz, bu alanda en az bir doktora tezi vermeniz gerekir. Yani for (int i=0 ; i<100 ; i++) gibi bir ifadenin derleyici ile makine diline dönüşmesi zannettiğinizden daha karışıktır. Özetle buraya kadar derin konuların giriş kısımları anlatıldı. Şimdi sıra assembly kodlarına bir hacker gibi değil de bir programmer gözüyle bakmaya geldi. DEĞĐŞKENLERĐ DEKLARE ETMEK Örneğin 2 sayıyı toplayan program yazmayı düşünelim. Bunu 2 değişik şekilde yapabiliriz. Birincisi acil adresleme modu ile; MOV ADD AL,5 AL,4

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

Bu örnekte hiçbir değişken tanımlanmamıştır ve bu program parçası sadece 5 ile 4 ü toplar ve sonucu işlemcinin içindeki AL kaydedicisinde saklar. Tabi bu programın ne kadar kullanışlı olduğunu artık siz tahmin edin. Oysa bu sayıları birer değişken olarak tanımlasaydık daha esnek bir program hazırlamış olurduk. .DATA sayi1 DB 5 sayi2 DB 4 toplam DB ? . . . .CODE . . MOV AL,sayi1 ADD AL,sayi2 MOV toplam,AL Yukarıdaki program parçasında 3 adet bir byte’lık değişken tanımlanmıştır. Bunlar sayi1, sayi2 ve toplam değişkenleridir. Aslında bu yazdığımız satırlar assembler’a bir demeç şeklindedir. Assembler programımızı derlerken, hafızada bizim kullanmamız için 3 byte’lık alan ayıracak ve bu alanlardan birine 5 diğerine 4 değerlerini yerleştirecektir. Toplam değişkeninin değeri program çalıştığında önemli olacağından dolayı, onun değeri henüz atanmamış fakat şundan da emin olun ki o adreste muhakkak bir değer mevcuttur. Gördüğünüz gibi değişkenlerini isimleri, türleri ve değerleri mevcut. Değişken ismi (sayi1 gibi) aslında bir offset adresidir ve kullanımı seçimliktir. Şayet değişken tanımlarken isim kullanmazsanız assembler yine hafızada değişkenin türüne göre yer ayırır. Fakat böyle bir durumda değişkeni programınızın içinde kullanmak için adresini (ds:0000 gibi) bilmeniz gerekir. Çok sayıda değişken tanımlarken bu adresleri hesaplamak güç olacağından dolayı değişkenlere isim vermemek pek tavsiye edilmez. Değişkenin türü ise boyutu ile alaklıdır, örneğin DB ile değişkenimizin 1 byte’lık olacağını belirtiyoruz. Son olarak değişkenin değeri tabi ki bir rakam yada sayı olmak durumunda. Şayet başlangıçta değer önemli değilse ? operatörünü kullanabilirsiniz. Kaynak kodda değişkenleri bu şekilde yazarak assemblera hafızada yer tahsis etmesini söylemiş, bir başka deyişle değişken deklare etmiş oluyoruz. Đşaret Karmaşası 1 byte’lık bir hafıza alanına ne sığar? Toplam 256 adet farklı değer 1 byte ile tanımlanabilir. Bunlar onluk düzende 0-255 arası sayılar veya -128’den 127 ye kadar olan işaretli sayılar olabilir. Kafanız karışmasın bu değerleri aslında binary olarak düşünmek lazım, çünkü 0...255 ve -128...127 arası sayılar toplam 512 adet ediyor. Aslında, bunlar sadece 1’lerin ve 0’ların kombinasyonlarıdır. Yani 1 byte 0000 00002 ile 1111 11112 arasında değişen kombinasyonlardan oluşur. Günlük hayatımızda işaretli bir sayıyı tanımlamak ne kadarda kolay değil mi? Başına - işaretini getirdiğimiz zaman işlem tamamdır. Fakat bilgisayarlarda 1 ve 0 dan başka kullanacağınız bir değer yok. Đşaretli veya işaretsiz sayılar, harfler, metinler, resimler, mp3’ler ve Tomb Raider :) tamamen 1 ve 0’lardan oluşur.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

Bunu tam tersi de olabilir. i j k db byte sbyte 0 255 -1 . Bu işlemde artan 1 bitlik değer ilkokul matematiğinden bildiğimiz elde’dir ve bu elde işlemci durum kaydedicisinin C (carry) bitinde saklanır. Şekil 1 .MASM için alternatif direktif HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Şimdilik siz matematiksel hesaplamalar yaparken alanlarını kısıtlı olduğunu göz ardı etmeyin. Ayrıca bilgisayarın bu hesap mantığı ile pozitif bir sayı bir başka pozitif sayı ile toplandığında negatif bir değer de elde edilebilir.1 byte’lık bir değer 1 byte’lık başka bir değerle toplanınca sonuç 1 byte’lık olmak zorundadır. ancak o zaman anlam kazanırlar. 255’tir.MASM için alternatif direktif . O zaman işaretli ve işaretsiz sayılar neye göre belirlenecek? Boyutlar ve işlemci durum kaydedicisi (flag register) burada imdadımıza yetişiyor. işlemci durum kaydedicisini anlatırken işaret ve boyut taşması olarak inceleyeceğiz. Örneğin 1111 1111 değeri onluk düzende 255’mi yoksa -1’mi. 1 byte’lık bir değer 1 byte’lık başka bir değerle toplanınca sonuç bir byte’lık olmak zorundadır. DB Đngilizce’de Define Byte yani byte tanımla anlamına gelir. çünkü ayrılan fiziksel alan bu kadardır. Bu direktif ile hafızada 1 byte’lık bir alan tahsis eder ve bu alana adresi ile erişebilirsiniz. Biz bunları ilerleyen makalelerimizde. MASM ile DB direktifi yerine byte yada sbyte direktiflerini de kullanabilirsiniz. sonuç olarak maksimum 255 değerini gösteren program demek şu anda daha doğru olur :) BASĐT DEĞĐŞKENLER Byte Değişkenleri Bir byte boyutunda değerleri deklare etmek istiyorsak genellikle DB direktifini kullanıyoruz. Bu kargaşa tamamen boyutların sınırlı olmasından kaynaklanıyor.Đşte bu 1 ve 0’ları program içinde yorumlamak önemlidir. çünkü 1 ile toplandığında 1 byte’lık alanda 0000 00002 değeri elde edilir ve elde biti oluşur. Yani 2 sayıyı toplayan program yerine. Daha önce işlemci durum kaydedicisinin bitsel olarak önemli olduğundan bahsetmiştim. çünkü 1111 11112 = 20+21+22+23+24+25+26+27 = 255 -1’dir. fakat sonuçta assembler’ın yapacağı iş aynıdır. Bu bağlamda bizim için alt seviyede önemli olan 1 ve 0’lardır. Aslında işlemci (CPU) sadece matematiksel. mantıksal ve veri taşıma işlemleri yapar.

-150" gibi 1 byte’a sığmayacak değerleri bu değişkenlere atamaktır.483. Yapılamayacak olan ise "mov i.967. Ayrılan Hafıza Alanı : 1 Byte Tanımlanabilecek Değer Aralığı: -128..648..255 Word Değişkenler DW 8086’dan 80286 işlemcisine kadar offset adresleri.. 125" komutu ile pozitif bir değer atayabiliriz. Ayrılan Hafıza Alanı : 2 Byte Tanımlanabilecek Değer Aralığı: -32768. sayi1 sayi2 isayi1 sayi_0 sayi_eksi pointer dd dd dd dd dd dd ? ? ? 0 -1 4000000000 sayi2 sayi_enbuyuk dd DD direktifi ile.295 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Ayrılan Hafıza Alanı : 4 Byte Tanımlanabilecek Değer Aralığı: -2..Yukarıdaki üç tanımlama farklı gibi gözükse de assembly dili yazımı değişkenleri tanımlarken boyut dışında bir sınır koymaz. işaretli ve işaretsiz tamsayılar tanımlamak için kullanılan en geniş veri tipiydi. Örneğin k değişkenine sonradan "mov k.. MASM için word ve sword direktifleri de aynı işi görür.65535 Double Word Değişkenler 4 byte’lık değişkenler tanımlamak için kullanılır. DB direktifi ile.... 300" veya "mov j.65535 arasındaki tam sayları DW direktifi ile deklare edebiliriz. MASM ile dword. DD direktifi ile bu türdeki değişkeleri tanımlayabilirsiniz. -32768. sdword direktiflerini de kullanabilirsiniz.147. sayi1 sayi2 isayi1 sayi_0 sayi_eksi pointer dw dw dw dw dw dw ? ? ? 0 -1 65535 sayi1 sayi_enbuyuk dw Özetle DW direktifi ile.4. Word değişkenler hafızada 16 bit yani 2 byte’lık alan kaplarlar.294.

BX. p bir değişken olsun. Örnekte AX kaydedicisinin değeri pointer’ın işaret ettiği adresten alınacak 2 byte’lık değer ile değişecektir.ds:1000h komutu da aynı işi yapardı fakat pointer değişkeni kullanılmadığından sonradan pointer değerini değiştirip aynı komut satırı ile hafızanın başka bir bölgesine erişmek mümkün olmazdı. p ax. Far (uzak) pointer’lar ile hafızanın istediğiniz bölgesine erişip işlem yapabilirsiniz. 48 bitlik pointer (indeksleme amacıyla. çünkü x86 ailesinin henüz 64 bitlik genel amaçlı bir kaydedicisi yoktur. yani pointer 32 bitlik olmalıdır. Yukarıdaki direktiflerle ilgili ayrıntılı bilgileri kayar noktalı sayılarla işlemler başlığı altında ilerleyen makalelerimizde vereceğim. Bunlar near (yakın) ve far (uzak) pointer’lardır. [bx] . bu sayı ile doğrudan işlem yapamazsınız çünkü en büyük kaydedici 32 bitliktir. Yani bu direktif ile 64 bitlik bir tam sayı deklare ettiğinizde. BP.) aşmaması yada aşması durumunu ifade eder. SI ve DI kaydedicilerini erişeceğiniz uzak offsetler için herhangi bir segment kaydedicisini de (ki bu genellikle ES olur) erişmek istediğiniz segment için kullanabilirsiniz. DQ: 64 bitlik kayar noktalı sayları 64 bitlik tamsayıları deklare etmek için kullanılır. DT: Daha hassas (80 bitlik) kayar noktalı sayılar ve 10 byte’lık BCD değerleri deklare etmek için kullanılır. Aslında mov ax. Buradaki yakın ve uzak kavramı referans alınan adresin segmenti (64Kb.BX’e p pointerını yükle. Near pointer’ler 16 bitlik’tir ve bir segmentin offsetlerine erişmek için kullanılırlar. . DQ direktifi ile 8 ve DT direktifi ile 10 byte’lık değişkenler tanımlanır. Bir başka deyişle DS:1000h ve DS:1001h adresindeki değerler AX’e yüklenecek. 32 bitlik korumalı modda. Daha çok kayar noktalı sayıları deklare etmek için kullanılır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .p’nin gösterdiği konumdaki veriyi AX’e getir. 8 ve 10 Byte’lık Değişkenler DF direktifi ile 6. pointer near yani yakın bölgedeki bir adresi göstermiş oldu. p=1000h için aşağıdaki kodları inceleyelim. Bunun için pointer deklare edilirken DD direktifinin kullanılması gerekir. Bu direktif ile 6 byte’lık değişkenlerin tanımlanması mümkün olsa da 80386 ve sonrası işlemcilerde pointer olarak kullanılır. Bu işlem aynı segment içinde olduğundan dolayı. Fakat bu direktifler aslında kayar noktalı BCD (ikilik düzende kodlanmış onluk sayılar) sayılar için kullanılır. Bu 3 direktifin asıl kullanım amaçları aşağıda açıklanıyor. mov mov bx. offset adreslerini göstermek için kullanılan bir işaretçi) olarak kullanılır. Pointer Veri Tipleri Pointer işaretçi anlamına gelip adresleme modlarında gördüğümüz indeksli adresleme ile alakalıdır.6. Đsterseniz bunu bir örnek ile açıklamaya çalışalım. DF: 80386 ve üstü işlemcilerde. x86 uyumlu işlemciler iki tür pointer’ı desteklerler.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bu örnekte pointer 32 bitlik’tir ve erişeceğimiz segment:offset adresini gösterir. Bu işlemi yapan program aşağıdaki gibidir.5555:3333 adresine erişip. operandında gösterilen kaydediciye de (bu örnekte BX) düşük değerlikli 2 byte’ını (3333h) yükler. LES komutu ES kaydedicisine pointer değişkeninin yüksek değerlikli 2 byte’ını (5555h) yüklerken. buraya FFh değerini kopyalamaya çalışacağız. MOV ES:[BX]. AL komutu ile de 5555:3333 adresine AL deki FFh değeri kopyalanır.Uzak adreslere erişmek için 32 bitlik pointer’lar kullanılır. Aşağıdaki şekiller ile bu programın pointer kullanarak nasıl uzak adreslere eriştiğini görebilirsiniz. Şekil 2 . Kaynak kodları buradan download edebilirsiniz.

Şekil 3 .LES BX.Pointer değişkeni ilgili kaydedicilere yüklendikten sonra HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . P komutu işlenmeden önce ES ve BX’in durumu Şekil 4 .

taban adresi. word veya double word değişkenler dizileri oluşturabilir. çok boyutlu diziler ve yapıları başka bir makalede güzel örneklerle. Daha önceki makalelerimizde "Merhaba Assembly" yazısını ekrana yazdırmıştık. Diğer terimleride isterseniz aşağıdaki şekille açıklamaya çalışalım. amacına uygun bir şekilde anlatacağım.Diziler ile ilgili terimler. Burada dikkat edilmesi gereken en önemli nokta diziyi oluşturacak elemanların aynı türden olma koşuludur.5555:3333 adresine FF değeri yüklendikten sonra ÇOKLU DEĞĐŞKENLER Bu tür değişkenler birden fazla parçadan oluşur. Şu anda yazdığım karakterlerde hafızada bir dizi veri olarak saklanacak. Bu makalede sadece tek boyutlu dizileri anlatmaya çalışacağım. Tek boyutlu ve çok boyutlu diziler (arrays) ve yapılar (structures) bu tür değişkenlerdir. işte bu karakterlerde hafızada dizi olarak saklanır. Şekil 6 . Diziler Dizilerlerde diğer değişkenler gibi hafızaya yerleştirilmiş verilerden oluşur. bunlar indeks. Dizi kavramının yanında getirdiği bazı terimler vardır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Ardarda gelen byte. dizi elemanı ve eleman tipi’dir.Şekil 5 .

7 tane byte türünden elemandan oluşan bir . Eleman_Adresi = Taban_Adresi + ((Indeks . Eleman_Adresi = Taban_Adresi + ((Indeks . Dizinin elemanlarına erişmek için bu adres referans olarak alınabilir. Dizilerin Deklare Edilmesi Başlangıçta elemanların değerleri önemli değilse. . örneğin yukarıda ’Merhaba Assembly’ karakterlerinden oluşan byte türündeki dizinin taban adresi Yazi’dır.16 elemanlı bir karakter dizisi. Dizinin herhangi bir elemanına erişmek için kullanılacak klasik formül. 0. Bunun için formülümüz vardı. 105Eh Yukarıdaki dizinin 2. Elemanlar aynı olacaksa. 45. 11 dizi. Dizi DB 100 DUP (12h) .byte türünden 100 elemanlı bir dizi . Eleman_Adresi = WordDizi + 2 olarak bulunur.word türünden olduğundan dolayı hafızada 200 Buradak DUP direktifi ingilizcedeki duplicate (diğerinin aynısı) kelimesinin karşılığıdır. Elemanlar farklı ise.Đlk_Index) x Eleman_Boyutu) Bu formülde ilk_indeks 0 ise göz ardı edilebilir. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 7. bununla beraber dizinin ilk elemanının adresi taban adresidir. 567Ah. . hafızada Unutulmaması gerekir ki taban adresi dizinin başında yazdığımız etikettir. 67. Eleman_Adresi = WordDizi + ((2 .Dizinin tüm elemanlarının aynı türden olması gerektiğini söylemiştik. Dizi DB 100 DUP (?) Dizi DW 100 DUP (?) byte’lık alan kaplar. Son olarak dizinin ilk elemanından itibaren adresler artarak devam eder ve bu adreslerdeki her elemana indeks değerleri ile erişilir. Tek Boyutlu Dizilerin Elamanlarına Erişmek WordDizi DW 1. 45. Yazi DB ’Merhaba Assembly’ ascii kod karşılıkları saklanır. Dizi DB 32. elemanına erişmek demek o elemanın adresini bulmak ile aynı anlama gelir. 3F. 1234h. 99. Hafızaya 100 adet 12h yerleştirir.Đlk_Index) x Eleman_Boyutu) Bu formülü word tipindeki dizimize uygulayacak olursak.0) x 2) yada.

bx. Yildizlar DB 10 DUP (’*’) dizisinden aşağıdaki üçgeni ekrana yazdırmak gibi. AX’e dizinin 2. * ** *** **** Alın size ödev. ax. indeks değeri BX’e yükleniyor. Aynı işi yapan program parçası aşağıda verilmiştir. Daha fazla eleman deklare etmek için indeks değerinin boyutunu arttırmak gerekir ama bu durumda da dizi elemanlarının aynı türden olması şartını göz ardı etmemek gerekir. Birincisi ekrana bir dizi byte’ın ASCII görünümünü yazdırmak. Örneğin byte türünden bir dizi için bu teknikle en fazla 255 elemandan oluşan bir dizi deklare edebilirsiniz. WordDizi [bx] . sonra ona felsefi bir boyut ekleyip filim yapıyor :) Assembly Kodlarına Bir Assembly Programcısı Gibi Bakmak Yazdığımız programda iki tane iş yapılıyor. 2*bx işlemi yapılıyor. bx . mov add mov bx. elemanı (1234h) yükleniyor. Önemli olan dizinin elemanlarına erişmek için kullanılacak olan fonksiyonu assembly dilinde yazabilme kabiliyetidir. Bazen assembly programcıları dizilerini deklare ederken. böylece hem adresleme modlarını hem de tek boyutlu dizileri kavramış olursunuz. fakat bunları ilerleyen makalelerimizde açıklayacağım. dizinin ilk elemanı olarak indeks değerini koyarlar. Sakın zor demeyin elin oğlu dizilerden matrix türetip. Örneğin.Tabi ki bu işlemi bir program ile yapmak lazım. Diziler usta programcıların vazgeçemediği veri yapılarıdır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . ikincisi bilgisayarı tekrar kullanıcının ellerine bırakmak yani işletim sistemine geri dönüş. Tabi ki bu durumun doğruluğu görecelidir. 2 . bir daha ki makaleye kadar bu programı yazmaya çalışın. Dizi elemanlarına erişmek için çok değişik teknikler mevcut.

işlemcinin AH kaydedicisine 09.Assembly dilinde ekrana bir şey yazdıracağım! AAP.Peki nasıl olacak? TAP. fonksiyonu senin için birebir.Şekil 6 . Anladın mı? AAP. AAP. AAP. ikincisi fonksiyon numarası 4C olan "Terminate Program". sana bir sorum olacak ekrana MERHABA ASSEMBLY yazdırmak istiyorum ama ekran kartına byte’ları nasıl göndereceğimi bilmiyorum.INT 21’in 9. AAP. onu senin yerine işletim sistemi yapar zaten. geçen hafta bu programı yazarken algoritma falan hazırlamadık ama önce ekrana yazdır sonra çık mantığını için de algoritma yazılmaz herhalde :) Bu program DOS’un meşhur kesmelerinden (interrupt) 2 tanesini çağırdı aslında. Ha bu arada son karakterden sonra hafızaya bir $ işareti koy ki interrupt servisi yazılacak karakterlerin bittiğini anlasın. tecrübeli assembly programcısı (TAP) yeterli derecede bilgisi olan bir programcıyı ima ediyor. bana anlatırmısın lütfen? TAP. sonrada 21.Windows! TAP.Byte’ları ekran kartına göndermene gerek yok.Programımızın parçaları Yukarıdaki şekilde algoritmanızın assembly koduna dönüşmüş halini görüyorsunuz.Hangi işletim sistemini kullanıyorsun? AAP. fonksiyon olan "Display String". interrupt servisini çağır. Tamam.Merhaba TAP. Buradaki acemi assembly programcı (AAP) azıcık assembly bilgisi olan birini.Hafızaya dataları girer sonrada bunları ekran kartına gönderirim nasıl olsa ekran kartı daha sonraki işlemleri kendisi halleder. Bunları söyledikten sonra ne desem kafanız karışacak bu yüzden bu olayı daha iyi anlamanız için aşağıdaki diyalogu hazırladım. hımmm ben en iyisi bir bilene sorayım. DX kaydedicisine karakterlerin başlangıç adresini yaz. Acemi programcının kafasının içinden geçenler.Ama gönderme işlemini nasıl yapacağım.Anlar gibi oldum? Ama ben bu işi kendim yapamaz mıyım? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . birincisi 9. AAP.

(AAP’nin sonra tekrar gelip başka interrupt servislerini de soracağından endişelenerek) Hey AAP. çünkü ekrana yazdırma işleminden sonra programı sonlandırmamıştır. AAP.Bak AAP kardeş. Daha sonra AAP bilgisayarının başına gider yukarıdaki şekildeki programın ilk üç satırını yazar ve çalıştırır. MOV AH..TAP. TAP.Teşekkür ederim TAP sonra görüşürüz. AAP. Đlerleyen makalelerimizde interruptları daha yakından ele alacağız. Interruplar hakkında şimdilik bu bilgiler umarım sizi tatmin etmiştir. bak buradan diğer interrupt servislerine de bakabilirsin.4C ve INT 21 satırlarını da programına ekledikten sonra programı kusursuz çalışır.Kaydedicileri debug ile görmek için r (registers) komutunu kullanabilirsiniz. tabi ki ekranda MERHABA ASSEMBLY görünür ama komut istemindeki penceresini kilitlenir. bunları şimdilik mikroişlemci içindeki hafıza konumlarına (memory location) benzeyen yapılar olarak düşünün. Şekil 7 . hani lazım olur diye söylüyorum.. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bu konular gerçektende çok zevkli.Đşletim sistemi de bu demektir zaten AAP. kullanıcıya bilgisayarı kolayca kullandırabilmek. Sende bu hizmetlerden faydalanır ve Amerika’yı yeniden keşfetmeye gerek duymazsın. Windows gibi işletim sistemini yazan programcılar senin gibi programcıların ekrana bir şey yazmak isteyeceğini. AAP.Yaparsın tabi ama çok ekmek yemen lazım :) AAP. Yukarıdaki diyalog ta kaydediciler (register) diye bir kavram geçti. veya klavyeden bir bilgi alacağını yada yazıcıdan çıktı almak isteyeceğini düşünerek bazı küçük programları yazıp işletim sistemlerine gömmüşlerdir.Nasıl yani?(bu arada TAP’ın gülüşüne de kızar tabi) TAP. TAP. Bunun üzerine programı sonlandırmak için tekrar interrupt servislerini araştırmaya koyulur ve interrupt 21’in 4C fonksiyonunu keşfeder.Evet çok akıllıca düşünmüşler doğrusu. programcıya.. Kaydedicilerin listesini görmek için debug programını kullanabilirsiniz.Teşekkürler TAP..

LOOP komutu CX’in değeri kadar operandı ile belirtilen adrese dallanır. Bu işlemi karakterlerin hexadecimal kodlarını yazarak ta yapabilirsiniz bu sefer her bir karakterden sonra ". ASCII kod tablosuna bakacak olursanız 0A=LF yani Line Feed (bir satır aşağı) 0D=CR yani Carriage Return (Kursör satır başına) olduğunu görürsünüz. DX. Program yazarken elbette bunları kullanacağız ama şimdilik üzümünü yiyin bağını sormayın. Daha sonra programımız fonksiyon:4C interrupt 21 ile sonlanıyor. BP. Kafalar fazla karışmadan yeni bir uygulama yapalım. Aşağıdaki işlemleri takip edin.P.. debug ile assembly modunda hafızaya bir dizi karakter girmek için DB (Define Byte) talimatını kullanıyoruz. zaten CR ve LF kontrol karakterleri olduğundan dolayı standart ASCII kod tablosunda A. SP. string veri tipleri gibi. Şekil 8 .C. CX. Buradaki string’e dikkat. BX.bat uzantılı script dosyası hazırlayıp ilk programımızı 10 defa çalıştırmak bunlara dahil değil tabi :) ) Şimdi yazacağımız programda ilk programımızın ilk üç satırını 10 defa çalıştırıp sonra programı sonlandıracağız.X86 kaydedicilerinin AX. 10 defa Merhaba Assembly Yazdırıyoruz Tabi böyle bir işi yaptırmanın değişik yolları mevcut ( bir . aynı C’deki int. Talimatlar (daha sonra ayrıntılı bir şekilde göreceğiz) derleyiciye verilir yani opcode olarak dönüştürülmezler. C dilindeki for döngüsü gibi. double. burada dallanılacak adres 0103 offset adresidir ve bu işlem sayesinde ekrana 10 defa MERHABA ASSEMBLY yazılır. Burada CX kaydedicisine (0A)16=(10)10 değerini sayaç olarak yüklüyoruz.10 defa alt alta MERHABA ASSEMBLY yazan program Programı yukarıdaki gibi hafızaya girdikten sonra bir önceki makalemizden faydalanıp bu programı dosya haline getirin. DB’den sonra şayet byte’ları karakter olarak girmek isterseniz " " arasına yazmalısınız. diye adları vardır ve bunların hepsinin değişik işlevleri mevcuttur." koymanız gerekir. çünkü bağın yerini söylersem ve sizde gider o bağa bakarsanız iştahınız kaçabilir.. kod karşılıklarını kullanmak zorunda kaldık. INT 21 fonksiyon 9 ile yazdıracağınız karakter dizilerinin sonunda mutlaka 24=$ bulunmalı yoksa HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Burada her iki teknikte kullanılmıştır. byte’ları saymada sizler için pratik olur.Z gibi normal karakter olarak karşılıkları yoktur mecburen hex.

Programcılık ve elektroniğin sınır noktası budur aslında. bunun için program yazma işlemi bitince P (Proceed) komutunu kullanın T (Trace) komutu ile programınız içinden çağrılan interrupt servislerine de girebilirsiniz (ama çıkabilirmisiniz orasını bilemem) Debug’tan çıkmadan bir daha programınızı çalıştırmak için "r ip" komutunu kullanarak ip kaydedicisini 0100 yapın. Assembly programcıları kaydediciler. böylece programın başlangıç adresini doğru ayarlamış olursunuz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bir assembly programcısı keskin bakışlarını mikroişlemcinin içinden çekip :) sistemin tamamına baktığında bile.. hafıza veya sistemi oluşturan birimlerde dolaşan elektron akımlarını 1’ler ve sıfırlar olarak görürler ve genelde bu 1 ve 0’lardan enaz 8 tanesini yan yana gördüklerinde bir şeyler anlamaya veya yorumlamaya başlarlar. Bir assembly programcısı sadece mikroişlemci içindeki birkaç kaydediciyle ilgilenir. örneğin 0D karakterini kodlardan çıkartın yada CX’e yüklenen değeri değiştirin. Son olarak debug ile bu programı adım adım çalıştırabilirsiniz.Adım adım programı işlemek Bir sonraki makalemizde sayı düzenleri ile ilgili birkaç önemli noktayı. ve assembler konularını işleyeceğiz. Şekil 9 . Bunun dışındaki birimler genelde okullarda bilgilendirmek amacıyla verilir. örneğin CPU içinde bir ALU biriminin olduğunu bir çok programcı bilir ama bu birimin çalışması ile ilgilenmezler. Assembly programcısı sisteme nasıl bakıyor? Mikroişlemci bir çok karmaşık birimden oluşur. Bu programın kodları ile oynayarak konuyu daha iyi kavrayabilirsiniz.. Yorumlarınızı ve önerilerinizi bekliyorum.bu interrupt servisi hafızada 24 değerini bulana kadar ekrana yazma işlemine devam eder.. neyse ki programcılar donanımsal olarak sistemleri fazla yakından bilmek zorunda değillerdir. donanımların ve donanımları birbirine bağlayan birimlerin çalışması ile ilgili fazla birşey göremez yada görmesine gerek yoktur.

memory (RAMROM/Hafıza) ve I/O (Input-Output/Giriş-Çıkış) birimin olması gerekir. Yukarıdaki şekilde bu birimleri görüyorsunuz. bunun böyle olması gerekir yoksa işler kontrolden çıkabilir. Dikkat ederseniz bütün yollar CPU’ya çıkıyor. diğer birimler arsında doğrudan bir bağlantı yok. Ne demişler kontrolsüz güç. Elbette bu birimle birbirlerine yollar (bus) ile bağlı olmalı ve sistemin açılabilmesi için hafızasında bir firmware programının yüklü olması gerekir. Aslında her modern bilgisayarda DMA (Direct Memory Access/Doğrudan Bellek Erişimi) adında bir transfer yapısı mevcuttur fakat bu özellik kullanıcı tarafından kapatılabildiğinden dolayı birimler arasındaki en temel bağlantı yukarıdaki şekildeki gibidir.X ışınlı gözlerimiz PC üzerinde? Şekil 1 . güç değildir :) Konuyu fazla dağıtmadan isterseniz X ışınlı gözlerimizle CPU’ya zoom yapalım :) X ışınlı gözlerimiz CPU üzerinde? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . CD-ROM kilitlenmelerinde Ctrl+Alt+Del kombinasyonun zorda olsa çalışması bundan dolayıdır.PC’nin kabaca iç organizasyonu Bir sisteme bilgisayar diyebilmeniz için o sistemin en az 1 CPU. Ayrıca DMA özelliği kullanıldığında CPU veri transferinden elini ayağını tamamen değil kısmen çeker.

örneğin hafızaya bir veri yerleştirilmeden önce adres yolundan verinin yerleştirileceği hafıza adresinin bilgisi gönderilir. Bunu daha iyi anlamak için aşağıdaki animasyonu izleyebilirsiniz yada animasyonu offline izlemek için download edebilirsiniz.Şekil 2 . Bu üç birime programcının doğrudan müdahalesi söz konusu değildir. En temel 3 birimden biri olan ALU aritmetik ve mantıksal işlemleri yapan bir elektronik devredir. BUS dediğimiz bu yapılar birçok iletkenden oluşur. BIU ise komut kodlarının icrası ile ilgilenir yani emirleri icra eden birim olarak basitçe tanımlanabilir. Kontrol yolunda R/W (oku/yaz) gibi kontrol sinyalleri. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Mikroişlemcinin kabaca iç yapısı Sistemi içindeki birimleri birbirine bağlayan yollar. veri yolundan işlenecek veriler gidip gelir. mikroişlemcinin içinde de devam eder. Programcı sadece CPU içindeki kaydedicilere erişebilir. Adres yolu iste tek yönlüdür ve CPU’dan diğer birimlere doğru sinyal akışı olur. Kontrol ünitesi ise sistemdeki birimleri harekete geçirmek için kontrol sinyalleri üretir.

Base (EBX. aynı zamanda tüm sistemdeki en hızlı depolama birimleridir.Şekil 3 . BL): Accumulator gibi genel amaçlı ve hafıza erişiminde indexleri göstermede kullanılır. AX. Çok genel kullanım alanına sahiptir. Genel Amaçlı Kaydediciler Bu kaydedicilerin 8. yani burada ne kadar anlatsak boş bu yüzden kısaca yukarıdaki şekilde gördüklerinizi açıklayıp hemen bir uygulama yapalım. Accumulator (EAX. Kaydedicileri tam olarak anlayabilmeniz için onları kullanmanız gerekir. Genel amaçlı kaydedicilerin hepsi verileri geçici olarak üzerlerinde barındırabilir fakat bazı x86 komutları buradaki kaydedicilere özeldir. BH. Bir başka kullanım alanıda hesaplamalardır.16 ve 32 bitlik kullanımı mümkündür. Ayrıca bazı komutlar işlenmeden önce accumulator’den parametre alır veya bu kaydediciye işlemin sonucunu kaydeder. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bölme ve taşıma gibi) kullanılır. AH. BX. Bu şekil 32 bitlik işlemciler (P4 serisi gibi) için kaydedici yapısını gösteriyor. AL): En sık kullanacağınız kaydedicidir. Bu kaydedici birçok giriş/çıkış işleminde ve aritmetik işlemlerde (çarpma. Örneğin AL ve AH Accumulator’ün 8 bitlik kullanımını AX 16 bitlik EAX ise 32 bitlik kullanımını simgeler. Mesela loop komutu ile CX kaydedicisinin değeri azalır. daha önceki makalelerimizde yazdığımız kodlara bakarsanız çok değişik amaçlarla kullanıldığını görebilirsiniz.Kaydediciler işlemcideki.

exe türündeki bir programda kullanılacak olan veriler data segment denilen hafıza bölümünde tutulur. Data Segment Kaydedicisi (DS): . CS kaydedicisi ise IP kaydedicisi ile birlikte programın çalışma sürecinde. daha önce loop komutunun CX kaydedicisini otomatik olarak değiştirdiğini söylemiştik. Index Kaydedicileri Bu kaydedicilerin E ile başlayanlar 32 bitlik programlarda. SP ve BP. Hepsi de verilerin offset adreslerini tutmada kullanılır. DS kaydedicisi ise bu bölgedeki verilerin konumlarını gösterir. CX. Bunlardan bazılarını programcı kullanamaz bazıları HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . CH. Özel kaydediciler IP ve EIP kaydedicileri: IP 16 bitlik DOS programlarının EIP ise 32 bitlik programların işlenmesi sürecinde. Bildiğiniz gibi mikroişlemci matematiksel işlem yapar. Đşlemci durum kaydedicisi olarakta bilinen bu kaydediciler sonucun sıfır. ayrıca çarpma ve bölme işlemlerinde accumulator ile birlikte büyük sonuçları bu kaydediciden okuruz. pozitif veya negatif olduğunu veya işlemin sonucunda elde üretilip üretilmediği gibi birçok önemli veriyi bitsel olarak programcıya bildirirler. Stack Segment Kaydedicisi (SS): Tüm programlar stack segment denilen bir hafıza alanını geçici depolama alanı olarak kullanmak zorundadırlar (örneğin dallanma işlemlerinde). Segment Kaydedicileri Segment kaydedicilerinin hepsi 16 bitliktir ve hafızanın segment olarak adlandırılan kısımlarını adreslemede kullanılır. FLAG ve EFLAG kaydedicileri: Flag kaydedicisi 16 Eflag kaydedicisi ise 32 bitten oluşur. Extra Segment Kaydedicisi (ES): Bazı string işlemlerinde DI kaydedicisi ile birlikte karakterlerin bulunduğu hafıza adreslerini tutarlar. DL): Bazı giriş/çıkış komutlarında bu kaydedicinin kullanılması gerekir. SS kaydedicisi ise SP kaydedicisi ile birlikte bu verilerin adreslerini referans eder. SS kaydedicisi ile birlikte SI ve DI. DS ve ES kaydedicileri ile birlikte hafıza adreslerine erişmek için kullanılır. DH. diğerleride 16 bitlik programlarda kullanılır. Data (EDX. FS ve GS Kaydedicileri: 80386 ve sonrası CPU’larda bulunurlar ve diğer segment kaydedicilerinin yetersiz kaldığı durumlarda kullanılırlar. programın oluşturan kodların adreslerini gösterirler. CL): Özel amaçlar ve hesaplamalarda kullanılacağı gibi genellikle bu kaydediciyi sayıcı olarak kullanılır. bu kaydedicilerde her işlemden sonra o işleme özel sonuçları gösterirler.Counter (ECX. DX. işlenecek olan bir sonraki komutun offset adresini gösterir. Burada açıklamadığım diğer kaydediciler: X86 ailesindeki işlemcilerde başka kaydedicilerde mevcuttur. Code Segment Kaydedicisi (CS): DOS işletim sisteminde programları oluşturan kodlar code segment’e yüklenir.

X86 ailesi işlemciler. bu binary formata en uygun sayı sistemidir. sıra hafızada. özetle data bus’ın (veri yolu) genişliği kullanılacak olan hafıza chip’ini belirler. korumalı mod diye adlandırılan özel çalışma modlarında anlam kazanır hatta bu tür çalışma modlarında yukarıda saydığımız kaydedicilerin birçoğu bambaşka amaçlar için kullanılırlar. Çok karışık bir konu olmasına karşın basit bir anlatımla bu konuyu kavramanızı umuyorum. hafızadan verileri düşük değerlikli kısmından itibaren okurlar (little endian). fiziksel yapısı ile programcı fazla ilgilenmez hafızanın mantıksal yapısı ise tüm programcılara hemen hemen aynı görünür.Hafızanı fiziksel yapısı. Hafıza denilince boyutu 8 bit olan bir dizi hücre ve bu hücrelerin numarası olan adresler akla gelir. adres ve kontrol yollarına bağlıdır. 16 bitlik bir veri yolu bulunan işlemciler için uygundur. Bu örnekte hafızaya erişim çift numaralı adresten yapıldığı için ABFFh verisi data bus’a doğru bir şekilde HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Yukarıdaki gibi bir hafıza yapısı. Hafızada bulunan veriler hexadecimal formatta gösterilirler. Hafızanın Fiziksel Yapısı Şekil 4 . Böyle bir durumda hafızanın fiziksel yapısını bilmek işe yarayabilir. örneğin 8086 işlemcisi için. adresten itibaren 16 bitlik (2 byte veya word) bir değerin işlemci kaydedicilerine herhangi bir işlem için çekileceğini varsayalım. Şayet veri yolu 32 bitlik ise daha fazla bank gerekir. 16 veya 32 bitlik bir değer işleyebilir.ise ayrıcalıklı mod. x86 hafızası ne kadar byte olarak adreslense de programcı hafızadan tek bir komut ile 8. Örneğin 0. Hafıza chip’leri veri. Đşlemciyi kısaca anlatmaya çalıştım. HAFIZA Şimdi hafızanın fiziksel ve mantıksal yapısını anlatacağım.

) ise verinin türüne göre offset adresini tutacak olan kaydedici değişir. Özetle çift numaralı adreslerden 1 byte’tan fazla bir değere erişilirse buna sıralı erişim (Aligned Memory Access). daha sonra işletim sistemine göre hafıza farklı bir şekil alabilir. örneğin erişilecek veri stack’ta (yığın bellekte diyebilirsiniz) ise buradaki verinin offset adresini SP (stack pointer) tutar. Bu durumda hafızanın tamamı bir kitap. Hafızanın Mantıksal Yapısı: Bir mikroişlemcinin ne kadarlık bir hafızaya erişebileceği adres yolu ile doğru orantılıdır. buda 4 Milyar küsür hafıza konumuna denk gelir. Tüm bu modlar tek başına bir makale konusu olduğundan ve şu an için biraz ağır konular olduğundan fazla ayrıntıya girmiyorum. Sayfalama (paging). DOS işletim sistemi yükleniyorsa (neydi o günler :)) hafıza real mod’da kalır. adresten okuma yapıldığını varsayalım. Sıralı hafıza erişimi sırasızdan 2 kat daha hızlı olduğundan programlamada buna dikkat edilmelidir. Şimdi sadece en basit ve programlarımızda kullanacağımız mod olan Real Mode Adressing yeni gerçek modda hafıza’yı inceleyeceğiz. Erişilecek olan veri (değişken.yerleşecektir ve en hızlı hafıza erişimi bu şekilde yapılır. Örneğin Linux yada Windows işletim sistemi yükleniyorsa hafıza Protected Mod (korumalı mod) denilen yapıya bürünür. Real mod’da hafıza 64Kb’lık segmentlerden oluşur ve bu segment içindeki her byte’a erişmek için offset adresleri kullanılır. 80286 ve sonrası işlemciler protected mod’a geçiş yapabilir. karakter vs. sanal bellek (virtual memory) ve multitasking (çok görevlilik) korumalı modun getirdiği büyük avantajlardır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . a denk gelir. Yavaş yavaş 64 bit devri başlıyor. Protected mod çok daha karmaşıktır. Birde korumalı mod altında DOS programlarını çalıştırmak ve korumalı mod ile real mod programları arasında geçiş yapmak için windows işletim sisteminin Virtual Protected Mod’u vardır. tek numaralı adreslerden okuma yapılırsa buna sırasız hafıza erişimi (Unaligned Memory Access) denir. Hafızanın mantıksal yapısı çalışma moduna göre değişiklik gösterir ve çalışma modu işletim sistemleri tarafından belirlenir. Günümüzde kullanılan mikroişlemcilerin adres yolu çoğunlukla 32 bitliktir. Birde tek numaralı bir adresten örneğin 7. segmentler sayfalar ve adreslenebilen her byte ise satır olara düşünülebilir. offset adresini de şayet erişilecek olan bir komut kodu ise IP kaydedicisinden alır. X86 uyumlu tüm PC’ler Real Mod denilen çalışma modunda açılırlar. 8086 işlemcisi 20 bitlik bir adres yoluna sahiptir ve adresleyebileceği alan 220=1048576 yani 1 MB. Adres yolu 16 bit olan bir mikroişlemci 216 yani 65536 adet hafıza konumuna erişebilir. Bu tür ayarlamalar assembly dilinde direktiflerle yapılır. Her ne kadar mikroişlemci böyle büyük hafıza alanlarını desteklese de böyle bir alanı kullanabilmemiz hafızayı nasıl organize edileceğine bağlıdır. 80286 işlemcisinin adres yolu 24 bitlik’ti ve 224= 16777216 hücreyi. AMD 64 bitlik işlemcilerini çoktan piyasaya sürdü 264 adet hafıza konumu geleceğin programlarını çalıştırmak için epey yeterli. Bu durumda okunması gereken değer 4676h olmasına rağmen data bus’a 7646h verisi yerleştirilir gibi görünüyor değil mi? Hal böyle olunca işlemci önce Odd Bank’tan daha sonra Even Bank’tan okuma yapar ve bu byte’ları sıraya koyar. lık bir hafıza alanını adresleyebilirdir. Mikroişlemci hafızanın herhangi bir konumuna erişirken segment adresini segment kaydedicilerinden. başka bir deyişle 16MB. bu tür bir hafıza erişimi daha uzun zaman alır. Hafıza organizasyonuna yapılan bu yaklaşıma hafızanın mantıksal yapısı diyebiliriz.

real mod’da offset adresleri index kaydedicilerinin 16 bitlik kısımlarında (SP. Gerçek modda bilgisayarınız Pentium 4 bile olsa hafızanın sadece 1MB. segment adresi 4 bit sola kaydırılır veya başka bir deyişle adresin sonuna 4 adet 0 getirilir (0000)2=(0)16 böylece segment adresi 045F0 olur. Örneğin 3456:76A3 real modda bir hafıza adresini gösterir. lık hafızayı adresleyebilir fakat xxxx:xxxx şeklinde bir gösterim 4GB’lık bir alana denk gelir (FFFF kere FFFF). 045F:0032 adresi için.DI) veya 16 bitlik olan IP kaydedicisinde tutulur.Programcı hafızayı adresleri olan byte tablosu olarak düşünür Real mod’da gerçek adres şu formülle bulunur.BP. Şimdi’de hafıza ve kaydedicileri daha iyi anlamak için örnek program hazırlayalım. ayrıca sadece kaydedicilerin 16 bitlik kısımlarını kullanabilirsiniz. viteste sürmeye benzer.SI. Hal böyle olunca işlemci real modda çalışırken gerçek adresi bulmak için bir hesaplama yapar çünkü gerçekte hafıza real mod’da 00000H-FFFFFH arasında anlamlıdır. Şekil 5 .######################################## HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 045F0h+0032h=04622h gerçek hafıza adresidir. 3456:76A3 gibi bir adres gösteriminde 3456’yı sayfa numarası olarak düşünürsek bu sayfada 0000-FFFF arasında 65536 adet offset adresi (satır) mevcuttur diyebiliriz ve bu konumların her biri 1 byte’a denk gelir.asm) .Segment kaydedicileri 16 bitliktir. Bu son model ferrari’nizi otobanda 1. Bu durum xxxx:xxxx formatında gösterilir. burada 3456 segment adresi iken 76A3 ofset adresidir. Hafızanın gerçek yapısını göz önüne alırsak örneğin 8086 işlemcisi en fazla 1MB. lık alanını adresleyebilirsiniz. TITLE Kaydediciler ve Hafıza (regmem. sonra buna offset adresi eklenir ve gerçek adres bulunur.

DATA Sayi1 Sayi2 Sonuc .toplama işlemini sonucu hafızaya yüklendi.si 32 byte’lık stacak segment bölgesi 2. Bu olayları en güzel uygulama yaparak anlayabiliriz. # . Sayi1 AL. Bir sonraki makalede görüşmek üzere hoşça kalın.# Son Güncelleme: 05/03/05 # . bu arada olumluolumsuz eleştirilerinizi bekliyorum. Sayi2 Sonuc. AX AL.CODE ANA MOV MOV MOV ADD MOV MOV INT ANA PROC AX. Đşlemci kaydedicileride programın yüklenme sürecinde ilk değerlerini alırlar..STACK . Ayrıca CPU tüm giriş çıkış işlemlerini de hafızaya erişerek yapar. . @DATA DS. AL AH. işler. ADRESLEME MODLARI Bildiğiniz gibi programları oluşturan kodlar ve veriler hafızaya yüklendikten sonra işlemci tarafından satır-satır icra edilirler.MODEL . .sü kodlarımın kapladığı alan kadar code segment bölgesi.######################################## . program önce hafızaya yüklenir ve mikroişlemci ilk komuttan itibaren programı atır-satır icra etmeye başlar. .Data segment .ayarlanıyor. Şimdi kendinize bir kahve hazırlayın ve keyifle bu videoyu izleyin. bunun için sizlere bir video hazırladım.# tekrar hafızaya kaydeder. Bazen hafızadan doğrudan bir kod ya da veri alır.AL’deki 5 ile 6 toplandı sonuç tekrar AL’de.DOS’a . .AL’ye 5 değeri yüklendi.# Yazan --> Eren ERENER # . Örneğin CS kaydedicisi code segment bölgesinin segment adresini ve IP kaydediciside bu bölgede bulunan kodların ilkinin offset adresinin değerini alır. Kafanıza takılan bir soru olursa bana mail atabilirsiniz.dönüş SMALL 32 DB DB DB 5 6 ? Bir programın çalışma süreci genel olarak şöyledir.# Bu program hafızadaki 2 adet byte’ı toplar ve sonucu # . Bazen hafızaya bir veri gönderdiğinizde birde bakmışsınız bu bir HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .’si 3 byte’lık data segment bölgesi ve 3. Bu program hafızaya yüklenirken hafızada mantıksal olarak 3 tane segment oluşturacak 1.4CH 21H ENDP END ANA .

Daha sonraları bir devrim niteliğinde olan 80386 işlemcisi ile ek adresleme modlarıda geldi. Şu ana kadar yaptığımız programlarda çok fazla komut örneği görmediniz ama makalelerimizi takip ettiyseniz MOV komutunu yakından tanımanız lazım. Bu yüzden bu makalede adresleme modlarını anlatırken MOV komutunu örnek alacağım. En hızlı adresleme modu’dur. ax . çünkü işlem hafızada değil işlemcinin içinde gerçekleşir. BX teki değeri AX’e kopyalar . Her mikroişlemci üreticisi bir mikro işlemci piyasaya sürdüğünde. Đşte bilgisayarın donanım ve yazılım düzeyinde yaptığı bunca çeşitli iş için CPU hafızaya değişik yollardan erişme ihtiyacı duyar. bx . al si. Sizlerde programlarınızı yazarken CPU’nun hafızaya nasıl erişeceğini yazdığınız kodlarla belirtmek zorundasınız. Intel 8086 işlemcisini piyasaya sürdüğünde oldukça kullanışlı bir dizi adresleme modu sağladı. Çünkü bir program çalışırken genelde hafızaya yazar yada okur. Küçük boyuttaki kaynaktan büyük boyuttaki hedefe de kopyalama yapılamaz. Assembly dilinin ilk basamağı olan adresleme modları da bu konuları kapsıyor. Bu özel adresleme modları sadece 386 ve sonrası işlemcilerde kullanılabilir. Bu da doğru bir kullanımdır! Kaydedici adreslemede en çok dikkat etmeniz gereken husus hedef ve kaynağın boyutlarıdır. bx dl. MOV hedef. SP deki değeri BP’ye kopyalar . MOV komutu assembly programlama dilinde en çok kullanılan komutların başında gelir. kaynak 8086 ADRESLEME MODLARI: 8086 Kaydedici Adresleme: Adından anlaşılacağı gibi kaydediciden kaydediciye yapılan işlemlerde bu adresleme modları kullanılır. Genel amaçlı ve indeks kaydedicilerde kaydedici adresleme modları: mov mov mov mov mov mov ax. MOV komutu da bu iş için biçilmiş kaftandır ve bu kadar çok kullanıldığından dolayı bir çok adresleme modunu destekler. dx sp. CL deki değeri DH’a kopyalar . Tabi ki bu ek adresleme modları ile assembly programlama dili daha esnek bir yapıya bürünmüştü.yanlış kullanım. bp dh.yazıcıdan belge olarak çıkmış vs. Programcılar da bu belgelere göre programlarını yazarlar. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . AL teki değeri DL’ye kopyalar . komut setini ve adresleme modlarınıda yayınlar. Örneğin 16 bitlik bir kaydediciden 8 bitlik bir kaydediciye taşıma yapılamaz! mov al. yani bu komut ile hafızaya çok değişik yollardan erişebilirsiniz. MOV komutunun genel kullanım şekli. derleme anında assembler hata verir. cl ax. DX teki değeri SI’ya kopyalar . Bizde bu makalemizde adresleme modlarını 386 öncesi ve sonrası olarak ikiye ayıracağız. Intel’in şu ana kadar ürettiği işlemcilerde bu adresleme modlarını kullanabilirsiniz.

AL’ye 11h yüklenir. 17 . Değişkenler ve sabitler sembolik kelimelerle ifade edildiğinden buna gerek yoktur. 1. kullanılmamalıdırlar. Yanlış kullanım. al ax. Đyi bir program organizasyonu için.cs . AL’nin içeriği ds:000C adresine kopyalanır. al . doğru kullanılmayan segment kaydedicisi şeklinde assembler hata verir! Bu işi yapmak için. mov ds. ax . ds:000C adresinden 1 byte AL’ye kopyalanır. mov al. mov mov mov mov (2 byte) al. Bunun yerine genel amaçlı kaydedicileri kullanmanız daha uygun olur.Direkt Adresleme (Displacement Only Addressing ) Acil adreslemenin doğru kullanılmış şeklidir. Bunlara ek olarak segment kaydedicilerinin kullanımında dikkat edilmesi gereken noktalar vardır. 2. Yüklenecek olan veri kod segmentten alınacağından bu tür kullanımları şahsen ben pek tavsiye etmem. ds:12 ds:12. AL’ile CX eşit boyutta değil.mov cx. ds:000C adresinden 2 byte AX’ye kopyalanır.cs ds. ds:12 ds:12. Bu adreslemede segment:ofset adresi kullanılarak hafızaya erişilir. Ne var ki debugger programlarında da sembolik değişken isimlerini değil HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . . AX’nin içeriği ds:000C adresinden itibaren kopyalanır Aslında kaynak kod hazırlanırken genelde bu şekilde bir kod yazımı yapılmaz.ax komut satırları kullanılabilir.CS ve IP kaydedicilerinin değeri kaydedici adresleme ile değiştirilemez mov cs. . mov mov ax. veriler hafızanın ayrı bir bölümünde (mesela data segmentte) değişkenler veya sabitler olarak belirtilmelidir.Segment kaydedicileri arasında bir transfer işlemi ancak genel amaçlı bir kaydedici vasıtasıyla yapılabilir. . ax . kaynak genel amaçlı kaydedici olmasına rağmen bu işlem mümkün değildir! Segment kaydedicileri programın icrası aşamasında hafızanın segment olarak adlandırılan bölümlerinin adreslerini tuttuklarından. 8086 Hafıza Adresleme Modları a. bu kaydedicileri verilerinizi saklamak veya taşımak için kullanmanızı tavsiye etmem. b.Acil Adresleme ( Immediate Addressing ) Herhangi bir genel amaçlı veya indeks kaydedicisine doğrudan bir değer yükleye bilirsiniz.

AL’ye ES:0003’den kopyalama yapılır [di] . AL’ye DS:0002’den kopyalama yapılır es:[di] . al. disp[bx] al. al. veriler tanımlanırken sayi1 db 5 şeklinde değil de . hafızadan AL’ye 1 byte taşınır. . daima stack segmentin (SS) offset adreslerini gösterir. @data mov ds. sadece db 5 yazılsaydı. sayi al. Alınacak verinin offset adresi BX’in değeridir. DI=0003 olduğunu varsayalım. mov mov mov al. al. 5 değerini al’ye yükler. Segment adresleri ise ilk üçünün DS sonuncusunun SS’dir. al.adresleri görürüz. .Kaydedici Dolaylı Adresleme ( Register Indirect Addressing ) Adının kaydedici olduğuna aldanmayın. al. AL’ye DS:0001’den kopyalama yapılır [bp] . Burada operand olarak kullanılan kaydedici köşeli parantez içine alınır ve bu andan itibaren bir offset adresi oluverir. AL’ye SS:0002’den kopyalama yapılır [si] . AL’ye CS:0000’dan kopyalama yapılır [bx] .code mov ax. AL’ye DS:0002’dan kopyalama yapılır d. BP indeks kaydedicisi yalnız başına hafıza adreslemede kullanılırsa. [bx] .data sayi1 db 5 . [bx] [si] [di] [bp] Yukarıdaki 4 örnekte AL’ye kopyalanacak verilerin offset adresleri ilgili kaydedicinin içindeki değerdir. ax mov mov al. c. al. SI=0002. Fakat BP kaydedicisi de dahil olmak üzere bu adresleme segment kaydedicileri de belirtilerek yapılırsa. aynı işi yapar yani 5’i AL’ye yükler. ds:0000 . al. o zaman ilgili segment:offset adresine erişilmiş olunur. al. .Đndeksli adresleme ( Indexed Addressing ) Kaydedici dolaylı adreslemenin operandına sabit bir değer eklenmiş halidir. al. BP=0001. disp[bp] al. cs:[bx] . mov mov mov mov mov mov mov mov al. AL’ye SS:0001’den kopyalama yapılır ss:[si] . BX=0000. mov mov mov mov al. Kullanım şekli. bu komutu kullanmak zorunda kalırdık. mov al. disp[si] HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Aşağıdaki kod parçasını inceleyin. al. AL’ye DS:0000’dan kopyalama yapılır ds:[bp] .

Aynı şekilde.mov al. DS:2020h adresindeki 1 byte’lık değer dl’ye kopyalanacaktır. Komut setlerinde adresleme modları açıklanırken disp veya mem kısaltması ile çok sık karşılaşacağınızdan. Aynı şekilde BP=3030h olduğunu varsayalım. arttırır veya azaltırlar. DI normalde DS’nin ofsetlerini gösterirken e. mov al. Buradaki anlamı ise referans alınan ofset adresidir. . bu yüzden bu kaydediciler genellikle programlamada indeks değerlerini tutar.Taban Đndeksli artı direkt adresleme (Based Indexed Plus Displacement Addressing) Bu adresleme modu taban indeksli adreslemeye 8 yada 16 bitlik sabit bir değerin eklenmiş halidir. Bu adresleme modunda da BP segment kaydedicisi daima SS’in ofsetlerini gösterir. AX. SS:4050h adresindeki 1 byte’lık değer dh’a kopyalanır. mov al. Mesela BX=2000h olsun. Kullanım formatı aşağıdaki gibidir.Taban Đndeksli adresleme ( Based Indexed Addressing ) Bu adresleme modu da kaydedici dolaylı adreslemeye çok benzer. cs:disp[si] burada CS’in ofseti olmuş. mov dh. mov mov mov mov al. es:disp[bp] burada ES’in ofseti olmuş. al.[bp+di] gibi bir komut işleniyorsa. [bx][si] [bx][di] [bp][si] [bp][di] BX’in 0500h SI’nın 0360h olduğunu varsayalım. Fakat kaydedici dolaylı adreslemede de olduğu gibi bizzat segment kaydedicisinide belirterek bu adresleme modunu kullanabiliriz.1020h[bp] gibi bir komut ile. ss:disp[di] burada SS’in ofseti olmuş. SI ve DI kaydedicileri için Intel’in özel komutları vardır. Bu durumda ofset adresleri komutta belirtilen segmentin ofseti olur.[bx][si] gibi bir komut işlenince AL’ye kopyalanacak veri DS:0860 adresinden alınır. SI normalde DS’nin ofsetlerini gösterirken . BP normalde SS’nin ofsetlerini gösterirken . mov al. al. mov dl. f. BP=1598h DI=1004 ve mov ax. mov al. komutları yazarken Đngilizce ifadeler kullanmak durumunda kaldım. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 20h[bx] şeklinde bir komut kullanıldığında. al. SS:259Ch ve SS:259Dh adreslerindeki veri ile yüklenir. ss:disp[bx] burada SS’in ofseti olmuş. disp[di] Not : disp kısaltması Đngilizcede displacement kelimesinin karşılığıdır. mov al. BX normalde DS’nin ofsetlerini gösterirken .

[bp][di].10h[bx+si] mov ch.8086 adresleme modları için yardımcı şekil. disp[bx][si] disp[bx+di] [bp+si+disp] [bp][di][disp] BP = 1000h. AL’ye DS:2130 adresindeki veri yüklenir . disp[bx][si] = disp[bx+si] = [disp+bx+si] = [disp+bx][si] = disp[si][bx] = [disp+si][bx] = [disp+si+bx] = [si+disp+bx] = [bx+disp+si] Yukarıda yazılan bu 3 adresleme modundaki operandlar aynı işi yaparlar. Taban Đndeksli artı direkt adresleme için. disp[bx][si]. DI = 5 olduğunu varsayalım. ve taban indeksli artı direkt adresleme için değişik yazım şekillerini desteklerler. disp[si]. al. [bp][si]. disp[bx]. [bx]. disp [bx][di]. disp[bx] = [bx][disp] = [bx+disp] = [disp][bx] = [disp+bx] Taban indeksli adresleme için. disp[bp][si]. Bunlar disp. CS:2007 adresinden itibaten 2 byte’lık veri TASM ve MASM ‘ın adresleme modları için esnekliği.125h[bp+di] mov bx. [di]. bu 17 adresleme modunu ezberlemeniz yerine kolayca hatırlamanıza yardımcı olacaktır. Aşağıdaki şekil.cs:2[bx][di] yüklenir . and disp[bp][di] adresleme modlarıdır. MASM ve TASM "[ ]" sembollerine "+" operatörü gibi davranır. al. disp[di]. [bx][si] = [bx+si] = [si][bx] = [si+bx] . SI= 0120h. [bp]. TASM ve MASM assembler’ları indeksli.mov mov mov mov al. al. Şekil 1 . mov al. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . taban indeksli. [bx][si]. disp[bp]. BX= 2000h. Đndeksli adresleme için. ( disp[bx][si] = disp[bx+si] örneğinde olduğu gibi ) 8086 Adresleme Hafıza Adresleme Modlarını Hatırlamak Đçin Kolay Bir Yol: 8086 işlemcisi için toplam 17 adet adresleme modu mevcuttur. [bx][di]. [si]. CH’a SS:112A adresindeki veri yüklenir .

Bu durunda AL kaydedicisine ds:1000Fh adresindeki veri değil ds:000Fh adresindeki veri yüklenir. disp[di] 1. [bx]. ilk olarak kaydedici adresleme modlarını anlatmaya çalıştım. disp[bp][di]. [bp][di] Son olarak tüm sütunların birleşimi ile aşağıdaki geçerli adresleme modlarını kolayca çıkartabilirsiniz. Örnekler. Not:Hafıza adresleme modlarında şayet hesaplanan etkin adres 0FFFFh değerinden büyük olursa. Hangi komutun hangi adresleme modunda kullanılacağı komut setlerinden faydalanılarak bulunur. [bp]. Örneğin BX=10h olsun ve mov al. sütunu yok sayın ve diğer elemanların birleşimini çıkartın disp[bx]. Her komut her adresleme modunu desteklemez. Genelde komut seti kılavuzları aşağıdaki tablo gibidirler. Hafıza adresleme modlarını unutmamanız için sizlere kolay bir yol göstermeye çalıştım. Bugüne kadar gerek internetten gerekse Türkçe assembly kitaplarından yaptığım araştırmalarda. [di] 3. buna etkin adres hesaplama da denir. [si]. FFFFh+2h=0001.. Karışık olan kısım ise hafıza adresleme modlarıdır.Bu şekil ile 17 adresleme modunu kolayca görebilirsiniz. Adresleme modlarının isimlerinden ziyade kullanım formatları önemlidir. disp[bx][si]. Her sütundaki elemanları teker-teker seçebilirsiniz veya herhangi bir sütunu geçip diğer iki sütunun birleşimi ile doğru bir adresleme modu yakalayabilirsiniz. “8086 instruction set” veya “x86 instruction set” anahtar kelimelerini internetten aratacak olursanız karşınıza yığınla komut seti gelecektir. disp[bp][si]. sütunu yok sayın ve diğer elemanların birleşimini çıkartın [bx][si]. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . (FFFFh+1h=0000. disp [bx][di]. Türkçe olarak yayınlanmış ayrıntılı bir komut seti bulamadım bu yüzden Đngilizce komut setlerinden faydalanıyorum. sütunu yok sayın ve diğer elemanların birleşimini çıkartın disp[si]. Hafıza adresleme modlarında belirtilen operand daima bir offset adresini işaret eder. Kaydedici adresleme de segment kaydedicilerini kendi amaçları dışında kullanmanız tavsiye edilmez. CPU bu hesaplama sonucu oluşan taşmayı göz ardı eder ve FFFFh’e ekleneni 0 dan itibaren ekler. disp. disp[bp] 2. Bir tek eleman seçin.0FFFFh[bx] komutu işlensin. FFFFh+16h=000Fh) Sonuç: 8086 adresleme modlarını 2 bölümde inceledik. [bp][si]. [bx][di].…. bu iş için yeterince genel amaçlı ve indeks kaydedicisi var zaten.

ebx. “Clocks” sütunu bu komutların işlemci tarafından kaç adımda işlendiğini (işlemcinin tipine ve hızına göre bu zaman birimi değişebilir).. .. . Örneğin mem. reg 2 2 1 2 mem.Move Byte or Word Usage: MOV dest. . derecede “operands” sütunu önemlidir ve ilgili komutu bu sütunda belirtilen formatların dışında kullanamazsınız.. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Son olarak x86 uyumlu hiçbir işlemci mem. 3 2 1 3-6 imm reg. “size bytes” sütunu ise hafızada makine kodlarının byte olarak kapladığı alanı gösterir. .. edx... imm 2 2 1 2-3 segreg. Yani 1... .. ebp.reg (register.. . işlenme sürecindeki nano saniyeleri ve hafızada kapladığı alanını byte düzeyinde önemi yoksa bu kısımlarla ilgilenmezler..... . .MOV . 5 5 9 2-4 mem16 .. edi.. reg 3 2 1 2-4 reg... reg..src Operands Clocks Size Bytes 286 386 486 reg. Tablo 1 . .... Çoğu zaman assembly programcıları programlarının.. eax. günümüzde kullandığımız Pentium işlemcilerin 32 bitlik kaydedicileri vardır. 2 2 3 2 reg16 segreg. Bu kaydediciler geçen makalemizde bahsettiğimiz.. segreg.. . esi. . aslında bu güne kadar bunu destekleyen hiç bir işlemci görmedim.mem şeklinde yani hafızadan hafızaya doğrudan bir adresleme modunu desteklemez. mem 5 4 1 2-4 mem..imm (displacement. . ... 80386 ADRESLEME MODLARI 80386 Kaydedici Adresleme (80386 Register Addressing) 80386 den itibaren. .reg16 (segment register... zaten böyle bir adresleme modunun desteklenmesi durumunda o sistem için yapılan programların çökme olasılığı çok büyüktür. ve esp kaydedicileridir. 8086 adresleme modlarına ek olarak bu işlemcilere de kaydedici adresleme yaparken bu 32 bitlik kaydedicileri de kullanabilirsiniz. ecx.MOV komutu için örnek tablo Bu tabloda birinci sütun MOV komutu ile kullanılacak operandın hangi adresleme modlarını desteklediğini gösteriyor. register 16 bit ) bir segment kaydedicisine 16 bitlik bir kaydediciden kopyalama işleminin yapılabileceğini gösterir.immediate) acil adresleme yi desteklediğini gösterir.register) kaydedici adreslemenin yapılabileceğini.

modları. DS in ofsetleri için . Aşağıda 80386 indeksli hafıza adresleme modları için birkaç örnek görülüyor. al. 80386 ve sonrası işlemcilerde bulunan bu esneklik şüphesiz ki programcıların işini kolaylaştırır. Base/Indexed. indeks adreslerinide SI. DS in ofsetleri için .kullanım formatı. Fakat gerçek moda 32 bitlik kaydedicileri hesaplamalarda kullanmanızda bir engel yoktur. al. al. mov mov mov mov mov mov mov mov al. al.Đndeksli adresleme . Taban/Đndeksli. bu yüzden offset adresleri gerçek modda 0.0FFFFh arasını gösterir. Taban indeksli adresleme modu iki adet 32 bitlik kaydedicinin birleşiminden ve taban indeksli artı direkt adresleme modu ise bir sabit değer ile iki tane 32 bitlik kaydedicinin birleşiminden meydana gelir.80386 Kaydedici Dolaylı Adresleme ( Register Indirect Addressing ) 16 bitlik Gerçek moda (Real Mode) 80386 ve üstü işlemcilerde programlama yapmanız offset adreslerinin 32 bit olacağı anlamına gelmez. SS in ofsetleri için .’ı geçecek ofset adreslerini gerçek moda değil ancak korumalı moda (Protected mode) kullanabilirsiniz. al. al. al. disp[eax] [ebx+disp] [ecx][disp] disp[edx] . [eax] [ebx] [ecx] [edx] [esi] [edi] [ebp] [esp] . al. ebx Not: Şayet programınızda 32 bitlik kaydedicileri kullanacaksanız kaynak dosyası hazırlarken . Taban adresini ilk operand iken indeks adresini son operand gösterir. şayet 16 bitlik gerçek moda kullanılırlarsa erişebilecekleri ofset adresleri 16 bit’i geçemez. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Yani 64Kb. DI. DS in ofsetleri için . 80386 taban indeksli hafıza adresleme modlarında taban adres ve indeks adresi diye iki tane terim kullanılır.80386 Đndeksli. olduğunu unutmamak gerekir. al. 80386 kaydedici dolaylı adreslemede kullanabileceğiniz tüm geçerli adresleme formatı aşağıdaki gibidir. Hiçbir zaman unutmamalısınız ki bu adresleme modları ne kadar 32 bitlik olsa da. DS in ofsetleri için .386 talimatını kullanmanız gerekir. BP ve BX gösterebiliyordu. al. ve Taban/Đndeksli/Direkt Adresleme modları ( 80386 Indexed.. 80386 Hafıza Adresleme (80386 Memory Addressing) a. SS in ofsetleri için b. DS in ofsetleri için . and Base/Indexed/Disp Addressing ) 80386 Đndeksli adresleme modu 32 bitlik bir kaydedici ile sabit bir değerin birleşiminden meydana gelir. Segmentlerin her zaman gerçek moda 64Kb. taban adresini sadece BX veya sabit bir değer gösterebilirken.. Fakat 8086 indeksli veya taban indeksli hafıza adresleme modlarında. mov mov mov mov al. Bu kural kaydedici ismi ne olursa olsun geçerlidir. DS in ofsetleri için . mov eax.

al. mov mov mov mov mov mov mov mov al. Yukarıda anlattığım 3 adresleme modu ile dizilerin elemanlarına rahatça erişebilirsiniz.Taban indeksli artı direkt adresleme . al.SS in ofsetleri için . . . disp[eax][ebx] disp[ebx+ebx] [ecx+edx+disp] disp[edx+ebp] [esi][edi][disp] [edi][disp][esi] disp[ebp+ebx] [esp+ecx][disp] . c. 4 veya 8 ile çarparak dizilerin elemanlarına erişmede daha esnek bir yapı sağlar. ikinci kaydedici ise indeks adresini gösterir. al. Bununla birlikte indeks adreslerini gösteren kaydedicilerin türü verinin hangi segmentten alınacağına etkisi olmaz. esp kaydedicisini indeks kaydedicisi olarak kullanamazsınız ama esp nin taban kaydedicisi olarak kullanılmasının bir kısıtlaması yoktur. [eax][ebx] [ebx+ebx] [ecx][edx] [edx][ebp] [esi][edi] [edi][esi] [ebp+ebx] [esp][ecx] .Taban indeksli adresleme . al. al. al.mov mov mov mov al. al. . al. al. al. al. Yukarıdaki adresleme modlarına sabit bir değer eklerseniz 80386 taban indeksli artı direkt adresleme yapmış olursunuz. . Aşağıdaki örneklerde ise 80386 taban indeksli adresleme modları için çeşitli örnekler görünüyor. disp[esi] disp[edi] disp[ebp] disp[esp] .SS deki ofsetleri gösterirler. disp[index*n] [base][index*n] HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . . .80386 Ölçekli Đndeksli Adresleme Modu (80386 Scaled Indexed Addressing Modes) Programcılıkla az çok uğraşan arkadaşlar diziler konusu bilirler.DS deki ofsetleri gösterirler.modları. al.SS deki ofsetleri gösterirler. al. mov mov mov mov mov mov mov mov al. al. al. 80386 indeksli adresleme modlarında sadece tek bir kısıtlama söz konusudur.için. Fakat özellikle dizi işlemler için bir adresleme modu arıyorsanız 80386 ölçekli indeksli adresleme modunu kullanmak daha akıllıca olur. Kaydedicilerin 32 bitlik olduğunu düşünecek olursanız 4GB’lık hafızanın istediğiniz bir konumuna erişebilineceğini de görebilirsiniz (tabi ki korumalı modda). Burada taban adresi olarak esp ve ebp kullanıldığında SS’deki bir ofset adresini göstereceğini unutmayın. Bu adresleme modu ile indeks kaydedicisini 1.DS deki ofsetleri gösterirler.modları. al. 2.SS deki ofsetleri gösterirler. Tabi ki sonuçta bu iki kaydedicinin içindeki değerler toplanarak etkin olan hafıza adresini işaret edecekler. Bu örneklerde ilk kaydedici taban adresini gösterirken. Kullanımı.SS deki ofsetleri gösterirler. al.

ölçeği 1 olan (n=1) 80386 Ölçekli Đndeksli Adresleme Modu olarak düşünülebilir ve bu hafıza adresleme modlarında gösterilen ilk kaydedici taban ikinci kaydedici indeks adresini gösterir.DS’nin ofsetini gösterir. . Zaten CPU tarihinde 80386 bir devrin kapanıp diğer bir devrin başladığı nokta olarak kabul edilir. ebx = 1000h ve esi = 4. disp[bx][si*2]. Aşağıdaki tüm operandlar aynı işi yaparlar. . 80386 taban indeksli ve taban indeksli artı direkt adresleme modları. Ayrıca operanda segment kaydedicisini de göstererek adresleme modunu zorlayabilirsiniz.DS’nin ofsetini gösterir. 2[esi*1] = mov al. 80386 Đndeksli.ds:4000h daki veriyi dan AL’ye kopyalar.ds:1020h deki veriyi dan AL’ye kopyalar. Taban adresini gösteren kaydedici ebp veya esp ise bu adresleme SS’deki bir ofset adresine diğer kaydediciler taban adresi olarak seçildiğinde DS deki bir ofset adreslenmiş olunur. disp[si*2][bx]. ve Taban/Đndeksli/Direkt Adresleme modlarını da 80386 Ölçekli Đndeksli Adresleme Modunun n değerinin 1 olduğu adresleme modları olarak düşünebilirsiniz mov mov mov al. . [ebx][ebp] [ebp][ebx] [ebp*1][ebx] [ebx][ebp*1] [ebp][ebx*1] . [ebx][esi*1] = mov al. [si*2+bx][disp]. 2.8[ebx][esi*4] . için aşağıdaki örnekleri inceleyelim. 2[ebx][esi] al. [ebx][esi] al. . al. [si*2+disp][bx].SS’nin ofsetini gösterir. 4 ve 8 değerlerini alabilir. "n" ise 1.ds:1018h daki veriyi dan AL’ye kopyalar. [bx+disp][si*2]. Bu yüzden söz konusu olan hız ise (mikro saniyelerden bahsediyoruz ki bunlar bazen birleşip dakikalar oluyor) adresleme modu seçilirken çok dikkat edilmesi gerekir. [disp+bx][si*2] Sonuç: 80386 adresleme modları 8086 adresleme modlarına nazaran programcıya daha çok olanak sağladığından daha çok tercih edilirler.DS’nin ofsetini gösterir. 2[esi] MASM ve TASM 80386’nın tüm bu hafıza adresleme modlarının yazımında değişik varyasyonları kabul eder. Ne var ki 8086 adresleme modları 80386 adresleme modlarına nazaran daha hızlı çalışırlar. al.SS’nin ofsetini gösterir.1000h[ebx][ebx*2] .1000h[esi*8] .veya disp[base][index*n] "base" ve "index" 80386’nın herhangi bir genel amaçlı kaydedicisi olabilir. Taban/Đndeksli. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . mov mov mov al. 2[ebx][esi*1] = mov al. [bx+si*2+disp]. Đlk yazılan kaydedici ölçekli olarak gösterilirse ("*n") bu bir taban adresi olmaktan çıkar bir indeks adresi olur. Benim şahsi görüşüm X86 uyumlu PC’ler gerçek gücünü 80386 işlemcisi ile birlikte gelen bu olanaklardan almışlardır.

AX . Direkt adresleme. Bu uygulama ile hem adresleme modlarını hem de Turbo Debugger programının kullanımını açıklamaya çalışacağım.######################################## . .DATA SMALL 32 VerilerByte DB 5h. 12345678h . [BX][SI] değer DS:0000h’daki 05h’tır. Yukarıdaki ile aynı işi yapar. .SS’nin ofsetini gösterir.# Yazan --> Eren ERENER # . AX . DS:0000h adresindeki 5h değeri AL’ye kopyalanır. Kaydedici dolaylı adresleme.asm) .ES’nin ofsetini gösterir.[ebx*1][ebp] es:[ebx][ebp*1] . Data segment . # . 8Dh. Đndeksli adresleme. .---------------------------------------.---------------------------------------MOV DX. 0AFh VerilerWord DW 1234h. SI’yı 1 arttırdık. . 3[VerilerByte] .# Son Güncelleme: 17/04/05 # . 17h.CODE ANA MOV MOV PROC AX.# Bu program 8086 ve 80386 adresleme modlarının # . MOV AL. Acil adresleme. şu anda AL’ye kopyalanacak . INC SI . TITLE Adresleme Modları (admod.# iyi kavranması için yazılmıştır. 0C01Dh VerilerDoubleWord DD 3DF0178Ah. Kaydedici adresleme. 0000h MOV AL. [BX] . ayarlanıyor. zaten assembler VerilerByte değişken ismini ds:0000h olarak çevirecektir. SI = 0 oldu. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . @DATA DS. 0 MOV AL.######################################## .8086 Hafıza Adresleme Modlarına Örnekler .Zorlanmış. DS:0000h . 5566h BX. DS:0003h adresindeki AFh AL’ye yüklenir MOV AL. 7h. MOV BX.STACK . 3[BX] . Şimdi sıra uygulamada.MODEL . 11223344h. MOV MOV AX. . zaten BX=0’dı. MOV SI.

. [EBX][EAX] .dönüş HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . MOV INT ANA AH. SUB (Subtract) yani . şimdi AL’ye kopyalanacak değer . LEA komutu (Load Effective Address) VerilerDoubleWord dizisinin başlangıç adresini EAX’e kopyalıyor. 4[ebx][esi*2] .MOV DS:0001h’daki INC INC MOV DS:0003h’daki AL. Bu adreste 0007h vardır. INC SI . şimdi SI=3 oldu. . . EBX .4CH 21H ENDP END ANA . Đndeks’i 1 olarak ayarlandı. ve bu dizideki ilk eleman (3DF0178Ah) ECX’e kopyalanıyor. 0" ile aynı işi fakat daha AX. EBX çıkartma komutu.80386 Hafıza Adresleme Modlarına Örnekler . 80386 adresleme modlarını ve 32 bitlik kaydedicileri kullanmak için bu direktifin yazılması gerekir!!! MOV ESI. 80386 ölçekli indeksli adresleme modu dizisinin 1.---------------------------------------. EBX = 0 oldu. Burada BX taban SI indeks kaydedicisi oldu. Bu adres VerilerWord değişkenin adresidir ve bu adreste 1234h vardır. . elemanı (1234h) AX’e kopyalandı. SI SI AL. VerilerWord dizisinin 2. MOV AL. MOV AX. 80386 kaydedici adresleme SUB EBX. [BX][SI] AFh’tır. MOV ile VerilerWord INC MOV ile VerilerWord .386 . DS değil SS ’in offsetlerini adresler. ebx = 0 yapıldı. 4[bx+si] . elemanı (0007h) AX’e kopyalandı. elemanına erişiliyor. . 0 SUB EBX. çünkü 4+0+0 = 4’tür. 2 kere arttırılıyor ve. . LEA EAX. ESI AX. [BP][SI] . . MOV AX. şu anda Stack Segment’in içinde ne olduğunu bilmiyoruz!!! . çünkü 4+0+2 = 6’dır. [BX][SI] 17h’tır.---------------------------------------. hızlı yapar.DOS’a . 2 arttırdık.Taban indeksli artı direkt adresleme MOV SI. şimdi AL’ye kopyalanacak değer . BX’i değiştirmediğimizden hala sıfır ve AX’e getirilecek 2 byte’lık veri ds:0004h adresinden alınacak. 80386 ölçekli indeksli adresleme modu dizisinin 2. SI=0 oldu. INC SI . 4[bx+si] . SI’yı. . 4[ebx][esi*2] . 0 . burada "MOV ebx. SI. VerilerDoubleWord . 80386 taban indeksli adresleme. . MOV ECX.

Turbo Debugger kullanımına ilişkin birkaç ipucu: Đlk olarak konsola "td" yazarak programı çalıştırın.Yukarıdaki program sadece 8086 ve 80386 adresleme modlarına örnek olması için hazırlanmıştır. Not: Turbo Debugger’ı pencere modunda çalıştırırsanız GDI (Graphics Device Interface) kaynaklarını sömürürcesine kullandığından bilgisayarınız yavaşlayabilir. Turbo Linker paketini içermekte.Turbo Debugger ekranı. Programı pencere modunda başlattıktan sonra konsol penceresinin ayarlarından tam ekran yapmanızın da bir faydası olmaz. Programı buradan indirebilirsiniz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Şekil 2 . Turbo Assembler’ı. Hafızadaki veriler nasıl erişilir sorusuna yanıt arayanların bu programı dikkatle ve satır-satır incelemesini tavsiye ederim. Turbo Debugger ile program dosyalarınızı açtıktan sonra bir çok işlem yapabilirsiniz. Bu yüzden önce komut istemini açın. içinizde belki hala DOS veya Windows 95 kullanan vardır diye bir mouse programı ekledim. sonra tam ekran yapın ve Turbo Debugger’i çalıştırın. Turbo Debugger Microsoft’un debug’ı ile aynı işi yapar fakat daha kullanışlı bir kullanıcı ara yüzüne sahiptir. Sıra bu programı derledikten sonra Turbo Debugger ile açıp hafızada ve işlemcide hangi olayların olduğunu incelemeye geldi. Şayet durum böyleyse önce konsola "mouse" yazdıktan sonra Turbo Debugger’ı çalıştırın. Đndireceğiniz bu dosya Turbo Debugger. Turbo Debugger programının 16 ve 32 bitlik hafızayı incelemek için iki ayrı versiyonu var şu anda gerçek modda çalışan programlar hazırladığımızdan dolayı 16 bitlik sürümünü kullanacağız. Ayrıca bu pakete. Bu yüzden tam ekran modunda başlatmanızı öneririm. Turbo Debugger’ın ekranına ulaşacaksınız.

Bu mesaj penceresinde "OK" e tıklayıp çalışmaya başlayabilirsiniz.Turbo Debugger ekranı 5 bölümden oluşuyor. Şekil 3 . bölgeyi yığın hafızayı gözlemlemek için kullanabilirsiniz. Turbo Debugger açıldıktan sonra "File" menüsünden derlediğiniz program dosyasını açıp kodlarını inceleyebilirsiniz. 3.Turbo Debugger ile dosya açma. 2 ve 3 nolu kısımlar hafızayı incelemek için kullanılırlar. kısımdada yine mikroişlemci kaydedicilerinden olan flag register’ı bitsel olarak görebilirsiniz. kısım mikroişlemci kaydedicilerini ve 5. Şekildeki 1. 2. Ayrıca menülerden sırasıyla View/Another/File seçeneklerini tıklayarak başka bir dosyayı diğer bir pencerede açabilirsiniz. bölge programı oluşturan kodları. 4. bölgede verilerin incelenmesi için kullanılır. Program dosyanızı açtıktan sonra "Program has no symbol table" diye bir mesaj gelebilir. Genellikle 1. (Mesela kaynak dosyasını) HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Değişikliğe uğrayan kaydediciler beyaz görünür.Turbo Debugger ile aynı ekranda kaynak dosyanızı da görebilirsiniz. Şayet bu pencerede yazı yerine hex kodları görürseniz.Şekil 4 . pencerenin üzerine sağ tıklayıp açılan menüden "Display As" ı seçin. F8 tuşu programı adım adım işletmek için kullanılır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Program adım-adım işlenirken mavi bir çubuk o anda hangi komutun işleneceğini gösterir. F7 ise adım-adım program işlenirken döngüleri incelemenizi sağlar. Programı çalıştırma seçeneklerini "Run" menüsünden seçebilirsiniz. Programın tekrar çalıştırmak için "Run" menüsünden "Program Reset" seçeneğini seçebilirsiniz. Aynı ekranda işlemcinin kaydedicilerinin nasıl değiştiğini gözlemleyebilirsiniz.

Açılan pencereye görmek istediğiniz adresi yazın. Programınız satır-satır işlenme sürecinde. adresleme yapılan bir komutun işlenmesi anında kod penceresinin sağ üst köşesinde hafızanın hangi bölgesine erişildiği görülebilir. Bu makalemizdeki programı incelerken bu özelliği sıkça kullanmanız gerekecek.Turbo Debugger ile hafıza pencerelerini kullanma. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Şekil 2 . Yalnız .Şekil 2 .Program adım-adım işleniyor. pencereye sağ tıklayıp "goto" yu seçin.exe tipindeki program dosyalarında verilerinizi görebilmek için mov ax. Verilerinizi görmek için 2.@data ve mov ds.ax satırlarının işlenmiş olması gerekir.

Şayet Đngilizce okuduğunuzu anlıyorsanız sizlere Art of Assembly’yi tavsiye ederim. kısım) sağ tıklayıp "Registers 32 bit" i seçebilirsiniz. Bu makalemizde x86 Assembly programlama dilinin komutlarını anlatmaya çalışacağım ve bu makalede açıklanan komutları öğrendiğinizde kendi başınıza program yazabilir hale geleceksiniz. 80x86 komutları genelde 8 grup altında incelenir. Bir sonraki makalemizde veri tipleri ve x86 komutlarını inceleyeceğiz. Aslında 80386 ve sonrası mikroişlemciler için daha birçok komut mevcuttur ve bu komutlar assembly dilinde program yazma işini kolaylaştırır. ayrıca bu güne kadar yazdığımız programları da Turbo Debugger ile inceleyerek programı kullanmasını daha iyi kavrayın. Örneğin LEA mnemoniği Load Effective Adres kelimelerinin kısaltılmış şeklidir. cwd. Bu komutlar genelde mnemonik’ler (nivmonik diye okunur) şeklindedir. programlama dillerinin komut ve ifadeleri farklı olabilir. bunlara cevap vermesi daha az zamanımı alıyor ve sizler içinde çok faydalı olacağından eminim. Genelde sizlerden makalelerin daha sık aralıklarla yayınlanması ile ilgili mailler alıyorum. Fakat bir makale hazırlamak en az 1 haftamı alıyor ve üniversitedeki derslerden ve işlerden dolayı çok az vaktim oluyor. Bu komutları ilerleyen makalelerimizde açıklamaya çalışacağım. popf 2) Dönüştürme komutları cbw.Turbo Debugger ile adresleme modlarının işlevleri rahatça görülebilir. Şimdi sizler Turbo Debugger ile bu makaledeki programı inceleyerek pratik yapın. Assembly programlama dilininde diğer programlama dillerinde olduğu gibi bir dizi komutu vardır. Bu şekilde çalışan bazı arkadaşlar internetten kaynak kod bulup. Burada AL kaydedicisine kopyalanacak olan veriyi "ds:0000 = 05" şeklinde görebilirsiniz. 1) Veri taşıma komutları mov. derleyip takıldıkları yerlerde bana mail atıyorlar. pushf. Mesela bu makaleyi yazarken bu kaynaktan çok yararlandım ve sizlere de tavsiye ederim 80x86 KOMUT SETĐ (Bölüm 1) X86 tabanlı mikroişlemcilerin icra ettiği makine kodları sabit olmasına rağmen.Şekil 2 . lea. Bu yüzden makalelerimin yayınlanma aralığı birden 20 güne sıçrayabiliyor. les . pop. Đnternetten okuyabileceğiniz bedava bir kitap. Turbo Debugger’ın daha bir çok özelliği var ama şu anda bizlere bu kadarı yeter. Mesela yukarıdaki şekilde mov al. Daha sonra prosedür ve makrolarıda gördükten sonra nihayet kendi programlarınızı yazabilir seviyeye geleceksiniz. 32 bitlik kaydedicileri görmek içinse kaydedicileri gösteren kısıma (4. push. [BX] komutu işleniyor ve kaydedici dolaylı hafıza adresleme yapılıyor. xlat 3) Aritmetic komutlar HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Hal böyleyken sizlerin arayı soğutmamak için başka kaynaklardan faydalanmasını tavsiye ediyorum.

lea. stos. xchg. mul. çevirme ve bitsel işlemler için komutlar and. immediate data reg. cmp. Tüm komutlar için geçerli olan bu Đngilizce ifadelerin Türkçe karşılıkları aşağıdaki gibidir. mem : memory à hafıza (RAM-ROM veya Giriş/Çıkış portları olabilir) immediate data à acil adresleme ile kullanılan direkt veri HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . div. ve sahf komutları veri taşıma komutlarıdır. çünkü internetten erişebileceğiniz komut seti referanslarında hep bunlar karşınıza çıkacak. Jxx (şartlı dallanma komutları) 8) Diğer komutlar clc. mem mem. reg reg. Yukarıdaki kullanım şekilleri için Đngilizce ifadeler kullanılmıştır. pushfd. or. call. push. lgs. reg mem. shr. MOV komutu Bu komutun kullanım şekilleri aşağıdaki gibidir. kaydırma. pusha. pop. lods 7) Program akış kontrol komutları jmp. lahf. imul. pushad. inc sub. cmc Veri Taşıma Komutları Veri taşıma komutları bir değeri bir yerden başka bir yere taşımaya yarar. popa. ax/al segreg. xor. segreg MOV komutu assembly dilinde çok kullanılan bir komuttur. shl. popf. reg : register à kaydedici. reg16 mem16. not. popad.add. rcl. rcr 5) I/O (Giriş/Çıkış) komutları in. out 6) Karakter dizi (String) komutları movs. popfd. mov mov mov mov mov mov mov mov mov mov mov reg. segreg reg16. ret. mov. lfs. neg. lss. mem16 segreg. idiv 4) Mantıksal. mem mem. dec. stc. immediate data ax/al. les. pushf. lds.

Yani acil adresleme modunu segment kaydedicilerine uygulayamazsınız. toplam . Bu işlemi yapmak için taşınacak veri önce mikroişlemci kaydedicilerinden birine getirilmelidir. gibi) MOV komutunu kullanırken yapamayacağınız iki şey vardır. MOV MOV AX. BX . MOV DS. Bu komut işlenince AX’in içinde 0015h değerini görürsünüz. Dikkat edilemesi gereken diğer bir husus ise hafıza operandlarıdır.yanlış kullanım Yukarıdaki gibi bir komut satırı yazarsanız.sayi1 ve sayi2 değişkenlerinin word türünden olduğunu varsayıyoruz. burada toplam değişkeninin boyutu kesinlikle word tipinde yani iki byte uzunluğunda olmalıdır. AX Bunların dışında operandların boyutları eşit olmak zorundadır. MOV komutu ile yapamayacağınız ikinci şey ise segment kaydedicilerine doğrudan bir veri taşımaktır. MOV MOV AX. 1525h DS. Derleyici bu komut satırına hata verir. MOV AX. derleyiciniz hata mesajı verir. AX . 1525h . 15h . 5 word ptr [bx].segreg : segment register à segment kaydedicisi mem16 : memory 16 bit à 16 bitlik hafıza alanı (dw direktifi ile tanımlanan veriler) reg16 : register 16 bit à 16 bitlik kaydedici (AX. bu kullanım hatalıdır. MOV AX. 5 gibi bir komutla acaba hafızaya byte boyutunda bir 5 değerimi (05) yoksa word boyutunda bir 5 değerimi (0005) yüklenecek? Bunu kodlarınızda belirtmeniz gerekir.. sayi1 sayi2. 5 dword ptr [bx]. mem” tipinde bir kullanımdır. bunlardan birincisi “mem. Şayet acil adresleme kullanarak bir veri taşıyorsanız işlemci operandın boyutunu kaydediciye uyarlar. Böyle bir işlemi yapmak için genel amaçlı bir kaydediciyi kullanmanız gerekir. sayi2 . Ayrıca segment kaydedicilerine ancak 16 bitlik boyutunda değerler yüklenebileceğinden genel amaçlı kaydedicilerin 8 bitlik kısımlar değil 16 bitlik kısımları kullanılabilir. Doğru kullanım aşağıdaki gibi olmalıdır. 5 (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Segment kaydedicilerine bir değer yükleyebilmek için genellikle genel amaçlı kaydedicileri kullanılır. 5 gibi bir komut ile hafızaya neyin yükleneceği belli değildir (Burada BX kaydedicisine değil hafızaya taşıma yapıldığına dikkat edin) MOV [BX]. Yani hafızanın bir konumunda diğer bir konumuna doğrudan taşıma yapamazsınız. MOV sayi1. Örneğin MOV [BX]. mov mov mov byte ptr [bx].

kaynak Bu komutları aşağıdaki gibi kullanabilirsiniz. lds les lfs lgs lss reg16. LGS. mem32 reg16. Kullanım formatı aşağıdaki gibidir. LFS. mem32 reg16. böyle bir durumda ds:0000 adresine bir taşıma işlemi gerçekleşeceltir. LES. source reg16. mov byte ptr [bx]. Şayet operatör byte ptr değilde word ptr olsaydı o zaman ds:0000 ve ds:0001 adreslerine dırasıyla 05 ve 00 değerleri taşınacaktı. Ama bu adresten itibaren 05’mi yoksa 0005’mi yoksa 00000005’mi taşınacaktır? Đşte bunu ptr operatörü belirler. bunu “dd” direktifi ile oluşturabilirsiniz. mem reg. Genel kullanım formatı lea şeklindedir. reg16 eax. XCHG komutu xchg (exchange) komutu operandlarındaki değerleri yer değiştirir. mem32 (*) (*) (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir Reg16 genel amaçlı herhangi bir kaydedici olabilir mem32 ise double word boyutunda bir veri olmalıdır. reg32 (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir LDS. 5 satırını açıklayalım. ve LSS komutları Bu komutlar 32 bitlik bir hafıza bölgesindeki değeri bir segment kaydedicisine ve bir genel amaçlı kaydediciye bir defada yükler. mem32 reg16. LEA Komutu LEA (Load Effective Address – Etkin Adresi Yükle) sadece offset adreslerini hedef operandına yükleyen bir pointer gibi düşünebilirsiniz.mov byte ptr [bx]. Daha önce bu komutlardan biri olan LES komutu için “X86 Assembly Dilinde Değişken Bildirimi -1” adlı makalede çok güzel bir örnek vermiştim. LxS hedef. mem32 reg16. 80x86 ailesi için dört değişik kullanım şekli vardır. 5 komut satırı için ds:0000 adresine 1 byte’lık bir veri yani 05 taşınır. Burada BX=0000 olduğunu varsayalım. xchg xchg xchg xchg reg. lea dest. reg ax. Erişmek istediğimiz adresin segment ve ofset bölümlerini birleştirerek bir değişken oluşturuyor sonrada bunu program çalışırken istediğimiz gibi kullanıyorduk. mem HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Dizi PUSH ve POP komutları 80x86 push ve pop komutları Stack Memory (Yığın hafıza bölgesi) ile ilgili işlemlerde kullanılır. Yğın hafıza bölgesini sizler .24h Daha sonra bu dizinin adresini DX kaydedicisine yüklememiz gerektiğinde aşağıdaki komutu kullanmıştık. LEA DX. MOV DX. pop komutuda bu bölgeden veri almada kullanılır. mem (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir. Push komutu bu yığın olarak adlandırılan hafıza bölgesine verileri iterken. tüm bu bilgilere herhangi bir intel komut setinden faydalanarak bakabilirsiniz.Stack direktifi ile belirliyorsunuz.OFFSET Dizi Bu komutun yaptığı işi LEA kullanarakta yapabiliriz. imm (*) leave (*) (*) 80286 ve sonrası işlemcilerde kullanılabilir (**) 80386 ve sonrası işlemcilerde kullanılabilir HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .0Dh.lea reg32. Bazen MOV komutu LEA dan daha hızlı çalışabilir. Đşte bu bölge genellikle programdaki dallanma veya altrutinlerin çalışması sırasında. Daha önceki makalelerimizde ekrana bir karakter dizisini yazdırmıştık.0Ah. fakat hangi komutu kullanacağınıza adresleme moduna göre seçmelisiniz. Dizi DB "Merhaba Assembly". bunun için kaynak kodumuzda ekrana yazdılıralacak olan veriyi aşağıdaki gibi tanımlamıştık.exe tipi program hazırlarken . MOV komutunu da LEA komutu yerine kullanabilirsiniz. push reg16 pop reg16 push reg32 (**) pop reg32 (**) push segreg pop segreg (CS hariç) push memory pop memory push immediate_data (*) pusha (*) popa (*) pushad (**) popad (**) pushf popf pushfd (**) popfd (**) enter imm. dönüş adreslerinin ve bayrak kaydedicisinin durumlarını saklamak için kullanılır.

Genişletme Đşlemleri Bazen byte boyutundaki bir değeri word boyutuna veya word boyutundaki bir değeri doubleword boyutuna genişletmek gerekebilir. Bu gibi durunlarda aşağıdaki komutlar kullanılır. CWD. Segment kaydedicilerinden olan SS yığın hafıza bölgesinin segment adresini gösterir. CBW. Tabiî ki bu yığına itilen veya yığından çekilen değerin boyutuna bağlıdır. CWD komutunda olduğu gibi word boyutundaki bir değeri double word boyutuna genişletmede kullanılır. CBW komutundaki kurallar bu komut içinde geçerlidir. movzx olmalıdır. SS:SP her zaman yığının tepesi olarak tabir edilen noktayı gösterir. movsx olmalıdır. cwd Bu komut 80386 ve sonrası işlemcilere özeldir. CWDE.Hedef kaynağın iki katı büyüklüğünde hedef. cbw cwd (convert word to double word) komutu AX’in değerini DX:AX’e genişletir. ve CDQ Komutları cbw (convert byte to word) AL kaydedicisinin 1 byte’lık içeriğini AX’e genişletir.Push ve pop komutları kullanıldığında yığın hafıza bölgesinin işaretçisi olan SP kaydedicisi değişir. Bu komutlar 2 veya 4 byte’lık değerler ile işlem yaptığından yığına 2 bytelık bir değer itildiğinde (mesela bu AX kaydedicisinin içeriği olabilir) SP’nin değeri 2 byte azalır. Yığın hafıza bölgesi ile ilgili unutulmaması gereken üç önemli kural vardır. Tabiî ki yığına birden fazla word ya da doubleword itildiyse aralardaki değerler ile işlem yapmak adresleme modlarıyla mümkündür fakat bu SP’de herhangibir değişiklik yapmaz. kaynak . Şayet yığına 4 byte’lık değer itilirse SP’nin değeri 4 azalır. LAHF ve SAHF Komutları Bu komutlar bayrakları AH kaydedicisine yükler veya AH’a yüklenen bayrak kaydedicilerinin durumlarını kayar nokta kaydedicisine ( floating point register ) yükler.Hedef kaynağın iki katı büyüklüğünde reg32 MOVZX. kaynak . CWD AX’i DX:AX’e genişletirken bu komut AX’i EAX’e genişletir. MOVSX. Unutulmaması gereken önemli bir hususta yığın hafıza bölgesine itilen en son değerin çekilecek olan ilk değer olmasıdır. Bu komutlar 8086 zamanından kalma ve günümüzdeki modern assembly programlarında pek kullanılmayan komutlardır. cbw cwd cwde cdq bswap xlat hedef. Yığına bir şeyler itildikçe SP azalır eökildikçe artar. AL’deki değer negatifse AH’ın tüm bitleri ‘1’ olur. Şayet AL’deki değer pozitifse AH’ın tüm bitleri ‘0’ değerini alır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

al .CBW ve CWDE komutlarının birlikte yaptığı işi reg16.CBW komutunun yaptığı işi yapar. reg32. AL’ deki 8 bitlik değeri 32 bitlik dx:ax’e genişletmek için cbw cwd . movzx komutu movsx komutu gibi kullanılır fakat negatif değerleri genişletmek için kullanılmaz. Örneğin Apple’ın Machintosh bilgisayarları big andian hafıza yapısına sahiptir. reg32. mem8 reg8 mem8 reg8 mem16 reg16 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . . ax eax. Bu komutun sonundaki zx harfleri Đngilizcede zero extend yani sıfır ile genişlet gibi bir anlam taşır.cwde cdq komutu EAX kaydedicisindeki 32 bit’lik değeri EDX:EAX ‘e genişletir. AL’ deki 8 bitlik değeri 32 bitlik eax’e genişletmek için cbw cwde . BSWAP Komutu Bildiğiniz gibi x86 hafızası little endian yapıya sahiptir. Bu komutda 80386 ve sonrası işlemlerde kullanılır. reg32. reg32. cdq Örnekler: . Tüm bu genişletme komutları genellikle aritmetik işlemlerde ve özellikle bölme komutlarında kullanılır. bununla beraber big endian hafızaya sahip bilgisayarlarda çok sayıda mevcuttur. reg16. çünkü movzx komutu genişletme işleminde sadece bitleri ‘0’ yapabilir. kullanım formatları aşağıdaki gibidir. movsx movsx movsx movsx movsx movsx Örnekler: movsx movsx movsx yapar.CWDE komutunun yaptığı işi yapar. al eax. AL’ deki 8 bitlik değeri 64 bitlik edx:eax’e genişletmek için cbw cwde cdq movsx komutuda yukarıdaki komutlara benzer iş yapar. . BSWAP komutu bu farklı hafıza sistemlerine sahip olan bilgisayarlar arasında veri haberleşmesi ax.

E. bswap reg32 XLAT Komutu Genellikle tablo olarak tasarlanan dizilere erişmek için kullanılır. elemanını AL’ye yüklemek istersek. C. Kullandığım sistemin saat bilgisini ekrana yazdırmak istiyorum. @data MOV DS. Đndeks değeri (0 dan 0Ah’a kadar 11 tane değer var) LEA BX. 16-23 arasındaki bitleri 8-15 arasına ve son olarak 24-31 arasındaki bitleride 0-7 arasına yerleştirir. F Bu tablonun 11. 6. Tablonun 11. 5. BX’e (taban kaydedicisi) Tablonun ofset adresi yükleniyor XLAT . MOV AX. Tablo DB 0. BU komut sadece 80486 ve sonrası işlemcilerde kullanılabilir. 8-15 arasındak bitleri 16-23 arasına. Tabiî ki bu gibi işlemler için hali hazırda DOS’un kesmeleri mevcuttur. 0Ah . 2. AX Yığın komutlarınıda veri taşımak için kullanabileceğimizden. Bu komutu aşağıdaki örneğe bakarak daha iyi anlayabilirsiniz. 9. 3.yapılması için kullanılır. Tablo . BSWAP operandında belirtilen 32 bitlik kaydedicinin içindeki değeri byte-byte ters çevirir.exe tipi programlarda DS kaydedicisinin değerini belirlemek için bu güne kadar hep aşağıdaki iki satırı kullandık. 8. D. B. sonra bu kaydedicideki değeri yığına ittik son olarakta yığından bu değeri çekip DS kaydedicisine yükledik. A. 4. Öncelikle Push ve Pop komutlarını DS kaydedicisinin değerini belirlemek için kullanabilirim. MOV AL. Fonksiyon 2Ch sistem zamanı ile ilgili bilgileri işlemcinin kaydedicilerine getirir. MOV AH. @DATA AX DS Yukarıdaki üç satırda DATA segmentin adresini önce AX kaydedicisine yükledik. MOV PUSH POP AX. Düşük değerlikli sekiz biri en yüksek değerlikli bölgeye. AL kaydedicisine tablonun elemanlarından birini yükler. 7. elemanına erişilip ASCII karakterin hex karşılığı AL’ye yükleniyor (AL=41h) Şimdi yukarıda açıkladığımız komutlardan birkaçını kullanarak bir program yazalım ve daha sonra da inceleyelim. 1. Kullanım formatı aşağıdaki gibidir. CH = saat CL = dakika DH = saniye DL = salise HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . .2Ch INT 21h Bu komutlar işlenince CX ve DX kaydedicileri saat bilgisi ile yüklenirler.

"37$". Tabloda her saat değeri için 3 byte’lık değer ayrılmıştır ve bu programda CH veya CL deki değerler yardımıyla indeks adresi hesaplanırken 3 ile çarpmak gerekir.Ve BX’e saat bilgisinin desimal karşılığı olan tablo konumu yüklendi."03$"."44$"."16$"."41$"."56$". sadece CH veya CL deki değerleri 3 ile çarpsın yeter."35$"."06$".3 ile çarpılarak tablodaki desimal karşılığı bulundu."47$". Çevirme işlemleri için çarpma. AX . çok fazla kullanım formatı mevcuttur. Tüm bu işlemleri yapan kod satırları aşağıdaki gibidir."19$" DB "20$"."42$". elemanın 0 yani 30 elemandan itibaren 10 değerinin mevcut olduğunu görürsünüz."02$". Bunun yerine biz hex-decimal tablolar oluşturup bu tablolardan desimal değerleri bulalım ve ekrana yazdıralım."18$". Bizim için burada."17$"."15$". MUL komutunu önümüzdeki makalelerde inceleyeceğiz."13$"."49$" DB "50$"."12$". En büyük saat bilgisi 23:59 yani 0 ile 59 elemanlarını kapsayan bir tablo oluşturmam yeterli."57$".Kaydedicilerin içindeki değerlerin binary olduğunu ve debugger programlarında bu değerlerin hexadecimal formatta göründüğünü unutmayalım."24$"."29$" DB "30$"."52$". Fakat tabloların sınırlarını belirlemek için elimizdeki bilgiyi iyi tanımamız gerekir."07$". çünkü x86 hafızası byte adreslenebilir ve her rakam veya karakter hafızada 1 byte’lık yer kaplar. bu saat 10 demek.Şimdi saat bilgisi."31$"."33$"."04$". Fakat MUL komutu sadece AL deki değeri bir değişken yada AL kaydedicisi ile çarpabildiğinden önce CH yada CL deki bilgileri AL’ye taşımamız HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN ."45$"."08$"."21$"."46$". Diyelim ki CH’taki saat bilgisi 0Ah."09$" DB "10$". Tüm bu işlemleri yapıp ekrana yazdırılıcak değeride DX kaydedicisine yüklemeliyiz."26$"."27$". Çünkü ekranda bir karakter dizisini yazdırmak için INT 21h’ın 9."01$"."38$"."23$". SaatTablo DB"00$". CH . bölme gibi komutları bilmeniz gerekir ama henüz o komutlarla ilgili örnekler çözmedik. CH’ta saat 10’u temsilen 0Ah değeri bulunuyorsa 0Ah*3 = 1Eh = 30 hesabı yapılmalıdır."34$"."05$"."25$". MULUc . MOVDI."11$"."39$" DB "40$"."53$"."36$"."14$"."28$"."32$". MOVAL."54$". LEA DX."43$"."51$".Bu adres indeks olarak düşünüldüğünden DI ya yüklendi."55$"."58$". fonksiyonu karakter dizisinin başladığı adresi DX kaydedicisinde bulunmasını ister. Tabloda “10$” olan kısım acaba tablonun hangi adresidir? Sayacak olursanız 30. SaatTablo[DI] . elemanın 1 31. Biz bu programda kullanıcı ekranına desimal formatta değerler yazdıracağımızdan ya çevirme işlemi yapacağız yada tablo oluşturup hex bilgilerin karşılığına tablodan bakacağız."48$"."59$" Yukarıdaki tablo bize 60 elamanlı gibi görünebilir fakat hafızada 60*3=180 byte yer kaplar."22$".

Daha sonra 3 değeri ile çarpıp tablodan adresi buluyoruz.gerekiyor. DI veya BX kaydedicilerinin birinde olmalıdır. Bu noktadan sonra bu adresi DX kaydedisine yükleyip ekranda string yazdırma kesmesini çağırırsak işlem tamam olacaktı ama. SaatTablo taban adresine göre hesapladığımız indeks adresi halen AX kaydedicisinin içinde ve LEA DX. 12345678Ekrana “Saat” yazdır Sistem saatini ilgili kaydedicilere yükle Tablodan saat bilgisinin desimal karşılığını bul Ekrana yazdır : karakterini ekrana yazdır Sistem dakikasının karşılığını bul Ekrana yazdır Dur HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Tabiî ki Uc bir değişken ve data segmentinde tanımlı olmalıdır. Son olarak ekranda bir string yazdıracağımızdan DX kaydedicisinin içine yazdıracağımız stringin başlangıç adresini atarak ve daha önce de kullandığımız INT 21h fonksiyon 9h ı kullanabiliriz. Bununla beraber “:” karakterinide saat bilgisini yazdırırken saat ile dakika arasına yerleştirelim. Uc DB 3 Al deki değer 3 ile çarpıldığında sonuç 16 bitlik AX kaydedicisinde saklanır. Ayirac DB‘:’ Birde saat kelimesini data segmentte tanımlayalım. Indeks olarak kullanılacak adresler 8086 assembly dilinde SI. programımın algoritmasını da yazdıktan sonra kodlarımı yazmaya başlayabilirim. SaatTablo[AX] gibi bir komut satırı kullanamam çünkü böyle bir adresleme modu mevcut değil. bu yüzden bizde hesapladığımız indeks değerini DI ya yükledik. Saat DB ‘Saat $’ Şimdi kabataslak ne yapacağım belli oldu. tabiî ki bu bilgide data segmentinde bir adreste saklı kalsın.

Saat bilgisini ekranda gösteren program.Şekil 1 . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

5 ADD AX. hızında bir işlemci saniyede 1 milyar elektronik darbe üretebilir ve bu saniyede milyonlarca işlem yapabileceği anlamına gelir. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bu saat darbesi ne kadar hızlı olursa işlemler o kadar hızlı gerçekleşir. x := y + z + t işlemini. Elbette bu program daha kısa veya pratik bir şekilde yapılabilirdi. 80x86 KOMUT SETĐ (Bölüm 2) Aritmetik ve mantık (lojik) işlemler mikroişlemcinin ALU (Arithmetic Lojic Unit) denen kısmında yapılır. Aritmetik komutların genel kullanım formatları aşağıdaki gibidir.z. ADD komutu işlemci durum kaydedicisinin C bitini hesaba katmazken ADC toplama işlemini C bitinide dahil ederek yapar.t’ler birer hafıza konumu veya kaydedici olabilir. MOV AX. Y ADD AX. 5 ADC AX. Bunun için komut bilgimizi genişletmeliyiz. 6 Bu işlemden sonra AX kaydedicisinde 11’in karşılığı olan 000Bh değeri görülür. ALU bir dizi elektronik toplama.y. T MOV X. Ayrıca değişken bildirimlerini de şu ana kadar tam olarak anlatmadım. Bu devrelerin çalışma mantıkları ise sayma temelinden geçer. Tabiki bu x. Bu konularla ilgili makalelerimiz yolda fakat şu anda sizlerin mevcut bilgilerinizle bu programa birde salise kısmını ekleyebilmeniz gerekir. 3 ile 5’i toplarken 3’ün üzerine 5 tane parmak sayardık. Z ADD AX.Şekil 2 . Örneğin 1 GHz. ADD ve ADC komutları: Toplama ve elde ile toplama komutlarıdır. Bu komutları kullanırken de adresleme modlarına dikkat etmemiz gerektiğini unutmayalım. 6 Bu işlemden sonra şayet C=0 ise sonuç 000Bh C=1 ise sonuç 000Ch olacaktır. AX şeklinde yapabilirsiniz. Mikroişlemcide her saykılda (saat darbesinde) ALU’da bir sayma işlemi yapar. MOV AX. Bizlerde ilkokul sıralarında temel işlemleri parmaklarımızla sayarak yapardık. çıkarma ve mantık devrelerinden oluşmuştur.Programın ekran çıktısı. MOV AX.

AX Yukarıdaki şekilde bu işlemi yapabilrsiniz ama bu çokta iyi bir yol değildir. AX Bu yol daha iyi gibi görünsede bundan daha iyi çalışacak kodlar aşağıdaki gibidir. ADD ve ADC komutları işlemcinin bayrak kaydedicindeki bitlere şöyle etki ederler. Binary değerler ile desimal sayıları kodlamak gerekebilir (BCD). 2. 0 sonucu bir çok yerde önemli olabilir. X MOV BX. 3. 1. Bu durumda düşük değerlikli 4 bitte taşma olursa bayrak kaydedicisinin A biti 1 olur. Z ADD AX. 5. Đşaretli sayılarla işlem yaparken işaret taşmalarını göstermesi amacıyla V (overflow) bitine. südür. Bunu en hızlı şekilde işlemciye nasıl hesaplatabiliriz? 1. X ADD AX. Sonucun alana sığmadığı bu gibi durumlarda programcıyı haberdar etmesi amacıyla C=1 olur. Şayet sonuç negatif bir değerse S=1 değilse S=0 olur.yol MOV AX. x ve z hafızadaki birer değer olsun yani değişkenlerimiz. 3. Z MOV X. Çünkü bazen negatif bir sayı ile negatif başka bir sayı toplanır ve pozitif bir sonuç elde edilebilir.x := x + z işlemini düşünelim. 2. Đşaretsiz sayılarda işlem yaparken boyut taşmalarını göstermesi amacıyla C bitini. AX Adresleme modlarını akıllı bir şekilde kullanabilirseniz çok hızlı çalışan programlar hazırlayabilirsiniz. 4. Bu yüzden toplama komutları ile işlem yapıldığında sonuç 0 olursa Z=1 aksi halde Z=0 olur. Z ADD X. yol MOV AX. Bu yüzden A=1 olur ve işlemci programcıyı bu HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Örneğin 0000 1111b değerine 1 eklendiğinde sonuç 0001 0000b olacaktır ve düşük değerlikli 4 bitteki en büyük sayı olan 1111 birden 0 a düşecektir. BX MOV X. Yukarıdaki üç program parçası aynı işi yapmasına rağmen en hızlı çalışanı 3. Günümüzde kullanıcıya daha yakın ve program yazması daha kolay olan üst seviye programlama dillerine göre assembly dilinin en büyük avantajı budur.yol MOV AX. Örneğin 2 byte’lık bir değişken olan FFFFh (65535) ile 1 i toplarsınız sonuçta 0 elde edersiniz.

2 şeklindede yapabilirsiniz ve bu durumda sadece 1 adet komut satırı yazarsınız. Yani bu komutu aşağıdaki formatlarda kullanabilirsiniz. Bu komutların genel kullanım formatları aşağıdaki gibidir. Çıkartma işlemini yapan komutlar: SUB ve SBB komutları: SUB (Subtract) yani çıkartma SBB ise borç ile çıkart (SuBtract with Borrow) anlamına gelir. örneğin 0000 0101 değerinde 2 tane 1 vardır bu durumda P=1 olur.2 veya 4 bytelık operandı olabilir. reg reg. 6. Bu komutu aşağıdaki örnek ile daha iyi anlayacağınız kanaatindeyim. reg reg.1 formatına tercih edilir çünkü daha hızlıdır. BX . Döngülerde çok kullanılan bir komuttur. . INC komutunun 1. sub sub sub sub reg. buna rağmen peşpeşe 1 den fazla inc komutu kullanmak gerekirse komut setinin incelenmesinde fayda vardır. AX = 07h ve BX = 03h olsun XADD AX. 4 bytelık kaydedici INC HAFIZAADRESI . Her iki çıkartma işlemi bir çıkartma sonucu üretmenin yanında bayrak kaydedicisinin C bitinide etkilerler. 1 gibi çalışır. Ayrıca INC bayrak kaydedicisinin C bitine etki etmez. X kaydedici veya hafıza alanı olabilir. Oysa ADD ve ADC C bitine etki ederler ve büyük dizilerde bu komutlar kullanılırsa dizinin içindeki elemanları işaret etme işleminde bazen yanlış sonuç gösterebilirler. Bu yüzden dizi işlemleri için çok uygun bir komuttur. yani AX’teki kaybolan operand buraya taşınır. AX = 0Ah yeni toplama işleminin sonucunu gösterir. INC AL . 1 bytelık kaydedici INC AX . Byte word veya doubleword boyutundaki değişkenler olabilir.durumdan haberdar eder. INC komutu genelde ADD mem.2 veya ADD mem. . ve BX = 07h olur. immediate data HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 2 bytelık kaydedici INC EAX . Çünkü bu işi ADD reg.1 veya ADD reg. Bu komuttan sonra . mem mem. Elde edilen sonuçtaki binary 1 ler çift sayıda olursa. Kısaca hedefi 1 arttırır. XADD Komutu: 80486 ve sonrası işlemciler için geçerli bir toplama komutudur. INC Komutu: ADD X. Bu yüzden çok önemlidir.

kaynak şeklinde genellersek. SBB komutu ise. FFFAh’ın binary karşılığı 0000 0000 0000 0101 . 1111 1111 1111 1010 . Çünkü sonucu işaretsiz bir tamsayı gibi değerlendirirse yanılır. kaydedicideki FFFAh değerinin 15. P ve C bitini etkilerler. MOV AX. yani çıkana bu sonucu eklerseniz. biti 1 olduğundan sonuç negatif olarak değerlendirilmeli ve yukarıdaki işlem yapılarak sonucun gerçek değeri hesaplanınca. 1 fazlası yani 6 Ayrıca bu sonuç incelenirken. 0Ah SUB AX. S.C işlemlerini yapar. BX Yukarıdaki komutlar işlenince 04h-0Ah işlemi yapılır ve 2 byte’lık AX kaydedicisinin içinde FFFAh sonucu görülür. Çıkartma Aslında Toplamadır! HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . MOV AX. Bu işlemde büyük değerden küçük değer çıkartıldığından C bitinin durumunda bir değişiklik olmaz. FFFAh 000Ah ------0004h yukarıdaki 4h sonucuna erişirsiniz. immediate data sub eax/ax/al. tümleyeni 0000 0000 0000 0110 . Böyle bir sonuç elde edildiğinde sonucun tümleyeni alını ve 1 eklenir. immediate data Bu komutların ne yaptığını örnekler ile daha iyi anlayabiliriz. Z. SUB komutunun kullanımını SUB hedef. Çıkartma komutları toplama komutlarında da olduğu gibi bayrak kaydedicisinin. Bu işlemde ayrıca C biti set edilir ve C=1 olur. -6 değerine ulaşabilirsiniz. V. 0Ah MOV BX. BX Yukarıdaki komutlar ile işlemci 0Ah-04h işlemini yapar ve 6 sonucunu AX kaydedicisinin yani hedef kaydedicide saklar.kaynak . Programcı C’nin bu durumunu göz önünde bulundurmalıdır. A. 04h SUB AX. Tabiki bu etkilenen bayraklar yapılan işleme göre programcı tarafından değerlendirilmelidir. hedef = hedef . 04h MOV BX. hedef = hedef .kaynak.sub mem. Aslında FFFAh sonucunun sağlamasını yaparsanız.

Y . immediate data eax/ax/al.z işlemi yapılıp sonuç x’e yükleniyor. bite gelindiğinde eldenin olup olmadığı hakkında bilgi verir ve P işlem sonucundaki değeri binary olarak düşündüğümüzde 1’ler tekmi yoksa çift mi durumunu gösterir. x . Bu bayrakları değerlendirirken de işlemlerin işaretli yada işaretsiz sayılar ile yapıldığının bilinmesi büyük önem taşır. Programcı etkilenen bu bayrakları göreceli olarak yorumlayabilir. X SUB AX. genel kullanım formatları. reg reg.y . x = x . y .y . AX . Z .(y + z) değilmidir? MOV AX. MOV AX. mem mem. cmp cmp cmp cmp cmp cmp reg. başka bir deyişle -1 ekler. Fakat bu işlem aslında x = x . SUB AX.z işlemi yapılmış oluyor.z işlmi yapılmış oluyor MOV X. sonucu AX’e yükleniyor. CMP komutu: SUB komutu ile aynı işi yapar fakat çıkarma işleminin sonucunu herhangi bir kaydediciye yüklemez. CMP’nin anlamı "compare" yani karşılaştır demektir. C. INC komutu gibi genelde döngülerde her iterasyondan sonra sayacı azaltmak için kullanılır. Kullanım formatları aşağıdaki gibidir.z işlemi yapılıyor SUB X.4 aslında 3 + (-4) değil midir? Bu tür basit bilgileri unutmamak bazen sizin işinizi kolaylaştırabilir. A ara elde biti yani işlem yapılırken 3. Aşağıdaki örneği inceleyelim. AX . Şöyle ki. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . C. O ve S bitlerinin durumları ile ilgilenirler. sonuç x’e yüklenerek x = x . reg reg. P.y -z işlemini yapmak için. A ve P bayraklarından ziyade programcılar Z. Bakın neleri karşılaştırabiliyoruz. S ve Z bayraklarını etkiler.y . hedef operandını 1 eksiltir. x . Z . DEC komutu: Decrement yani azalt anlamına gelir. Y ADD AX. Bu komut genelde şartlı dallanma komutlarından önce bayrakları etkilemek için kullanılır. x-y işlemi yapılıyor. DEC reg DEC mem DEC reg16 C biti hariç çıkartma komutların etkilediği bayrakları etkileyen bir komuttur.3 . immediate data Bu komut A. O. immediate data mem.

O=0 ise 2. O=1 ise 1. Şartlı Dallanma Komutları: Đngilizce karşılığı Conditional Jump Instructions’dır.operand dan büyük demektir. Bu tür komutları bundan sonra JXXX komutları olarak kullanacağım. 2. JNAE JNB. JAE JE JNE JPE JP JPO JNP JNC JC JNZ JZ JNS JS JNO JO JNP JPO JP JPE HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . O=1 veya S=1. O=0 veya S=1.5 mov bx. Bunlar. operand’tan büyüktür.S=0. mov ax.2 yada 3 harf şartı gösterir.S ve O bayrakları işaretsiz sayılarda anlamsız olurken işaretli sayılarda 2 değişik durumu gösterirler. Bu tür komutlar işlendikten sonra program ya normal akışına yani komutları satır-satır işlemeye devam eder ya da normal akışından sapıp başka bir adresteki komutu işler. operand 1. Karar alma mekanizmaları bu komutlar ile yapıldığından çok önemli komutlar olduğunu sanırım tahmin edebilirsiniz. operand’tan büyüktür.C bayrağı işaretsiz sayılarda. Tüm bu anlamlar ve komutları aşağıdaki 3 tabloda özetleyebiliriz. b. operand 2. Z=1 yani operandlar eşit. Şartlı dallanma komutlarının ilk harfi J ile başlar ve takip eden 1. JXXX komutlarının da CMP komutları gibi işaretli ve işaretsiz değerler için farklı anlamları vardır. operand büyüktür.Z bayrağı sayılar ister işaretli ister işaretsiz olsun eşitlik yada eşit olmama durumunu gösterir. C bayrağının işaretli sayılarda bize verdiği sonuçların bir anlamı yoktur. C=0 ise 1. 3. a. C=1 ise 2. operand 1.5 CMP ax.1.bx .S=0. Bayrakların Durumunu Test Etmek Đçin Jxxx Komutları Komut Açıklama Şart Eş Komut Karşıt Komut JC JNC JZ JNZ JS JNS JO JNO JP JPE JNP JPO Jump if carry (carry (taşıma) bayrağı 1 ise) Jump if no carry (carry (taşıma) bayrağı 0 ise) Jump if zero (zero (sıfır) bayrağı 1 ise) Jump if not zero (zero (sıfır) bayrağı 0 ise) Jump if sign (sign (işaret) bayrağı 1 ise) Jump if no sign (sign (işaret) bayrağı 1 ise) Jump if overflow (overflow (taşma) bayrağı 1 ise) Jump if no Overflow (overflow (taşma) bayrağı 0 ise) Jump if parity (parity (eşlik) bayrağı 1 ise) Jump if parity even (sonuçtaki 1’ler çift ise) Jump if no parity (parity (eşlik) bayrağı 0 ise) Jump if parity odd (sonuçtaki 1’ler tek ise) Carry = 1 Carry = 0 Zero = 1 Zero = 0 Sign = 1 Sign = 0 Ovrflw=1 Ovrflw=0 Parity = 1 Parity = 1 Parity = 0 Parity = 0 JB.

Tüm programlama dillerinde kullanılan if. xxx kısmı ise şarta göre değişir. deyimler aslında şartlı dallanma komutları ile düzenlenmiş bir kaç assembly komutuna benzetilebilir. Hatta işi biraz daha netleştirelim C dilinde kullandığımız "if" deyimi aslında bir adet cmp ve bir adet Jxxx komutundan oluşur. JNAE JNB JC. for. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . JNB JNAE JNC. JAE JB JC.Đşaretsiz Sayılarda Jxxx Komutları Komut Açıklama Şart Eş Komut Karşıt Komut JA Jump if above (>) (Yukarısındaysa) Jump if not below or equal (not <=) JNBE (Aşağısında değil yada eşit değilse) JAE Jump if above or equal (>=) (Yukarısında veya eşitse) JNB Jump if not below (not <) (Aşağısında değilse) JB Jump if below (<) (Aşağısındaysa) Jump if not above or equal (not >=) JNAE (Yukarısında değil veya eşit değilse) JBE JNA JE JNE Jump if below or equal (<=) (Aşağısında veya eşitse) Jump if not above (not >) (Yukarısında değilse) Jump if equal (=) (Eşitse) Jump if not equal (!=) (Eşit Değilse) Carry=0. küçük. Assembler her iki komut içinde aynı makine kodunu üretir. Zero=0 Carry = 0 Carry = 0 Carry = 1 Carry = 1 Carry = 1 or Zero = 1 Carry = 1 or Zero = 1 Zero = 1 Zero = 0 JNBE JA JNA JBE JNC. Tablolarda aslında aynı işi yapan hatta makine düzeyinde aynı kodu üreten komutlar vardır. fakat programcıyı assembly kodlarını yazarken birazcık olsun rahatlatması için Intel bu tür yazımı uygun görmüştür. yukarısında veya aşağısında kelimeleri sayıların değerleri açısındandır. JB JNA JBE JZ JNZ JAE JNBE JA JNE JE Đşaretli Sayılarda Jxxx Komutları Komut Açıklama Şart Eş Komut Karşıt Komut JG JNLE Jump if greater (>) (Büyükse) Jump if not less than or equal (not <=) (Düşük değilse yada eşit değilse) Jump if greater than or equal (>=) JGE (Büyükse veya eşitse) JNL Jump if not less than (not <) (Düşük değilse) JL Jump if less than (<) (Düşükse) Jump if not greater or equal (not >=) JNGE (Büyük değilse veya eşit değilse) Jump if less than or equal (<=) (Düşükse veya JLE eşitse) JNG JE JNE Jump if not greater than (not >) (Büyük değilse) Jump if equal (=) (Eşitse) Jump if not equal (!=) (Eşit değilse) Sign = Ovrflw or Zero=0 Sign = Ovrflw or Zero=0 Sign = Ovrflw Sign = Ovrflw Sign Ovrflw Sign Ovrflw Sign Ovrflw or Zero = 1 Sign Ovrflw or Zero = 1 Zero = 1 Zero = 0 JNLE JG JNL JGE JNGE JL JNG JLE JZ JNZ JNG JLE JGE JL JNL JGE JNLE JG JNE JE Tabiki yukarıda kullandığım büyük. while vb. Zero=0 Carry=0. Bunlara örnek olarak JA ve JNBE’yi örnek verebiliriz. Aşağıdaki örnekle bu olayı daha iyi anlayabilirsiniz.

Şekil 1 . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .C Dili ile yazılmış bir program.

Şekil 2 - Programın assembly kodlarına baktığımızda if deyimine karşılık CMP ve JLE komutlarını görüyoruz.

1. şekilde C dilinde yazılmış basit bir program görüyorsunuz. Bu programda tamsayı türünden 2 adet değişken (a ve b) ve karakter türünden 1 adet değişken mevcut (sonuc). IF deyimi ile şayet a, b’den büyükse (ki zaten öyle) sonuç değişkenine büyüğü temsilen b karakteri aksi durumda küçüğü temsilen k karakteri yüklenecek. Şimdi burada bizi ilgilendiren C dilinde IF acaba assembly’de neye karşılık geliyor? Şekil 2 ye baktığınızda bu sorunun cevabını hemen görüyorsunuz. IF aslında CMP ve JLE komutlarının bir kombinasyonuymuş. JLE yerine başka bir şartlı dallanma komutu gelebilirdi, bu tamamen IF ile kullandığınız şarta bağlıdır, bu programda IF (a>b) kullanılmıştı. Assembly karşılığında a’nın değeri olan 5 önce eax kaydedicisine yükleniyor ve sonra hafızadaki b değişkeni değeri ile yani 4 ile karşılaştırılıyor.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

JLE satırına dikkat edin, JLE’nin anlamı less or equal yani düşük yada eşitse. Yani a’nın değeri olan 5 b’nin değeri olan 4’ten düşük yada eşitse, program 00411A3E adresinden devam edip, önce eax’e k karakterini yükleyip (daha doğrusu k’nın ASCII kod karşılığını yükleyecek), bunu hafızadaki "sonuc" adlı yere (sonuc da aslında bir adres :)) kaydedecektir. Tabi 5 4’ten büyüktür. Hal böyle olunca bu programda JLE komutu işlendikten sonra bir dallanma söz konusu değildir. Yani program normal akışını devam ettirecek ve eax’e "b" karakterini ardından da sonuc adlı adrese kopyalayacaktır. Bu programın assembly kodlarını daha önce görmediğimiz bir biçimde birazcık farklı görmeniz doğaldır. Bunun nedeni Visual Studio.NET’in C derleyicisinin 32 bitlik olduğundandır. Yani bu güne kadar biz 16 bitlik TASM veya MASM’ı kullandık. Bu yüzden eax kaydedicisini göremedik veya adresleri buradaki gibi 32 bitlik değil de hep 16 bitlik offsetler halinde gördük. Bu yüzden assembly kodları biraz farklı. 32 bitlik kodlama bizim için henüz çok erken bir kavram, bu yüzden bundan sonraki makalelerimizde 16 bitlik kodlamaya devam edeceğiz.

80x86 KOMUT SETĐ (Bölüm 3) NEG komutu NEG negatif kelimesinin kısaltmasıdır. Tek operandı vardır. Kullanım formatı aşağıdaki gibidir. neg neg reg mem

yani operandı herhangi bir kaydedici veya hafıza adresi olabilir. Yaptığı iş operandın değerinin negatifini almaktır. Daha doğru bir deyişle operandını 0’dan çıkartır. Binary düzende düşünecek olursanız 1’lein yerine sıfır 0’ların yerine 1 getirir ve bu sonuca 1 ekler. mov neg al,0fh ax

yukarıdaki işlemden sonra AX’in içeriği F1h olacaktır. 0Fh = 0000 1111 tersi = 1111 0000 1111 0000 +1 = 1111 0001 = F1h Bu komutun ne amaçla kullanılabileceğini makalenin sonlarına doğru anlayacaksınız. MUL ve IMUL Komutları MUL çarpma IMUL ise işareti dikkate alarak çarpma işlemlerini yapar. Kullanım formatı aşağıdaki gibidir. Đşaretsiz çarpma: mul mul reg mem

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

Đşaretli çarpma: imul imul imul imul imul imul imul reg mem reg, reg, imm (*) reg, mem, imm (*) reg, imm (*) reg, reg (**) reg, mem (**)

*- Sadece 286 ve sonrası işlemcilerde. **- Sadece 386 ve sonrası işlemcilerde.

IMUL komutunun 286 ve 386 dan sonraki kullanım formatlarına bakacak olursanız, bu güne kadar gördüğümüz formatlardan biraz farklı olduğunu görürsünüz. Bu kullanım şekilleri programcıların kafasını biraz karıştırmakla beraber tek bir komut satırı ile çabucak çarpma işlemini yapmasını sağlar. Nede olsa Intel karmaşık komut setini benimsemiştir. Çarpma komutları bayt-bayt, word-word veya Doubleword-Doubleword çarpma yapabilir. Tabi ki Doubleword çarpım için 386 ve sonrası işlemci kullanmanız gerekiyor, çünkü 32 bitlik kaydediciler 386 ile birlikte gelmiştir. Ayrıca çarpma işlemi toplamadan daha büyük sonuçlar çıkarabilir. Yani 2 basamaklı bir değeri başka bir 2 basamaklı değer ile toplarsanız sonuç en fazla 3 basamaklı çıkarken çarpmada bu 4 basamağa kadar çıkabilir. Daha fazla basamaklı sayıların çarpımında sonuç çarpılan veya çarpandan çok daha fazla basamaklı çıkabilir. Bu gerçeği göz önüne alarak işlemci tasarımcıları sonucu her zaman çarpan ve çarpılanın boyutundan daha büyük bir kaydedicide saklama yoluna gitmişlerdir. Bunları aşağıdaki şekil ve açıklamalarla daha iyi anlayacaksınız. Byte Çarpma

27h ile 17h’ı çarpmak için; mov mov mul al, 27h dl, 17h dl

komutlarını kullanabilirsiniz. Burada "mul dl" komutu ile DL*AL işlemi yani bu kaydedicilerdeki değerler olan 17h ve 27h sayıları çarpılır. Peki sonuç nerede? Yukarıdaki şekle baktığınızda sonucun AX içinde olacağını görebilirsiniz. Bu çarpma işleminden sonra AX’te 0381h değeri görülür.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

. Aynı şeyi tabi ki çarpan için yani 100h değeri içinde yapabilirsiniz.100h mul bx böylece 2345h değeri daima "carpılan" ismi ile hafızada korunur. Word Çarpma Bu tür bir çarpma işleminde operand AX ile çarpılır ve sonuç DX-AX kaydedicilerinden okunur. carpilan db 2345h . . mov mul al. Aşağıdaki örnekleri inceleyin. Fakat çarpılan değer yani 2345h bu işlemden sonra kaybolacaktır.sayi al komutlarını kullanabilirsiniz. 2345h bx. Şayet bu çarpılan değer sizin için önemliyse... carpilan mov bx. 100h bx bu işlemden sonra DX=0023h ve AX=4500h olur. .. Benim tavsiyem bu tür çarpmalarda çarpan ve çarpılanı birer değişken olarak programınızın data segmentinde tanımlamanızdır. Sonucun düşük değerlikli byte’ı ise AX kaydedicisinde saklanır. . carpilan carpan . mov ax. Burada dikkat ederseniz çarpma işlemiyle birlikte AX kaydedicisindeki "çarpılan" da kaybedilecektir. mov mov mul ax. DX’te daha önce ne olduğu önemli değildir çünkü çarpmadan sonra buraya sonucun yüksek değerlikli byte’ı yerleşir.Pratik olarak 8 bitlik bir değerin karesini almak için. db db 2345h 100h HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 100h ile 2345h değerlerini çarpalım.. Yani asıl sonuç olan 234500h değerinin yüksek değerlikli word’u DX’te düşük değerlikli kısmıda AX’te görülür.

. 2. carpilan mov bx... carpan bx Double Word Çarpma Double word boyutundaki verilerin çarpımında da word dekine benzer bir yapı kullanılır. . carpilan dd 12345678h carpan dd 34522344h . MUL komutu bayrak kaydedicisinin C ve O bitlerini etkiler. bu işlemi 16 bitlik bir programlama ile de halledebilmemize rağmen 2 katı daha fazla komut yazmamız gerekir.Byte boyutundaki bir operand AL ile çarpılırsa sonuç AX’te görülür.386 32 bitlik kaydedicileri kullanmak için assembler’a verilen bir direktif (talimat) dır. Bu çarpma işleminden sonra EDX=03B878D6h ve EAX=10295FE0h olur. Buradaki . carpilan bx.Word çarpmada C ve O sıfır ise DX’te sıfır demektir. 1. aksi durumlarda bu bayraklar set olur. Çarpılan değer EAX kaydedicisine yerleştirilip. ... Daha sonra elde edilen sonucun yüksek değerlikli doubleword’u EDX’te düşük değerlikli doubleword’ü ise EAX’te saklanır. carpan mul bx Yukarıdaki örnekte sonuç olarak işlemci 03B878D610295FE0h değerini hesaplar.386 . MUL veya IMUL komutunun peşinden gelen operand ile bu değer çarpılır.. 32 bitlik programlama. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . EDX ve EAX gibi 32 kaydedicilerin 32 bitlik alanlarını kullanmak için nu talimatı vermeniz gerekir. AH=0 ise C ve O sıfır olur. Bu bayraklar beraber değerlendirildiğinde aşağıdaki sonuçlar çıkartılır. 16 bitlik programlama nedir bunlar? Şimdilik sadece 32 bitlik programların 16 bitliklere göre daha avantajlı olduğunu görebilirsiniz. . mov ax. Çünkü 32 bitlik programlama ile kaydedici boyutlarımı 2 katına çıkıyor ve bir kaydedicide hesaplayabileceğimiz değerlerde aynı oranda artıyor. aksi durumlarda bu bayraklar set (1) olur. Yani sonuç 64 bitliktir. mov mov mul ax.

Double word çarpmada ise C ve O sıfır ise EDX’te sıfır demektir. reg16. bununla beraber IMUL komutuna özel çok operandlı kullanım formatlarıda mevcuttur. bu durumlara Intel’in komut setinden bakabilirsiniz. imul operand1. Ayrıca bu çarpma işlemlerinde sonucun boyutu operandta belirtilen kaydedicilerin boyutuyla aynıdır. imm8 mem16. reg16. imm8 (*) mem32. reg16. Yukarıdaki üç durum soldaki sıfırların çarmada bir değeri olmadığından. IMUL ile Diğer Çarpma Formatları IMUL (Integer Multiplication) komutu ile yukarıdaki MUL komutu için verilmiş kalıpları kullanabilirsiniz. BX = 0004h ax. reg32. Tüm kullanım formatları bu makalenin başında verildiği gibidir fakat kaydedicilerin 8 16 ve 32 bitlik durumları da göz önüne almamız gerekir. imm16 imm8 imm6 reg32. AX = 4 * 3 = 000Ch Bu komutlar ile 8x8 bit çarpım söz konusu değildir. aksi durumlarda bu bayraklar yine set olur. reg32.3. Şimdi henüz açıklamadığımız 286 ve 386 sonrası işlemcilerde kullanılabilen komut formatlarını aşağıdaki örneklerle inceleyelim. imm8 reg16. imm32 (*) mem32. reg32. reg16. Bu durumda sonucun hedef kaydediciye sığmaması durumuna karşı C ve O bitleri birlikte kontrol edilmelidir. operand2. bx. imm16 mem16. yani makalenin başında anlattığımız mul komutu gibi sonuç operandın 2 katı olmaz. sonucu optimize etmenize yardımcı olacaktır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . imm32 (*) imm8 (*) imm32 (*) * Sadece 80386 ve sonrası işlemcilerde kullanılabilir Yukarıdaki komut formatlarının 3 operandlı olanları operand1 := operand2 x imm ve 2 operandlı olanlarıda operand1 := operand1 x imm şeklinde çalışır. .Genel kullanım formatı reg16. 4 . mov imul bx. reg32. Her zaman son kullanılacak olan operandın "imm" yani sayısal bir değer olduğuna dikkatinizi çekerim. imm imul imul imul imul imul imul imul imul imul imul imul imul reg16. reg32. 3 . reg16. reg32. imm8 (*) reg32. imm8 olarak yukarıda gördüğünüz operand sadece komutunun makine kodunun olmasını sağlar.

an azından Intel bu komutlar için böyle bir form öngörmüştür. Đşaretli çarpma Word’u Byte’a Bölmek Örnek: 10h:3h işlemini yapmak istiyoruz. 10h şimdi 0010h ve AX’te bl . bl’ye bölündü bu işlemden sonra AX. bu değerlerin ikisinin de byte türünden olduğunu varsayalım. hatırlarsanız bu tür komutları daha önceki makalelerimizde açıklamıştık. Đşaretsiz çarpma . ax. Bu konuya çok boyutlu dizileri ve karmaşık veri yapılarını anlatırken bir daha değinmeyi düşünüyorum. Nitekim 16’nın (yani 10h) 3’e bölümü ile de bu sonuç üretilir. IMUL komutu için Intel’in 80286 ve sonrası işlemcilere koyduğu bu adresleme biçimleri çok boyutlu diziler ile yapılan işlemleri hatırı sayılır biçimde kolaylaştırmıştır. 10h bl. çünkü x86 Assembly dilinde en küçük veri tipi byte’dır. bu yüzden bu komutları kullanırken bölünen’in boyutu bölen’in boyutunun iki katı olmak zorundadır. Aynı şekilde sonucun işaretini öğrenmek için işaret bayrağı yerine C ve O bitlerinin sıfır olup olmadığı kontrol edilmelidir. DIV ve IDIV Komutları DIV division yani bölme kelimesinin kısaltmasıdır. Doubleword’u Word’e Bölmek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bl yerine başka bir kaydedicide olabilir! . Bu yüzden bölünenin boyutu en az word türünde olmalıdır. div div idiv idiv reg mem reg mem . 03h . Div ve idiv komutlarının genel kullanım formatları aşağıdaki gibidir. Bölme işlemi çarpmanın tersine bölünen’e göre küçük sonuç üretir. AH’taki 01h kalan ve AL’deki 05h ise bölümdür.Bununla beraber bu formattaki çarpma komutları Z bitini her zaman doğru bir şekilde etkilemeyebilir. şayet sonucun sıfır olup olmadığı sizin için önemli ise ancak sonucu sıfır ile karşılaştırdıktan sonra Z bitini kontrol etmelisiniz. Bu tür bölme işleminde elde edebileceğiniz en büyük bölüm 255 (FFh işaretsiz değerler için) yada 127 (7Fh işaretli değerler için) değerleridir. Bu durumda byte türünden bir değeri bölmek isterseniz bunu CBW komutu ile word boyutuna dönüştürmeniz gerekir. 0105h olur. mov mov cbw div al.

aynı kağıt üzerinde normal bölme işlemi yapar gibi. Fakat kalanı 10 ile çarpıp sonrada bölünen ile karşılaştırıp şayet bölünenden büyükse tekrar bölene bölme işlemine gidebilirsiniz. artık bu komutları kullanarak basit bir hesap makinesi programı yazmak isteyebilirsiniz. çıkartma. Bu yöntem sıkça kullanılmaz. bu tamamen kullanıcının hayal gücüne kalmış bir olaydır. çarpma ve bölme komutlarını gördük.Bu tür bölme işleminde elde edebileceğiniz en büyük bölüm 32767 (FFFFh işaretsiz değerler için) yada 16383 (7FFFFh işaretli değerler için) değerleridir.666. 8086 komut seti (bölüm 1) başlıklı makalemizde saat programı yapmıştık ve kaydedicilerde elde ettiğimiz sonuçları bir tablo vasıtasıyla ASCII karakterlerini ekranda göstermiştik. Quadword’u Doubleword’e Bölmek Peki ya sonuç tam değilse? Mesela 11h’ı (yani 17’yi) 3’e bölerseniz sonuç normalde 5. Evet ekrana yazdırmak için daha önce programlar yazdık fakat bunu sadece stringler ile gerçekleştirdik. Bu arada floating point ünitelerini kullanmak için yüksek seviyeli assembly kodları yazmak gerekir ve bu iş bizim için henüz çok erken. böyle bir programı yazmaya başladığınızda karşınıza sonuçları ekranda desimal formatta göstermek gibi bir problem çıkacaktır. yani bölüm 5 ve kalan 2. Özetle 17’nin içinde 5 tane 3 ve 1 tane’de 2 vardır ve div ve idiv komutları tamsayı bölme işlemlerini gerçekleştirebilir. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . hatta daha önce bu iş için bu yöntemi kullanan bir program görmedim diyebilirim.. fakat floating point ünitelerini kullanmak inanın bu işten daha pratiktir ve daha kolay sonuç verir. Malesef Tüm Sonuçlar Binary Toplama. DB direktifi ile deklare edilen kelime katarları (stringler) hafızada byte-byte ve ardışık olarak saklanır aynı zamanda bu byte’lar elbette harflerin veya sayıların ASCII kod karşılıklarıdır. Representation yani gösterme veya sunum işlemi çok geniş bir yelpazede incelenebilir. 80486 DX işlemcisine kadar matematik işlemci normal işlemcinin yanına opsiyonel olarak konulurdu mesela işlemci 80386 ise matematik işlemcisi 80387 olurdu. bu işlemi div komutu ile yaptığınızda ise AX’te 0205h değerini görürsünüz.. Artık matematik işlemcisi normal işlemcinin içine gömülü olarak geliyor. şeklinde olur. Benim burada anlatmaya çalışacağım olay ise ekran text modunda iken hafızadaki binary ifadelerin ASCII karakter karşılıklarını ekranda göstermek olacaktır. Ondalıklı bölme işlemleri için floating point kaydedicileri kullanılır ve bu kaydediciler matematik işlemcisinin içindedir.

ax . AAS Komutları Klavyeden giriş yapıldığında. mov sonuc. Şayet ekrana bir karakter basılacaksa bu karakter ekrana gönderilmeden önce ascii forma dönüştürülmelidir. x86 tabanlı işlemciler hafızayı adreslerken little endian byte sıralamasını kullanırlar. Keşke AX’teki 0203h değerinde 0’ların yerine 3 gelseydi. şimdi ekrana sırasıyla 33h’ı ve 32h’ı gönderirsek kullanıcı 32 yi görecektir. klavyedeki en büyük tuş yani. Diğer bir gerçek 3’un ascii kod karşılığı 33h ve 2 nin ki ise 32h dır. or ax. bunu direk olarak ekrana yazdırırsanız sadece imleci 1 kez ilerletmiş olursunuz çünkü 20h ascii kod tablosunda space yani boşluk karakterine karşılık gelir.3030h . harflerin ve bir dizi kontrol karakterinin kod karşılıkları vardır sayıların kod karşılıkları yoktur. Bu bağlamda biz 32 yi değil 3 ve 2 yi yan yana ekranda göstermeyi düşünmeliyiz.AX’teki 0203h artık 3233h oldu. basılan tuşa ait kod hafızada ascii formatta saklanır. Peki 32yi nasıl yazdıracağız? Unutmayın ki ascii kod tablosunda sadece rakamların. böylece ax ile al’nin içeriklerini takas etmemize de gerek kalmaz.sonuc ah. bu yüzden al’deki düşük değerlikli byte hafızanın düşük numaralı adresine ax’teki yüksek değerlikli byte’ta hafızanın yüksek numaralı adresine yerleşmiş olur. Ama şu anda AL’de ne 3 ne 2 var sadece 20h var. Problemi özetleyelim elimizde bir baytlık 20h var ve bizim bunu 2 byte lık 3332h dizisine dönüştürmemiz gerekiyor. 20h ı 0ah yani 10’a bölsek zaten hex’den decimal’e dönüşüm işlemi yapmış oluruz. mov mov div ax.Diyelim ki bir işlem yaptınız ve sonucunu 20h (32) olarak AL kaydedicisinde saklamayı başardınız ve bunu ekranda göstereceksiniz. birde al ile ah’ı yer değiştirsek! Acaba buna gerçekten gerek var mı? Hatırlarsanız ekrana bir string yazdırmak için DOS kesmelerinden 09h nolu fonksiyonunu kullanmıştık ve bu fonksiyon hafızadaki stringleri yazdırıyordu. 20h bl. Keşke bir komut bu işlemi bizim yerimize yapsa! Böyle bir komut varmı yokmu oraya geleceğiz ama 20h ile 3332h arasında güzel bir bağ var. Artık sonuc değişkenini referans göstererek ekrana yazdırma kesmesini kullanabilirsiniz. lea mov int dx. yani biz AX’teki bu 3233h değerini önce bir hafızaya atalım sonra 32h ile 33h’ın yerini değiştirmek gerekiyor mu düşünürüz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . sonuc=3332h olur. 30h ile 39h arası ascii kod tablosunda rakamlar için ayrılmıştır.AX=0203 yapar. mikroişlemci hesaplamaları binary yapar bu yüzden ascii’den binary’ye dönüşüm yapmak gerekir. 0Ah bl .9 21h AAA.

şayet aynı değer hafızada 12 34 byte dizisi olarak saklanırsa bu da paketlenmiş BCD’dir. AAA. Bu komutların operandı yoktur AL kaydedicisindeki değerleri dönüştürürler. AH temizleniyor . AL = 34h 34h artık ascii olarak 4 demektir. buna BCD (Binary Coded Decimal) kodlama diyoruz. Sonuç AL’de 09 olarak görülür.Bizler günlük yaşamımızda desimal değerleri kullanırız. 6 ADD AL. SUB AH. Desimal numaralar hafızada BCD olarak gösterilmenin yanında ASCII olarakta gösterilebilir. 8 AAA OR AL. bunlar packed BCD (paketlenmiş BCD) ve unpacked (paketlenmemiş) BCD’dir. AH MOV AL. Đşte AAA. 36 = 0011 0100 35 = 0011 0101 +_______________ 6B = 0110 1011 Sonuç 11 olması gerekir AAA komutu B değerinin yerine 1 koyar ve toplama sonucu 9 değerini aştığından AH kaydedicisine de 1 koyar.30h . yani AX = 0101 olur. 1234 hafızada 01 02 03 04 byte dizisi olarak saklanırsa bu paketlenmemiş BCD’dir. AAS gibi komutları bunun için kullanıyoruz. Henüz mantıksal komutları görmedik bu HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . AAA (Ascii Adjust After Addition) komutu toplama komutundan sonra sonucu ascii ye ayarlar. Örneğin klavyeden girilen 1234 hafızada 31 32 33 34 olarak ASCII formda saklanır. BCD gösterimin ise iki farklı çeşidi vardır. Tüm bu işlemlerden sonra OR komutunu kullanarak sonucu ASCII gösterim için hazırlayabiliriz. bu desimal değerleri hafızada binary rakamlar olan 1 ve 0’ları kullanarak gösterebiliriz. DAA. Tabi burada AH kaydedicisini de kontrol edip şayet 01 ise bu değeri de 30h ile OR işlemine tabii tutmalıyız. Aşağıdaki örnekleri inceleyin. AL + 08h işlemi yapıldı sonuç 0Eh . AX = 0104h . 34h = 0011 0100b 35h = 0011 0101b +_______________ 69h = 0110 1001b Sonuç 09 olması gerekir AAA komutu 6 değerini siler. ilk değer AL’de . AAD ve AAM komutlarının hepsi ascii değerlere dönüşüm için kullanılır. AAS. Bu tür işlemler için genelde ekrana tek bir karakter basma fonksiyonu kullanılır yani AL’deki değer teker teker ekrana bastırılır.

bu yüzden açıklamalara dikkat edin. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .yüzden aşağıdaki programı tam olarak anlamayabilirsiniz.

Bu durumda sonucu doğrudan 30h ile OR işlemine tabi tutmak hatalı olacaktır. mov al.30h yukarıdaki kod parçası sonuç negatif olsa da pozitif olsa da. Daha sonra 7 ve 8 değerleri girilmiş ve sonuç 15 olarak ekrana basılmış. sonucun mutlak değerini doğru bir şekilde ascii değere dönüştürür. or al. Unutmayalım ki klavye bize ekran text moundayken daima ascii değerler verecektir.35h sub al. AH’tan 1 çıkartılır.31h aas . ascii 5 . Tabiki bu 4 değeri ekrana yazdırılmadan önce önüne . şayet AF bayrağı 1 ise (başka bir deyişle bu 4 bit Ah.5-1=4 AF=0 olduğundan bir değişiklik olmaz sonuç hala 04h . çıkartma komutundan sonra sonucu ASCII’ye ayarlamak için kullanılır. mov sub aas al. AX = FF06 (yanlış sonuç) yukarıdaki gibi bir durumda SUB komutu ile A ve C bayrakları set (1) olur. şayet AAA komutundan önceki bayrakların durumu sizin için önemliyse bayrakların durumunu saklamanız gerekir.sonuç FCh (negatif) . Yukarıdaki şekilde program ilk çakıştırıldığında klavyeden sırayla 2 ve 3 girilmiş ve sonuç 5 olarak ekrana basılmış. FCh sonucu desimal -4 değerine eşittir bu yüzden burada programcı OR komutu ile doğru ascii değeri ekrana yazdırmadan önce NEG komutu ile tersini alabilir.34h .Şekil .ascii 4 .34h sub al.34h al.38h jnc devam neg al devam: aas or al. Bu durumda sonuc 4 olacaktır.38h . AAS komutu sekiz bitlik AL kaydedicisinin yüksek değerlikli 4 bitini kontrol eder.Makine dilinden insan diline dönüşüm Pekte güzel bir ekran çıktısı olmasa da bu program dönüşümleri anlamak için iyi bir örnektir. mov al. bu çarpma ve bölme işlemlerinde de problem oluşturur. AH’tan 1 çıkartmak normalde 00 olan AH’ı FF yapmak yani rakamın negatifliğini ayarlamak demektir..ascii 8 -. Klavyeden girilen değerlere sanki 30 eklenmiş gibi geleceğinden çarpma işleminin sonucu HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .işareti konulmalı.. ascii 4 sonucun negatif çıktığı bir örnek. Gerçektende sonuçlar doğru :) Unutulmaması gereken bir nokta AAA komutunun C bitini etkilediğidir.Fh arasında ise) AL’den 6. AAS (Ascii Adjust after Subtract) komutuda AAA gibi çalışır.

5. 80x86 KOMUT SETĐ (Bölüm 4) Mantıksal (logical) komutlar AND.girilen değerde bir modifikasyon yapmadığımız sürece yanlış hesaplarız. Buna düşük değerlikli 4 bite dokunmadan diğer bitleri sıfırlamakta denilebilir. Bu tür modifikasyonları yapmak için başka mantıksal komutlara ihtiyacımız olacak. 1011 0001 0010 0000 v __________ 0010 0000 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . .devam komutları . Bu komutu assembly programcıları genelde maskeleme işlerinde kullanırlar. . ve 4. AAD ve AAM gibi komutları açıklamak istemiyorum. OR. XOR ve NOT adıyla bilinen ve matematiksel hesaplamalarda çok kullanılan komutlardır. 0010 0000b . 1 1 0 0 ve ve ve ve 1 0 1 0 = = = = 1 0 0 0 sonuçlarını üretir. bu durumda.378h . mov al. 6. dx . Diyelim ki AL’ye IN komutu ile alınan byte 1011 0001 olsun. bitlerini göz ardı etmek için aşağıdaki gibi bir program parçası yazılabilir. devam: . . mov dx. biti kontrol et (maskele) jnz devam . A5h and al. bu adresten bilgiyi al and al. 5. bu yüzden bu komutları anlatmadan DAA. bit 1 ise "devam" a dallan . mesela paralel porttan alınacak olan verinin sadece 5 bitini kontrol etmek için. Bu komutu elektronikçiler çok kullanırlar. DAS. 0Fh bu işlemlerden sonra AL’in yüksek değerli 4 biti (nibble) sıfırlanacaktır yani AL binary olarak ifade edersek 0000 0101 olacaktır. 5. Örneğin 1 byte’lık değerin 7. AND komutu Yapı olarak AND (VE) mantığı 1 ve 0’lar ile ifade edilirse. paralel port adresi in al. .

mem reg. and and and and and and and OR komutu Mantıksal veya işlemini gerçekleştirir.0" dan kat kat hızlı çalışır HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . AND komutunun kullanım formatları. reg reg. imm eax/ax/al.yukarıdaki işlem yapılır ve AND komutu bayrak kaydedicisinin Z bitini 0 olarak kurar. biti 1 olan bir byte seçilmiştir. reg mem. XOR komutu ile şifreleme ve paketleme işlemleri için örnekler şu anda belki de sizin için biraz ağır kaçabilir. çünkü sonuç 0’dan farklıdır. IN ve OUT komutlarının kullanımı sonraki makalelerin konusudur. eXclusiveOR (özel veya) kelimesinin kısaltmasıdır. Kullanım formatları AND komutundaki gibidir.ax . kaynak reg. bunun yerine swap (yer değiştirme) ve kaydedici sıfırlama örneklerini XOR komutunu ile neler yapılabildiğine örnek teşkil edeceğini düşünüyorum. Đşte burada maske olarak sadece 5. ax=0 olur ve "mov ax.hedef := hedef & kaynak doğruluk tablosu yukarıdaki gibidir. XOR komutu XOR olmadan şifreleme işlemleri sanırım çok zor yapılırdı. 1 1 0 0 | | | | 1 0 1 0 = = = = 1 1 1 0 hedef. imm . imm mem. Not: Windows XP altında paralel port’a doğrudan erişim işletim sisteminin kerneli tarafından engellendiğinden bu programı windows XP öncesi işletim sistemlerinde çalıştırabilirsiniz. xor ax. Doğruluk tablosu. 1 1 0 0 ^ ^ ^ ^ 1 0 1 0 = = = = 0 1 1 0 Ben genelde öğrencilerime bu komutun yaptığı işi anlatırken "aynılarda 0 farklılarda 1" sonucunu veren mantıksal ifade derim. Çok fazla kullanım alanı olmakla beraber veri paketleme ve şifreleme işlemleri için hayat kurtarıcı bir komuttur.

Öncelikle Windows’un cmd. not bl .exe yada komut istemi ile açılan pencerenin görüntüsünün aslında B800:0000 adresinin bir yansıması olduğunu hatırlatmak isterim. Overflow bayrağını 0 yaparlar Zero bayrağını şayet sonuç 0 ise 1 yaparlar ve aksi durumlarda bu bayrağı 0 yaparlar En Yüksek değerlikli bit’i Sign bayrağına kopyalarlar Parity bayrağını (sonuçtaki 1’lerin sayısı çift ise) 1 yaparlar Auxiliary carry (Ara Elde) bayrağının durumunu değiştirirler.. bx bx. XOR komutunun kullanım formatları AND ve OR komutlarınınkiyle aynıdır. Şimdi Uygulama Zamanı Bu makalemde sizlere örnek teşkil etmesi için konsol ekranındaki görüntüyü (tüm yazıları) önce karma karışık bir hale getiren daha sonrada tekrar orijinal haline çeviren bir programı anlatmayı düşünüyorum. NOT komutu hiçbir bayrağı etkilemez. NOT komutu NOT komutu operandının mantıksal tersini alır. BL kaydedicisinin değeri 15h olsun. bu 3 komut sonrasında AX = 9876h ve BX = 1234h olur. ax ax. Carry bayrağını 0 yaparlar.AX = 1234h ve BX=9876h olsun xor xor xor ax. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bx .bl = 0001 0101b iken bu komuttan sonra 1110 1010b olur. Kullanım formatları aşağıdaki gibidir. not reg not mem . Debug ile bu alana göz atalım. Bayrakların Durumu Yukarıda anlattığım bu üç komut bayrak kaydedicisini aşağıdaki gibi etkiler.

hem de bizim boş olarak tabir ettiğimiz ama aslında 20h olan yerler bile. Bu text mode özelliği olup siyah zemin üzerine beyaz yazı anlamına gelir. Peki değiştirdiğim her byte’ı tekrar eski haline getirebilir miyim? Bütün bunların cevabı aşağıdaki programda saklı... Debug’ı çalıştırıp b800:0000 adresini ekrana döktüğümüzde bu yazı hala aynı yerindedir. Böyle bir durumda ekranda karman çorman anlaşılmaz bir görüntünün belirmesi olası bir durumdur..00F3h gibi) 07h değerini görüyorsunuz. Hafıza dökümünde tek numaralı her offsette (0001h. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . en üst satırın tamamını ve sonraki satırın yarısından biraz fazlasını gözler önüne seriyor. B800h segmenti de burada görünen yazının bulunduğu text video alanıdır. Konsol penceresi açılınca şayet işletim sisteminiz Windows XP ise "Microsoft Windows XP." ile başlayan bir yazı görülür. Şimdi bu karakterlerin tek tek adreslerine erişip (özellik içeren 07h byte’larını atlayarak) bunları lojik bir işlemden geçirsem ekranın o anki görüntüsü değişir. Gerçektende ekrandaki karakterlerin hepsi beyaz ve zemin siyah değil mi? Konsol ekranının tamamı karakterlerle dolsa..Aslında ekran yansıması da hafızadaki byte’lardan ibarettir. Şekilde B800:0000 adresindeki 4Dh değerinin aslında M harfi olduğunu ve C karakterininde yine aynı segmentte bir değer olduğunu görüyorsunuz. ekranda kaç karakter görürüz? Tabi ki 80x25=2000 adet. Yukarıdaki resimdeki hafıza dökümü.Şekil 1 .0003h.

80x25 text mode da görünen ekrana müdahele.Şekil 2 . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Ekrandaki yazılara ne oldu böyle? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Şekil 4 .Program çalıştırılmadan önceki durum.Şekil 3 .

STOS ) incelemeye çalışacağız.kodsw. “Merhaba” kelimesi bir string’dir.stosd LODS lodsb. word ve double word dizileri üzerinde işlemler gerçekleştirmek için kullanılmaktadır.Şekil 5 . Indis registerleri olarak adlandırılan SI ve DI registerlerinden. bellekteki bir bilgiyi bir adresten başka bir adrese taşırken kullanıyoruz.stosw. ASSEMBLY’de stringleri kontrol edebilen komutlar vardır ve bu komutlar hafıza blokları üzerinde çalışırlar. SCAS.movsw. Bu makalemizde 80 X 86 ailesinde kullanılan string komutlarını (MOVS. Aşağıda ilgili komutlar ve kullanım şekillerini tablo halinde görebilirsiniz.scasw. DI registerine de diziyi taşımak istediğimiz belleğin başlangıç adresini yerleştirerek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bu programda özellikte.scasd STOS stosb.lodsd String komutlarını ile işlem yaparken. text video alanının segment adresini DS kaydedicisine yüklenişini ve bu alanın kaydedici dolaylı (register indirect) adresleme modu ile sanki kendi tanımladığımız bir data alanı gibi kullanılışını incelemenizi tavsiye ederim 80x86 String Komutları (Bölüm 4) Çeşitli bilgilerin birleşerek biraya gelmelerine string denir. burada anlatmaya çalıştığım. Aslında video işlemleri için daha pratik interrupt’lar mevcuttur. Komut Kullanım Şekli MOVS movsb. "şayet assembly dili ile hafızanın her yerine erişebilecek deneyime sahipseniz yapamayacağınız şey yoktur" gerçeğiydi.movsd CMPS cmpsb.cmpsw. SI registerine taşınacak bilgi dizisinin başlangıç adresini. LODS. komutlarımız byte.cmpsd SCAS scasb. CMPS.Klavyeden bir tuşa basıldığında görüntü tekrar normale döner.

yapmak istediğimiz işlemi gerçekleştirebiliriz. Indis registerlerinin program içeirisinde kullanım şeklini gösteren örneğimizi inceleyebilirsiniz. Byte1 db ‘a’ Byte2 db ‘*’ Movs Byte2,Byte1 Lea di,Byte2 koy Lea si,Byte1 koy ;byte1 için ayrılan alana ’a’ değerini koy ;byte2 için ayrılan alana ’*’ değerini koy ;byte2 bilgi dizisini, byte1 bilgi dizisine kopyala ;taşımak istediğimiz belleğin başlangıç adresi di registerine ;taşınacak bilgi dizisinin başlangıç adresini si registerine

Movsb ;si registerinde bulunan byte dizisini di registeri ile gösterilen adrese byte olarak taşı

String işlemlerinde kullanılan komutları daha detaylı incelemeye başlayalım; MOVS Komutu: movs komutunun kullandığı veri tipine göre farklı kullanım şekilleri vardır, data segmentinde ve ofset adresi SI rejisterinde bulunan byte / word / double word dizilerini ES ve DI registerleri ile gösterilen adrese taşır. CX registerinde tutulan deger adedince taşıma işlemi tekrarlanır.movsb ile byte dizileri, movsw ile word dizileri ve movsd ile double word dizileri üzerinde işlemler yapılır. REP: kendisinden sonra gelen string komutunun cx registerinin değeri 0 olana dek tekrarlar.

Komut

Anlamı

Đşlem si’de bulunan byte dizisini, cx registerinde tutulan değer adedince di registerine taşı si’de bulunan word dizisini, cx registerinde tutulan değer adedince di registerine taşı si’de bulunan double word dizisini, cx registerinde tutulan değer adedince di

movsb

byte dizisi taşı

movsw

word dizisi taşı

movsd

double dizisi olarak taşı

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

registerine taşı CMPS Komutu: REPE, REPZ, REPNE ve REPNZ komutlarının parametresi olarak bellekteki iki stringi birbirleriyle karşılaştırma işleminde kullanılır. Stringlerden biri Data Segmentte diğeri ise Extra Segmentte tutulur. Data Segmentindeki stringin ofset adresi SI registerine, Extra segmentteki stringin ofset adresi ise DI registerine yerleştirilir. Cx registerindeki değer adadince karşılaştırma işlemi tekrarlanır. Not:REPE: eşit oduğu zaman tekrarla REPZ: zero flag “0” oldugu zaman tekrarla REPNE: eşit olmadığı zaman tekrarla REPNZ: zero flag “0” olmadıgı zaman tekrarla

Komut

Anlamı

Đşlem data segmentte ve extra segmentte tutulan byte dizisini, cx registeri adedince karşılaştır data segmentte ve extra segmentte tutulan word dizisini, cx registeri adedince karşılaştır data segmentte ve extra segmentte tutulan double word dizisini, cx registeri adedince karşılaştır

cmpsb

byte dizisi karşılaştır

cmpsw

word dizisi karşılaştır

cmpsd

double word dizisi karşılaştır

LODS Komutu: Lods komutu string komutları içinde tektir. Komut öncesinde herhangi bir komut kullanmaya gerek yoktur. Ofset adresi DS:SI rejisterinde bulunan byte / word / double word dizilerini al, ax, eax registerlerine, si registerinin değerini

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

arttırarak veya azaltarak kopyalar.

Komut

Anlamı

Đşlem ofset adresi ds:si registerinde bulunan byte dizisini, si registerinin değerini arttırarak, al registerine taşı ofset adresi ds:si registerinde bulunan word dizisini, si registerinin değerini arttırarak, ax registerine taşı ofset adresi ds:si registerinde bulunan double word dizisini, si registerinin değerini arttırarak, eax registerine taşı

lodsb

byte dizisi kopyala

lodsw

word dizisi kopyala

lodsd

double word dizisi kopyala

SCAS Komutu: Ofset adresi DS:SI rejisterinde bulunan byte / word / double word dizileri içerisindeki değerle al, ax, eax registerlerindeki değerleri karşılaştırarak arama yapmak için kullanılır. Scas komutu AF, Cf, OF, PF, SF ve ZF bayraklarını ayarlarak arama işlemini gerçekleştirir.

Komut

Anlamı

Đşlem

scasb

ofset adresi ds:si registerinde bulunan byte dizisi byte dizisi içerisinde ara içerisindeki değerle, al registerindeki değeri karşılaştırarak arama yap

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN

word yada double word üzerinde işlemler yapmak için uygundur.scasw word dizisi içerisinde ara ofset adresi ds:si registerinde bulunan word dizisi içerisindeki değerle. stosb al içerisinde byte dizisi sakla stosw ax içerisinde word dizisi sakla stosd eax içerisinde double word dizisi sakla HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . eax registerindeki değeri karşılaştırarak arama yap scasd double word dizisi içerisinde ara STOS Komutu: Stos komutu es:di ile gösterilen adreste bulunan akümülator içerisinde belirtilen değeri saklar. istenilen word dizisi saklanır es:di ile gösterilen adresteki eax registerinde. Bu işlemden sonra yön bayrağının durumuna göre işlemci di registerini arttırır veya azaltır. ax registerindeki değeri karşılaştırarak arama yap ofset adresi ds:si registerinde bulunan double word dizisi içerisindeki değerle. Komut Anlamı Đşlem es:di ile gösterilen adresteki al registerinde. istenilen byte dizisi saklanır es:di ile gösterilen adresteki ax registerinde. Stos komutu byte.

girilen değerden buyukse degis’e atla .girilen değerden kucukse sbt’e atla al. kelime içerisindeki küçük harfler büyük harflere dönüştürülecek.’$’.Programın Ekran Görüntüsü. Programın ekran çıktısından da gördüğünüz gibi klavyeden ilk harf grubunun tamamı küçük harf ikinci harf grubunun bir elemanı ise büyük harf olarak girilmiştir. sonuc için ayrılan alan dizi_al: mov ah.data snc db 10.model small .code mov mov mov ax.klavyeden karakter isteniyor .al içindeki değerle a=61h karşılaştır .10.@data ds.13. Dönüştürme işleminde kucuk harf olup olmadığını anlamak için “a = ASCII 61h” oldugu için bu değer ile karşılaştırma yapacağız.istenilen double word dizisi saklanır Şekil 1 .ax .al değerinden 20h çıkar HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Umarım string komutlarının kullanımı konusunda faydalı olur. . Örneğimizde.ax es.stack 64 .girilen al’de . Dönüştürme işleminden sonra programı terk edeceğiz.’ ’. Eğer harf bu değerden buyuk ise küçük harf olduğunu anlayacağız ve harfi buyuğe çevirmek için 20h değerini çıkaracağız.20h .13 .al’deki değeri enter ile karşılaştır .01 int 21h cmp jz inc cmp jg jl degis: sub sbt: al.si ile kelime içinde bir sonraki karaktere ilerle .61h degis sbt . Sonuçta enter tuşuyla harf girişi tamamlanıp sonuç değeri elde edilmiştir. Harf değerimizden küçükse büyük harf olduğuna karar vereceğiz ve çıkarma işlemi yapmayacağız.13 yaz si al.enter’e basılmışsa yaz’a atla .

Stack memory geçici değerlerin saklandığı bir hafıza alanıdır. Bununla beraber stack memory’yi kendi isteklerimiz doğrultusunda da kullanabiliriz.09h dx.4ch int 21h end . SS stack alanının segment adresini tutarken SP bu alandaki offsetleri işaret eder. Bunun için bir çok komut mevcuttur. CALL. bu hafıza alanını yadığımız tüm programlar kullandı.programı terket Aslında string komutları ile yapılan işlemler bilgisayar kullanıcılarına o kadar yakın ki. Öncelikle stack hafıza alanına yüklenen bilgiler LIFO (Last In First Out) yani ilk giren son çıkar yada ilk yüklenen bilgi en son alınır düzenine göre sıralanırlar.dizi başlangıcına atla ah. Yorumlarınızı bekliyorum.snc 21h . Bu makalede stack (yığın) hafıza bölgesini anlatmaya çalışacağım. PUSH.sub mov yukle jmp yaz: mov lea int al.al . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .ekrana snc’de tutulan değer yazılıyor dosa: mov ah. Mikroişlemci SS:SP kaydedicileri ile bu hafıza alanına erişir.0h [snc+si]. POP. mesela msword uygulamalarında kullanılan kopyala-yapıştır gibi. Stack hafıza alanını kullanmama diye bir lüksümüz yok. RET bunlardan bazıları ve bu makalede anlatılacaklar arasındadır. bu makaleye kadar stack memory ile ilgili hiç bir komut yazmasakta.kelime içerisinde sıradaki harfe son al değerini dizi_al .al değerinden 0h çıkar . LIFO Mikroişlemci stack memory’yi diğer hafıza alanlarını adreslerken kullandığı yöntemden biraz daha farklı adresler.

Yine yukarıdaki şekilde orijinal SP yığın boşken SP kaydedicisinin aldığı değerdir. Geçici verilerinizi saklamak için ne kadar alana ihtiyacınız varsa o kadar stack tahsis edebilirsiniz.Stack (Yığın) hafıza. Stack’tan geri alınan veriler içinse "stack’tan çekilen" kelimesi kullanılır. POP ise verileri çekmek için kullanılır. push pop push pop push pop push pop push pusha popa reg16 reg16 reg32 reg32 segreg segreg mem mem imm (**) (**) (CS hariç) (*) (*) (*) HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Yığına veri itildikçe SP’nin değeri azalır. bu değerler yığından çekildikçe SP artar. BU alanın büyüklüğünü kod yazarken . .stack 100h gibi. . 32 bitlik çalışma modunda ise 32 bitlik değerler saklayabilirsiniz.stack 32 diye direktif verdiyseniz SP=0020h ı gösterir. PUSH ve POP komutları Stack memory’de verilerinizi saklamak için kullanılan komutlardır.Şekil 1 . x86 mimarisinde yığın hafızaya 16 bitlik çalışma modunda 16 bitlik değerler. Stack’ta saklanan veriler veya adres bilgileri için genelde "stack’a itilen" kelimeleri kullanılır.stack talimatı ile belirliyoruz. Yukarıdaki şekilde kırmızı bloğu stack memory olarak düşünebilirsiniz. Özetle PUSH komutu stack’a bir veriyi itmek için. Yığın hafıza alanını etkileyen komutların genel kullanım formatları aşağıdaki gibidir. Mesela .stack 32.

Bunun için programı parçalara ayırmak. POPA ve POPAD ise saklanan bu kaydedicileri geri almak için kullanılır. Günümüzdeki programlar onbinlerce hatta milyonlarca komut satırından meydana geliyor. dallanma işlemi gerçekleşmeden önce geçici parametreler stack’ta saklanır. Assembly dilinde CALL ve RET komutlarıda bunu amaçlar. En çok kullanılan komutlar PUSH ve POP komutlarıdır.Sadece 80286 ve sonrası işlemcilerde. CALL ve RET Komutları Bu komutları anlatmadan önce assembly dilinde prosedür (procedure) mantığını kavramanız lazım.pushad popad pushf popf pushfd popfd (**) (**) (**) (**) (*). Yüksek düzeyli programlama dillerinde kullanılan. PUSHF. fonksiyon gibi kavramlar hep bu amaç için türetilmiştir. PUSHA ve PUSHAD tüm kaydedicileri yığında saklamak amacıyla kullanılır. Đster assembly dilinde call komutunu kullanın isterseniz C dilinde bir fonksiyonu çağırın. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Hatta C dilinde ve birçok programlama dilinde fonksiyon çağrımlarının assembly dilindeki tam karşılığı CALL komutudur. (**). sınıf. PUSHFD bayrak kaydedicisini saklamak POPF ve POPFD ise bunları geri almak için kullanılır. modüller hazırlamak şart.Sadece 80386 ve sonrası işlemcilerde. Bir örnekle prosedürleri anlayalım. Peki neden kaydedicilerin içeriğini saklamak durumunda kalalım? Programcıların programlarını düz mantıkla yazmadığını biliyorsunuz. modüler programlama teknikleri kullanılmazsa 30-40 satırdan sonra kaynak kod anlaşılmaz hale gelir.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

şayet yazıyı oluşturan karakterler büyük harfli ise bunları küçük harfe dönüştürür. Programda üç tane prosedür bulunmakta ve ana prosedüre baktığınızda klasik kodlar olan segment ayarlama ve dosa dönüşün dışında sadece CALL komutlarını görüyorsunuz.Şekil 2 . Ana prosedürden 3 kere alt prosedürlere dallanma gerçekleşiyor.. Her dallanma sırasında geri dönüş adresi yığında saklanır. Alt HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Kaynak kodu buradan indirebilirsiniz. Bu program bir önceki makaledeki string komutlarına örnek olmakla beraber biz burada sadeve CALL ve RET komutlarını inceleyeceğiz.Prosedürler kullanılarak yapılmış bir kaynak kod. Program çalıştığında komut isteminden bir yazının girilmesini ister.

data ve stack tır.CPU CS ve IP kaydedicilerini kodlara erişip onları işlemek için.DS. alt prosedürleri istediğiniz kadar çağırabilirsiniz. Daha önce anlatılan AAA ve AAS komutlarında olduğu gibi AAM ve AAD komutlarıda operandsız yazılırlar. çarpım sonucu olan 00 51 değerini ax registerine aktarırken.ax = 00 51h . bu konuyu anlamamış olabilirsiniz diye sizlere birde video hazırladım. 5. Bölümden kalan değeride tekrar al’ye aktarır.al’nin değeri 9 . 2. AAM komutu. mov al. aam komutuda bu değeri 00 81 olarak ASCII formatına dönüştürmüştür. Offset ve segment adreslerinin 2 byte olduğunu düşünecek olursanız bunun stackın yapısınada uygun olduğunu anlarsınız.ax = 08 01h HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Al’nin değerini desimal 10 ile böler.09 mov bl. sağ dijiti ise al’de yer alır.bl’nin değeri 9 .Yapılan işlemin sonucunda. Yığın hafıza yada stackın kullanılmadığı bir program yok gibidir. buradaki gibi aynı segment içindeyse sadece IP yani offset adresi yığında saklanır.Programlar genelde 3 adet hafıza alanından oluşur. SI ve DI’yı değişkenlere datalara erişmek için. çarpma işlemi sonucunda. AAM ve AAD Komutu: AAM komutu. Örnek programımızdaki ana prosedür dışındada CALL komutunu kullanabilirsiniz. 1. Örneğimizde mul komutu. 4. "memory overflow" hatasından önce "stack overflow" hatasını alırsınız. elde edilen sayının sol dijiti ah’da.CPU bu alanlara adresleme yaparak erişir. Yukarıdaki programın örnek alındığı videoyu buradan download edip izlediğinizde sanırım problem çözülecek :) Şunları hatırlamakta fayda var.SS. Şayet dallanma bir başka segmente tapılıyorsa CS ve IP.AAM komutu.prosedürlerden dönerkende ret komutu ile bu adres geri yüklenir. AX registerinde oluşan değeri ASCII formata dönüştürme amaçlı kullanılır. bunlar code. parity. elde edilen değeri ah’a aktarır. Fakat bir prosedür içinden kendini çağırırken dikkatli olmalısınız. SP ve BP’yi yığın hafıza alanına erişmek ve biçimlendirmek için kullanılır. hatta bu bile mümkün olmaz çünkü mevcut CS ve IP saklanmadan geri dönüş söz konusu değildir. sign ve zero flaglarını al’ye aktardığı değere göre uygun şekilde etkiler. Aksi halde geri dönüş yapıldığında alt prosedürün değiştirdiği kaydediciler ile karşılaşılır. Tüm kesmeler (bunlarda bir çeşit alt prosedür gibi düşünüle bilir) çağrılmadan önce. Satırlar yığın hafızayı anlatmakta biraz yetersiz kalıyor olabilir. 3. o anki CS ve IP ayrıca tüm kaydediciler yığında saklanmak zorundadır. AH ve AL registerlerini gizli operand olarak kulanmaktadırlar. çarpma işlemi ile ax registerinde oluşan değerin ardından kullanılır. yazacağınız kodlarla programın sonsuz döngüye girmesini engellemezseniz.09 mul bl aam .

ax = 00 07 I.05 .ax = 00 23 mov bl. adım 03h = 0000 0011b ah 0Ah = 0000 1010b registerinin *_________________ içeriğini 1Eh = 0001 1110b 0Ah ile çarp 0Ah=d’10’ II. Yapılan işlem sonucunda ah registeri sıfırlanır. parity.51h = 0101 I.AAD komutu. AAD komutunu kullanarak. AAD komutu.adım çarpım 1Eh = 0001 1110b sonucundaki 05h = 0000 0101b değere +_________________ al’nin 23h = 0010 0011b değerini ekle ve al’ye yaz III. al registerinde bulunan BCD sayısı. başka bir BCD sayısı ile bölünebilir duruma getirilmiş olur. desimal 5’e bölünmekte ve sonuç yine desimal olarak elde edilmektedir. ax üzerine paketlenmemiş olarak aktarılan sayıyı. bl’ye al değerini koy div bl .adım Sonuç 23h = 0010 0011b _________________ =7 05h = 0000 0101b HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .ax = 03 05 aad . 0305 . kalan’ı al’ye aktar III. sign ve zero flaglarını al’ye aktardığı değere göre uygun şekilde etkiler. bölme işlemi için uygun hale getiriyoruz. AX registerinde oluşan değeri ASCII formata dönüştürme amaçlı kullanılır. Örneğimizde desimal 35 sayısı. mov ax.adım Sonuç ah = 08h al = 01h ax = 0801h AAD komutu ise bölme işleminde bölünenin sonucunda. adım 0001b al registerinin _________________ değerini = 08h 0Ah’a böl 0Ah = 0000 0Ah=d’10’ 1010b II.adım bölümün sonuç değerini ah’a . bölünen değerin yüksek seviyeli kısmını (ah registerinin içeriğini) desimal 10 ile çarpar ve al (düşük seviyeli kısmı) ile toplayarak al içerisine aktarır.

adım al registerinin düşük 0Eh = 0000 1110b seviyeli biti 06h = 0000 0110b 0’dan küçük olduğu için 6 +_________________ değerini 14h = 0001 0100b ekledik ve sonuç değere ulaştık DAS komutu ile yapılan çıkartma işleminin al registeri üzerindeki sonucuna ve auxuiliary ile carry flaglarının durumuna bağlı olarak iki farklı şekilde kullanılır.05 . desimal 13 ’den 5 ’i çıkartma işlemini al registerinde yaptığımız için sonuç 0E oluyor. parity.bl=05h sub al. II.Durum: al registerinin yüksek seviyeli 4 biti 9’dan büyük veya CF set ise. AF set edilir. al registerindeki değerin desimal sayı olması için çıkartma komutunun ardından DAS düzenleyici komutu kullanılıyor. mov al. al registeri ile 60h toplanarak CF set edilir.Durum: al registerinin yüksek seviyeli 4 biti 9’dan büyük veya CF set ise. al registerinden 6 çıkartılarak. DAS komutu. al registerinden 60h çıkartılarak CF set edilir.05 . Örneğimizde 9 ve 5 değerlerini toplayarak komutumuzla istenilen sonucu elde edeceğiz.09 . I.13 . al’nin içeriği olan değere ve AF (auxilary flag) ile CF (carry flag)’nin durumuna bağlı olarak iki farklı şekilde işleme sokulur. sign ve zero flaglarını etkiler. I. ADD komutunun arkasından kullanılan DAA komutu. II. al =14 I. mov al. Durum: al registerinin düşük seviyeli 4 biti 9’dan büyük veya AF set ise. Durum: al registerinin düşük seviyeli 4 biti 9’dan büyük veya AF set ise. AF set edilir.bl . Örneğimizde. carry. adım 09h = 0000 1001b al 05h = 0000 1001b registerlerini +__________________ topla 0Eh = 0000 1110b II. auxiliary. al = 9 add al.al = 0Eh das .DAA ve DAS komutu: DAA komutu ile yapılan toplama işlemi sonucunda her bir byte’da iki adet desimal dijit bulunur. al = 0E daa . al registeri 6 ile toplanarak.al = 08 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .al=13h mov bl.

Đşaretsiz sayılarla temsil edilen operandlar. Fakat işaretli sayılarla temsil edilen operandlarda değişim o kadar rahat olmamaktadır.01 I. CWD komutu da ax içindeki sayının işaret bitinin değerini dx’in tüm bitlerine aktararak sonuca ulaşmamızı sağlar. carry. hangi durumda test komutunu kullanmalıyız sorusu aklımıza gelecektir.I. CBW komutu. CWD:Word’un double worde çevrilmesi Aritmetik işlemler sırasında operandlar farklı uzunluklara (byte. and al. rahat bir şekilde düzenlenir. işlem öncesinde operandların uzunluklarının düzenlenmesi gerekir. Durum HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Küçük uzunluğa sahip operandın uzunluğunu. TEST Komutu: Test komutunun çalışma prensibi ve flagları etkileme biçimide dahil olmak üzere And ile aynıdır.adım al registerinin 0Eh = 0000 1110b düşük seviyeli biti 06h = 0000 0110b 0’dan küçük olduğu için 6 __________________ 08h = 0000 1000b değerini çıkardık ve sonuç değere ulaştık CBW ve CWD Komutu: CBW:Byte’ın worde çevrilmesi. Đşaretli sayıları içeren operandların uzunluklarının düzenlenmesi için CBW ve CWD komutları geliştirilmiştir. hangi durumda and. owerflow bayrakları test işleminin sonrasında reset edilirler. auxiliary dışındaki diğer bayraklarda işlem sonucuna uygun şekilde etkileneceklerdir. CBW komutu al ve ah. Bu gibi durumlarda. komut ile birlikte kullanılan operandların değerlerini değiştirmez. Farkı olmamasına rağmen. Örneğimizi inceleyelim. Diğer lojik komutlarında olduğu gibi. CWD komutu ise ax ve dx’i gizli operand olarak kullanırlar. al içerisindeki işaretli sayının işaret bitini ah’ın tüm bitlerine.word veya double word) sahip olabilirler. büyük uzunluğa sahip operandın uzunluğuna denkleştirilmektedir. adım 13h = 0001 0011b al 05h = 0000 1001b registerindeki değerden bl __________________ registerindeki 0Eh = 0000 1110b değeri çıkart II. Farklı olarak.

01 jz * . al registerinin değeri desimal 1 ile karşılaştırılmaktadır. Durumda. Bu işlem SHR ile verilen ikinci operandın değeri kadar tekrarlanır.30h shr al.. karşılaştırma sonrası adımlarda da gerekli ise test komutunu tercih etmeliyiz. Örneğimizde. . soldaki operandın en düşük seviyeli biti carry bayrağına kopyalanır ve operandın tüm bitleri sağa doğru 1’er bit kayar.al=18h .Sonuçtan da anlaşıldığı gibi.al=0Ch Şekil 1 . Fakat al’nin değeri 1’e eşit değil ve başka işlemler için bize gerekli ise sorun çıkacaktır. test al. mov al.jz * .Durumda: al’nin değeri korunacak ve zero bayrağının reset durumuna gelmesine sebeb olacak. al registerindeki değer desimal 1’e eşit ise I..01 shr al... bu sayede jz’yi izleyen komut ile program devam etmiş olacaktır.. En soldaki bitin değeri 0 yapılır. al registerinin karşılaştırma öncesi değeri. en düşük seviyeli biti 00110000 48 00011000 24 0 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .01 .adım: değerleri 1 bit sağa al=18h kaydır. sonucunda ise * yerine kullanılan adrese dallanılacak ve program bu adreste bulunan komut ile sürecektir.. adım: al’ye 30h al=30h değerini koy II.al=30h . 30h değerini iki kere 1’er biti sağa kaydırarak sonucun nasıl değiştiğini inceleyeceğiz.Durum I. II.. . Fakat değer 1’den farklı ise sonuç 0 olarak al’ye yerleştirilecek ve zero bayrağı set edilecektir.Shr komutu ile bitlerin sağa kaydırılması Adımlar Hexadesimal Binary Desimal CF - I. ve II.. SHR ve SHL Komutu: SHR Komutu ile.

mov al.adım: değerleri 1 bit sola kaydır.0Ch shr al.01 . Bu işlem SHL ile verilen ikinci operandın değeri kadar tekrarlanır.al=30h Şekil 2 . SHL Komutu ile. soldaki operandın en yüksek seviyeli biti carry bayrağına kopyalanır ve operandın tüm bitleri sola doğru 1’er bit kayar. 1 ise tek sayıdır. En soldaki bitin değeri 0 yapılır.adım: değerleri 1 bit sağa kaydır. adım: al’ye 0Ch al=0Ch değerini koy II.Shl komutu ile bitlerin sola kaydırılması Adımlar Hexadesimal Binary Desimal CF - I.adım: değerleri al=0Ch 1 bit 00001100 12 00011000 24 0 00110000 48 0 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Her bir shr işlemi sonrasında carry bayrağı 0 ise çift sayı. Örneğimizde 0Ch değerini iki kere 1’er bit sola kaydırarak sonuç üzerindeki değişiklikleri inceleyeceğiz. al=18h en yüksek seviyeli biti CF’na taşı III.al=18h .01 shr al.al=0Ch .CF’na taşı III. al=0Ch en düşük seviyeli biti CF’na taşı 00001100 12 0 Programda da görüldüğü gibi her bir sağa kaydırma işlemi ile sayıyı ikiye bölmektedir.

10.shr ve rcl komutlarını kullanarak örnek bir program hazırladım.stack 64 .Rcl komutu ile bitlerin sola kaydırılması Şekil 5 .Rcr komutu ile bitlerin sağa kaydırılması RCL Komutu. Đşlem ikinci operand değeri kadar tekrarlanır. carry bayrağının değeride yüksek seviyeli bit pozisyonuna aktarılır.13 dassonuc db ’00$’ HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Programın ekran görüntüsü Bu bölümde anlattığımız aam. Düşük seviyeli bit pozisyonundaki değer carry bayrağına. Đşlem ikinci operand değeri kadar tekrarlanır. RCR ve RCL Komutu: RCR Komutu.model small . .das. yüksek seviyeli bit pozisyonundaki değer ise carry flağına aktarılır.data aamsonuc db ’00$’.sola kaydır. aam komutu kullanılan prosedürde shr komutunu işleme katmak istediğimiz al registerinin içeriğini bir bit sağa kaydırmak için. en yüksek seviyeli biti CF’na taşı Programda da görüldüğü gibi her bir sola kaydırma işlemi ile sayıyı iki ile çarpmış oluyoruz. işleme tabi tutulan bitlerin herbirini bir pozisyon sağa kaydırır. Şekil 3 . Carry flağının değeri düşük seviyeli bit pozisyonuna. işleme tabi tutulan bitlerin herbirini bir pozisyon sola kaydırır. das ile ilgili prosedürde ise rcl komutuyla al registerinin içeriğini bir bit sola kaydırdım. Şekil 4 .

........28h rcr al..... aamornek proc mov al. .....sonucu yaz .01 al=14h mov bl..........al=9h ......@data mov ds.....02h mov dl.....al yerleştir...code mov ax........ax registerini sonuc dizisi içerisine ... .....9h mul bl aam add ax. .alt satıra geç ....al değerini ascii karaktere çevir.....knm db 10...............ax=81h ...........’$’ .01 al=9h mov bl.........05h sub al..ax mov es..al int 21h ..aamsonuc int 21h mov ah.al ve ah değerlerini ascii karakterlere çevir....ax call aamornek call dasornek .......... HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .........ax=51h .....bl=9h .al registerinin içeriğini bir bit sola kaydır.ah mov byte ptr [aamsonuc+1].........bl=5h .......13..........3030h mov byte ptr [aamsonuc]...sonucu yaz dasornek endp ...al registerinin içeriğini bir bit sağa kaydır.......09h lea dx.. .............09h lea dx.................... mov ah..........knm int 21h aamornek endp .... dasornek proc mov al.. ..12h shr al..al=Fh ..30h mov ah......bl das add al....

... Bu bölümde ise... bayraklar üzerindeki etkilerini anlatmaya çalıştım.. _____________________________________________________________________________________ _______________________ HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN ....4ch int 21h .. gerçekleştireceğiniz uygulamalar ve elde etmek istediğiniz performans doğrultusunda ihtiyacınıza en uygun olanı belirleyebilirsiniz.... Programımız. Daha önce anlatılan makalelerde DOS’ta DEBUG ve TASM’ı kullandık. Makalemizde aritmetik lojik komutların çalışma şekillerini...... Bu sayede temelden bize ait olan çalışma mantığını bildiğimiz istediğimiz özelliklere sahip fonksiyonlar geliştirme fırsatımız oluruz. anlatacağımız kodları pascal ve c++ builder içerisinde kullanacağız.programdan çıkış end ..0 içerisindeki asm{... Benzer özelliklere sahip komutların kullanılması sizlerin tercihine kalmış.. Ben kodu çalıştırdım ve gördüm ki kullandığım komutlar işini başarıyla gerçekleştiriyor. _____________________________________________________________________________________ _______________________ şekil 1: Pascal içerisindeki assembly bölümü _____________________________________________________________________________________ _______________________ C++ Builder 6........... Sadece assembly komutlarını kullanarak programlar geliştirmek kodlar için kullanılan satır sayısı arttıktan sonra zor olmaya başladığından farklı programlama dilleri içerisinde assembly kodlarını alt programlar olarak yazmak daha avantajlı bir yol olur.} blokları arasında tasm’da olduğu şekliyle kodlarımızı yerleştirebiliyoruz..... Şekil 1’de Turbo Pascal içerisindeki ASM.... Assembly kodlarımızı farklı programlama dilleri içerisinde de kullanabiliriz... blokları arasında.... Turbo Pascal 7...END..0 içerisinde assembly kodlarının yerleştirildiği bloğun yapısı.... anlatılan komutların sağlaması olarak da değerlendirilebilir. Şekil 2’de C++ Builder 6..mov ah...0 içerisinde assembly kodlarının yerleştirildiği bloğun yapısı.....

0’da ASM.. ve C++ Builder 6..END.0 Ekran Görüntüsü C++ Builder içerisinde kullanacağımız assembly bloğu dışındaki component ve fonksiyonları inceleyelim.} blokları arasında.. komut satırından girilen değerler MOV komutu ile AL registerine aktarıldıktan sonra ADD komutuyla toplama işlemini gerçekleştirip TOPLAM değişkenine AL registerinin son değeri olarak aktarıyoruz.0’da ASM{. C ++ Builder Componentleri : Etiket (TLABEL): Form içerisinde bulunan Metin Kutusu’na ne tür değer girileceğini belirtmek için kullanılmaktadır.0 ile assembly kod örneği şekil 4: Turbo Pascal 7. şekil 3: Turbo Pascal 7.şekil 2: C ++ Builder içersindeki assembly bölümü _____________________________________________________________________________________ _______________________ Şekil 1 ve 2’deki assembly blokları içerisinde. iki sayının toplanması işleminin nasıl gerçekleştiğine bakalım: Turbo Pascal 7. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . assembly bloğu dışında programlama dilinin fonksiyonları ile sonucu görüntülüyoruz.. Metin Kutusu (TEdit): Kullanıcının bilgi girişi yapması ya da elde edilen sonucun görüntülenmesi için kullanılır.

Sayı olarak girilmiş IntToStr(Edit1değeri >Text).Komut Düğmesi (TButton): Kullanıcın programda. gerçekleştireceği uygulamayı başlatan yada bitiren kontroldür. IntToStr HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . metine dönüştürür. sayıya dönüştürür. Assembly Bloğu dışında kullandığımız C ++ Builder Fonksiyonları: Fonksiyon Anlamı Kullanım Şekli StrToInt Metin olarak girilen StrToInt(Edit1değeri >Text).

assembly’nin diğer diller içerisinde nasıl kullanılacağını en basit haliyle anlatabilmek için kısa kodlar kullandım.şekil 5: C ++ Builder ile assembly kod örneği şekil 6: C ++ Builder 6.0 ile gerçekleştirdiğimiz örnek kodu buradan .0 ile gerçekleştirdiğimiz örnek kodu buradan indirebilirsiniz. daha gelişmiş kodları HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Turbo Pascal 7. Makalemizde .0 Ekran Görüntüsü C++ Builder 6.

Ve bu bitlerin her birinin bir adı vardır. BSR aritmetik lojik komutlarını açıklamaya devam edeceğiz... önemli olan hedefe ulaşmayı istemek. Tüm karar alma mekanizmaları bu kaydedicide gösterilen sonuçlar baz alınarak yapılır.Herkese iyi çalışmalar. SAL.8086’da işlemci durum kaydedicisi. BTS. ROL. CMPXCHG8B. 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. Uzak mesafeler katedebilmek için küçük adımlar atmak gerekiyor. sonuç sıfırsa girilen değerler eşittir aksi taktirde eşit değildir. SHLD. Mikroişlemci içinde yapılan işlemlerin durumlarını programcıya bildiren bir kaydedici mevcuttur. BSF. Cevabı basit bu değerlerin farkını alarak. BTC. BT. Aslında HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Örneğin C biti Carry yani taşıma biti veya Z biti Zero yani sıfır biti’dir. Turbo debugger ile işlemci durum kaydedicisinin içeriğini gözlemleyebilirsiniz. CMPXCHG. negatif. Şekil 1 . SHRD. BTR. 80X86 komut sistemine ait. Peki mikroişlemci bu değerlerin eşit olup olmadığını nasıl gösterecek bize. Adımlar küçük yol uzun. Makalemizde. Terminolojide genellikle bu bitler "flag" yani bayrak olarak adlandırılır.gerçekleştirebilmeniz için sizlere başlangıç olması açısından önemli. SAR. Đyi ama assembly programcısı bu sonuç sıfır değerini nereden okuyacak? Bir işlemin sonucunun sıfır. Diğer kaydedicilerin aksine işlemci durum kaydedicisi programcı için bitsel olarak anlamlıdır. Şekilde kırmızı çerçeve içine alınmış kısım işlemci durum kaydedicisini bitsel olarak gösteriyor. Bunu üst seviye programlama dillerinde basit bir şekilde if-else mantığıyla yapabilirsiniz. ĐŞ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. ROR.

daha doğrusu işlemciler geliştikçe ek bayraklar eklenmiştir. 3 . FFFE = 65534 işaretsiz sayıyı temsil ederse ADD AX. 8086. Örneğin carry (taşıma) bayrağı 1 olduğunda bazen işlemin elde ürettiğini bazen de borç alındığını ifade edebilir. mesela 80286’dan itibaren işletim sistemlerinin yazımı için gerekli olan ayrıcalıklı mod bayrağı eklenmiştir.x86 işlemci durum (bayrak) kaydedicisi. 80286. Bayrak kaydedicisindeki her bir bitin 1 olma durumuna SET. Şekil 2 . Hani bir fonksiyonun çözümü için sorularda "her x gerçel sayısı için" gibi ifadeler geçer ya. Örneğin Z için Zero Flag yani sıfır bayrağı denir. Bu örneği biraz daha açıklayacağım fakat daha önce matematik dersinde gördüğümüz bazı olayları hatırlatmak istiyorum. 0 olma durumuna da RESET denir. 80386. Örneğin. O = 0 olur ve bu bir boyut taşmasını gösterir. 0FFFEh . Çünkü 1 ve 0’ları ancak bu HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . C = 1. işte bu tür kabullenmeler assembly dilinde çok önemlidir. aşağıdaki şekilde ise 8086’dan 80486’ya kadar olan işlemcilerin sahip olduğu bayrakları görebilirsiniz. MOV AX. Đşlemcinin ürettiği sonuçlar hakkında programcıyı uyaran bayrak kaydedicisindeki durumlar görecelidir. 80486 ve Pentium işlemcilerin bayrak kaydedicileri biraz farklıdır. Bazen de iki bayrağın durumu birlikte değerlendirilerek bazı sonuçlara varılır.assembly programcıları işlemci durum kaydedicisi yerine bayrak kaydedicisi terimini daha çok kullanırlar. Yukarıdaki şekilde 8086’nın 8 bitlik bayrak kaydedicisini görmektesiniz.

386 ve sonrası işlemcilerde ise bayrak kaydedicisi 32 bitliktir ve bu 32 bit’in her biri bir bayrağı temsil etmez. Tabi ki 65534 + 3. Bu örnekte de FFFE=65534 değerini gösterirse diye başlıyoruz işe. Bu işlemin sonucu AX kaydedicisinde 0001 olarak görülür.şekilde yorumlayabilirsiniz. bu durumu programcı iki bayrağa birden bakarak anlayabilir. Đşlemci yine aynı sonucu üretecek fakat bu sefer programcı bunu -2+3 olarak değerlendireceğinden sonuç doğal olarak 1 ve AX’te 0001 değeri doğru sonuç olacaktı. Burada sonuç anlamlı aralık olan 0. Đşlemin doğru sonucu olan 65537 değeri 2 byte’lık AX kaydedicisinin içine sığmadığından bu sonuç üretilmiştir. Overflow Flag (OF) (Taşma Bayrağı): Đşaret taşması olduğunda olduğunda set (1) olur. Yine C=1 ve O=0 olsa da programcı için bu durum bir taşmayı göstermeyecektir. mesela 1 byte’lık işaretli sayılarda 100+50=150’dir. Đşte assembly programlama dili matematiğin bu basit gibi görünen temellerine bağlıdır.bilgisayarlar aslında 1’ler ve 0’lar dünyasıdır. Hani matrix filminde herkes kodlara bakıyor ama sadece Neo olayı idrak edebiliyordu ya.. işte o misal :) Şekil 3 . Hesap makinelerinin belli bir değere kadar işlem yapabildiğini hatırlayın. Ama burada işaretli değil sadece pozitif tamsayılarla işlem yapıldığı varsayılıyor. 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. bazen bir mp3 bazen de bir kelime oluveririler. fakat sonuç - HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .65535 arasında olduğundan O=0 olmuştur. yani baştan evrensel kümenizi kafanızda tanımlamanız gerekir. nitekim FFFE işaretli sayı olarak kabul edilseydi -2 değerini gösterecekti. aralarda hiçbir şeyi ifade etmeyen boş bit’ler 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. Bu durumda programcı kullanıcı ekranına "sonuç çok büyük" gibi bir mesaj gönderebilir. Özetle sonuç anlamlı aralıkta yanlış bir değerdir. 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 örnek için en başta FFFE işaretli bir saydır deseydik herhangi bir taşma söz konusu olmayacaktı. Bazen bu 1 ve 0’lar bir resim.. Đş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. işleminin sonucu 1’e eşit değildir. Hafızadaki 1 ve 0’ları nasıl yorumlarsanız öyle şekil alırlar. Fakat programcı doğal olarak AX kaydedicisini içindeki değeri yani 0001’i sonuç olarak alacaktır. Bu toplama işlemi sürecinde sayı FFFF’den 0000’a dönerken C=1 olur. 8086 için bayrak kaydedicisi 16 bitliktir ve bu 16 bit’te sadece 9 adet bayrak mevcuttur.

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.Đşlemcinin yaptığı işlemlerin özel durumlarını gösterirler 2. Bayrakların geri kalan kısımları ve bayrakları etkilen komutları sonraki makalelerimizde yeri geldikçe açıklamaya çalışacağım. Đ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 port’un 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.. Auxiliary carry Flag (AF) (Ara Elde Bayrağı): AL kaydedicisinin 0-3 arasındaki bitlerinde yapılan işlemde elde veya borç üretilirse 1 olur.128. Carry Flag (CF) (Taşıma Bayrağı): 1 olduğunda elde üretildiğini veya borç alındığını belirtir. Đ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. Sign Flag (SF) (Đşaret Bayrağı): MSB biti (en soldaki bit) 1 olduğunda bu bayrakta 1 olur. 1. SF. Bayrak Kaydedicisini özetleyecek olursak. (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. Direction Flag (DF) (Yön bayrağı): String işlemlerini yapan komutlar için kullanılır. ZF. Bu örnekte henüz işlemediğimiz konulardan olan "ekran ve klavye işlemleri" ve HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 1 olduğunda bir anda sadece 1 komut işlenir. 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) 1’lerin sayısının çift olduğunu gösterir.Bazı işlemler yapılmadan önce bazı bayrakların 1 yada 0 yapılması gerekebilir 3. Uzun bir süre bu bayraklardan OF. Zero Flag (ZF) (Sıfır Bayrağı): Sonuç sıfır olduğunda 1 olur. CF olanları bizim için önemli olacak. 1 olduğunda index kaydedicisi otomatik olarak azalır..127 aralığında değildir.Programcılar bazı işlemleri anlayabilmeleri için bazen birden fazla bayrağın birlikte ürettikleri durumları göz önüne almak zorundadırlar. Ş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.

Bu komutlar aşağıdaki gibidir.01 INT 21h JMP HedefAdres JE HedefAdres CMP BL. Bunların ayrıntılarını daha sonra anlatacağımdan şimdilik fazla önemsemeyin. Bu komut ile hedef adrese Z bayrağı 1 ise dallanma gerçekleştirilir. Bu komut ile hedef adrese dallanma gerçekleştirilir. AL HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 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."şartlı dallanmalar" konularını kapsayan komutlar kullanacağız. MOV AH. Bu komut BL ile AL kaydedicisini karşılaştırır.

Klavyeden girilen değerleri test eden program.Şekil 4 . Yukarıdaki programın kaynak kodlarını buradan download edin ve TASM ile HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

bu durumda Z=1 olur.derleyin. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . operandında belirtilen adrese dallanma işlemini geçekleştirir. Şekil 5 . Bu programı çalıştırdığınızda sizden iki adet değer girmenizi isteyecek. JE komutu ise ancak Z=1 olduğunda. Ş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. Şayet girilen değerler eşitse ekranda "Girilen Degerler Esittir" değilse "Girilen Degerler Esit Degildir" mesajını göreceksiniz. Aksi durumda işlemci klasik yolunu izler ve bir sonraki komutu işler.Programın ekran çıktısı. Değerlerin eşit olup olmama durumunu belirleyen işlemci durum kaydedicisinin Z biti (Z bayrağı) dir. değerleri girerken enter tuşuna basmanıza gerek yok. Bu bayrağın durumu karşılaştırma komutundan sonra girilen değerlere göre 1 yada 0 olur.

Şekil 6 . Klavyeden farklı değerler girildiğinde ise. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Z=1 olduğunda 0024h offset adresine dallanılacak. Bu durumda dallanma gerçekleşmez ve işlemci normal seyrini sürdürerek bir sonraki komutu işler. karşılaştırma işleminin sonucunda z=0 olur.

her komut bayrakları etkilemez. Bayrakların durumları bayrakları etkileyen bir komut işlendiğinde değişir. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Burada CMP komutu 6 adet bayrağı etkiliyor. Hangi komutun hangi bayrakları etkilediğine Intel’in komut setinden bakabilirsiniz.Şekil 7 .Z=0 olduğunda dallanma gerçekleşmeyecek. Komut setinden CMP komutunu bulursanız bu 6 bayrağın neler olduğunu görebilirsiniz. program sonraki komutu takip edecektir.

BL-AL yani 33h-34h işlemini yapan CMP komutu aşağıdaki nedenlerden dolayı bu bayrakları etkilemiştir.Binary olarak çıkartma işleminde daha 2. SF. Burada yapılan işlem "CMP BL. 2. CF. 1. çalıştırdığınız komutun etkilediği bayrak varsa bunun nedenini araştırın.Đşlem sonucunda bir işaret taşması olmadığından OF=0.Bu işlemin sonucu sıfır olmadığından ZF=0. başka bir deyişle 11111111b değerindeki 1’lerin sayısı sekiz adet yani çift olduğundan PF=1. OF. Gördüğünüz gibi program akış kontrolünde bayraklar hayati önem taşır. Aslında burada JE komutu ile ilerleyen makalelerde ele alacağımız if-else mantığını oluşturduk.Sonuçta elde edilen -1 yani FFh. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 6. 3. Đşlemci durum kaydedicisinde bulunan bu bayraklar şu anda aklınızın alamayacağı bir çok işlemde bizlere yardımcı olacak.CMP ile AF. ZF bayrakları etkilenir. bitte 0’dan 1 çıkarılırken 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. PF. borç alındığından AF=1 olmuştur. 4. AL=34’dür. 5. Đsterseniz Şekil7 deki etkilenen tüm bayrakları ve neden dolayı 1 yada 0 olduklarını inceleyelim.Şekil 8 . Bu konuyu daha iyi anlamak için Turbo Debugger’da programın her komutunu adım-adım çalıştırın ve komut setinden faydalanarak. AL" dir ve BL=33.33-34 işlemi için borç gerektiğinden (Küçük sayı büyük sayıdan çıkartılıyor) CF=1.Đşlemin sonucu negatif olduğundan SF=1.

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

You're Reading a Free Preview

İndirme
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->