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

6. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . adımdaki gibi olunca g tuşuna basıp ardından son olarak enter tuşuna tekrar basın.5. 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. 09 yazıp boşluk tuşuna basın.Klavyeden Enter tuşuna basın ve ekran görüntüsü 3. Đşlem bitince ekran görüntüsü aşağıdaki gibi olacaktır.b4 yazıp boşluk tuşuna (space bar) basın. adımdan itibaren yeniden başlayın.

işte : simgesi ile ikiye ayrılmış bu 8 rakam hafızanın adresidir. hafıza ve CPU’nun içindekileri görmemizi. Zamanla binary gösterim biraz fazla yer kapladığından hexadecimal gösterim benimsenmiştir. 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. E komutu ile hafızaya giriş yaptığımızı söyledik. Kodlar hafızaya yazılır. tesadüfen hepsi 00’dı. bunu evinizin adresine benzetebilirsiniz. "Ey CPU yazdığım bu kodları sırasıyla çalıştır bakayım". e komutu hafızaya kod girişi yapmamızı sağlar ve g komutu ise CPU’ya şu sihirli kelimeyi söylememizi sağlar. Daha sonra hexadecimal gösterimin anlaşılması zor olduğundan sembolik kodlar ile yazılan Assembly programlama dili geliştirilmiştir. Adresler her zaman bizim onları doldurmamız veya erişmemiz için hali hazırda beklerler. komut isteminin en solunda 152F:0100 gibi bazı rakamlar gördünüz. 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. En fazla 2 makale sonra Debug programını kullanmayı bırakıp daha jan-jan lı debuger programları kullanacağız. Debug programı Microsoft’un tüm işletim sistemlerinde bulunan. Bunu yaparken kod yazacağımız adreste hali hazırda hangi kod’un olduğunu görme gibi bir lükse de sahiptik. şimdilik böyle idare edelim.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. Makine kodları CPU’nun anlayacağı yegane kodlardır ve 2’lik (binary) yada 16’lık (hexadecimal) gösterimle ifade edilirler. ama 0100 aynıdır. Biraz önce Debug programının kendisi içinde kullanacağımız e (enter) ve g (go) komutlarını kullandık. 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. düzenlememizi sağlayan bir programdır. Hala hevesiniz kırılmadıysa :) neler yaptığımızı tek-tek açıklayalım. buradaki 152F sizin bilgisayarınızda farklı olabilir. Ç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. Đnsan oğlu rahatına pek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Daha sonra debug’ın N komutu ile dosyaya isim vereceğiz ve son olarak W komutu ile harddiskimize kayıt yapacağız. Bizde burada öyle yaptık zaten.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 yüzden ayrıntıya girmiyorum. adımdaki şekilden faydalanınız. daha çok donanımla alakalıdır.icra et sürecini başlatır. Programı mikroişlemci (CPU) çalıştırır ve programcı tarafından kısmen kullanılabilir. Kodları kendi elimizle teker teker girdiğimizden uzunluğunun 28 byte olduğunu biliyoruz. kaydedicide ne demek kardeşim dediğinizi duyar gibiyim merak etmeyin bu terimler ileride hiç ağzınızdan düşmeyecek) 28’in hex. (Yalnız komut istemi penceresini kapattıysanız işiniz yaş 1. 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. (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. Emin olmak için 5. Đşte biz buna halk dilinde program çalışıyor diyoruz.kodunu çöz .düşkün olduğundan :) daha sonra. Lütfen aşağıdaki şekli inceleyiniz. X86 PC’lerin hafızası byte adreslenebilir diye bir programcı ata sözü vardır. Son olarak debug’tan çıkıp komut istemine geri döneceğiz ve oluşturduğumuz programı çalıştıracağız. Bu söz her adrese en fazla 1 byte’lık kod yazabileceğinizi anlatır. Debug’ın g komutu ise meşhur fetch-decode-execute sürecini yani hafızadan al getir . karşılığı olan 1C’yi yazacağız. 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. kod yazması ve anlaşılması daha kolay olan B Programlama dilini geliştirmiş bu da yetmemiş C dilini geliştirmiştir.

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. sabretmek lazım :) Bu programı bir sonraki makalemize kadar silmeyin. 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ı. Siz bu arada HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Programımızı bir dosya haline getirdik. 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.com adlı dosyamız oluşturuldu ve çalıştırılmaya hazır. çünkü bir sonraki makalemizde bu dosyadan faydalanıp sembolik kodlardan oluşan assembly diline geçiş yapacağız ve eksik kalan noktaları tamamlayacağız. Bir burada COM olanından oluşturduk.

Makine kodlarını görmeden önce sizlere küçük bir tavsiye vermek istiyorum.Debug ile program yükleme Ekranın solunda bir . Şimdi bu dosya ile biraz daha yakından ilgilenelim. Assembly programlama dilinde ayrıntılar çok önemlidir ve her bir ayrıntı kendi çapında bir araştırma konusu olabilir. Şekil 1 . Ş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. program simgesinin üzerine gelip mouse ile tık-tık yapıldığı andan itibaren. 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. Bir sonraki makaleye kadar esen kalın ve kendinize iyi davranın.işareti göreceksiniz ve başka hiçbir şey olmamış görünecek ama aslında merhaba. örneğin burada yaptığınız program yükleme işlemini windows kullanıcıları. 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 . 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. Geçen makalemizde debug programını tanımış ve makine kodları ile küçük bir program hazırlamıştık. Bunun için ASCII kod tablosundan faydalanabilirsiniz.com adlı program dosyasını oluşturan makine kodlarını çoktan hafızaya yüklediniz bile. Yine komut istemine geçiş yapıp debug programını şekildeki gibi çalıştıralım. 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. 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. Sonra bu programı yine debug ile bir dosya haline getirmiştik.boş durmayıp bu kodlar üzerinde oynamalar yapabilirsiniz özellikle 12.

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. Neyse biz konumuza geri dönelim. Hemen kodları görelim o zaman. Şekil 2 . Tabi ki ekrana yazdırılacak olan MERHABA ASSEMBLY burada data sınıfına giriyor peki komutlar nerede? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .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. Neden 0100h adresinden itibaren hafızaya yerleşti? sorusunun yanıtı program dosyasının . Bizde burada kodları ekranda gösterdik. program şu anda hafızada ve 0100h offset adresinden itibaren yüklenmiş durumda.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 assembly dili bizlere daha yakın bir dildir.Şekil 3 .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... 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. 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 . Assembly dilindeki bu gösterim aynı zamanda sembolik kodlar olarak ta bilinir. Şekil 4 .

yani biz burada 0100h-010Ah offset adresleri arasınındaki makine kodlarını assembly dilinde görmüş olduk. Bu tür konuları öğrencilik yıllarımdayken HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Biz şimdilik hep 1 byte’lık opcodelar ile çalışacağız. 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. bunlar kitaplarda little endian byte ordering ve big endian byte ordering olarak geçer. BA0B01 MOV DX. Tabi ki birde düz olarak byte’ları yerleştirme olayı var. Intel’in opcode uzunluğu 1 yada 2 byte’lıktır. Şimdi yukarıdaki şekilde gördüğümüz makine ve assembly kodlarını karşılaştıralım. 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.4 veya 8 byte’lık olabilir.010B Burda 3 byte’lık bir komut satırı. Operandlar ise herzaman opcode’lardan sonra gelir ve X86 mimarisinde 1. bu yüzdende Intel’in x86 ailesi CISC (Complex Instruction Set Computers) olarak anılırlar. u dan sonra gelen 0100 010A ise hafıza aralığıdır. B409 MOV AH.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. Đkinci sorunun cevabı ise x86 ailesindeki işlemcilerin hafızaya erişme şekillerinin ters sıralı olmasından kaynaklanır.2. Burada sadece opcode ile operandı ayırmanız yeterlidir assembly dilindeki ifadeleri ne anlama geldiğini şimdilik önemsemeyin. Ama şimdi kafamızda 2 tane soru işareti var. B4= MOV AH’ın BA=MOV DX’in opcode karşılığıdır. Đlk olarak B4 veya BA MOV’un karşılığı gibi görünse de öyle değildir. Yani ikisi de farklı assembly ifadeleridir ve farklı opcode’larının olması son derece normaldir. 2 byte’lık olan opcode’ları 0F ile başlar. 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.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. Bunlar opcode ve operand alanlarıdır.assembly dilinde görmek için debug’ın "u" (unassembly) komutunu kullandık. opcode 1 byte’lık operand 2 byte’lık. Böylece ortaya karma karışık bir komut seti çıkar.09 Assembly dilindeki MOV AH.

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

fakat sonuçta assembler’ın yapacağı iş aynıdır. Biz bunları ilerleyen makalelerimizde. çünkü 1 ile toplandığında 1 byte’lık alanda 0000 00002 değeri elde edilir ve elde biti oluşur.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. mantıksal ve veri taşıma işlemleri yapar. 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. ancak o zaman anlam kazanırlar. çünkü 1111 11112 = 20+21+22+23+24+25+26+27 = 255 -1’dir. Şekil 1 . 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. Bunu tam tersi de olabilir.Đşte bu 1 ve 0’ları program içinde yorumlamak önemlidir. 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. 255’tir. işlemci durum kaydedicisini anlatırken işaret ve boyut taşması olarak inceleyeceğiz. Şimdilik siz matematiksel hesaplamalar yaparken alanlarını kısıtlı olduğunu göz ardı etmeyin. Örneğin 1111 1111 değeri onluk düzende 255’mi yoksa -1’mi. Bu bağlamda bizim için alt seviyede önemli olan 1 ve 0’lardır. Daha önce işlemci durum kaydedicisinin bitsel olarak önemli olduğundan bahsetmiştim. DB Đngilizce’de Define Byte yani byte tanımla anlamına gelir. MASM ile DB direktifi yerine byte yada sbyte direktiflerini de kullanabilirsiniz. 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.MASM için alternatif direktif HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Bu direktif ile hafızada 1 byte’lık bir alan tahsis eder ve bu alana adresi ile erişebilirsiniz. i j k db byte sbyte 0 255 -1 . 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. Yani 2 sayıyı toplayan program yerine. Aslında işlemci (CPU) sadece matematiksel.MASM için alternatif direktif . çünkü ayrılan fiziksel alan bu kadardır.

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

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

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

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

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

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

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

Hafızaya dataları girer sonrada bunları ekran kartına gönderirim nasıl olsa ekran kartı daha sonraki işlemleri kendisi halleder. işlemcinin AH kaydedicisine 09. onu senin yerine işletim sistemi yapar zaten.Byte’ları ekran kartına göndermene gerek yok. AAP. AAP. 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. Buradaki acemi assembly programcı (AAP) azıcık assembly bilgisi olan birini. birincisi 9. Acemi programcının kafasının içinden geçenler. 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.Ama gönderme işlemini nasıl yapacağım. fonksiyon olan "Display String". interrupt servisini çağır.Hangi işletim sistemini kullanıyorsun? AAP.Assembly dilinde ekrana bir şey yazdıracağım! AAP.Windows! TAP.Merhaba TAP. Anladın mı? AAP. ikincisi fonksiyon numarası 4C olan "Terminate Program". Ha bu arada son karakterden sonra hafızaya bir $ işareti koy ki interrupt servisi yazılacak karakterlerin bittiğini anlasın.Peki nasıl olacak? TAP. tecrübeli assembly programcısı (TAP) yeterli derecede bilgisi olan bir programcıyı ima ediyor.Anlar gibi oldum? Ama ben bu işi kendim yapamaz mıyım? HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .INT 21’in 9. AAP. Tamam. fonksiyonu senin için birebir. AAP. bana anlatırmısın lütfen? TAP. DX kaydedicisine karakterlerin başlangıç adresini yaz.Şekil 6 . sonrada 21. sana bir sorum olacak ekrana MERHABA ASSEMBLY yazdırmak istiyorum ama ekran kartına byte’ları nasıl göndereceğimi bilmiyorum.Programımızın parçaları Yukarıdaki şekilde algoritmanızın assembly koduna dönüşmüş halini görüyorsunuz.

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

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

Assembly programcıları kaydediciler. Bir assembly programcısı keskin bakışlarını mikroişlemcinin içinden çekip :) sistemin tamamına baktığında bile. Şekil 9 . donanımların ve donanımları birbirine bağlayan birimlerin çalışması ile ilgili fazla birşey göremez yada görmesine gerek yoktur. Assembly programcısı sisteme nasıl bakıyor? Mikroişlemci bir çok karmaşık birimden oluşur.. Yorumlarınızı ve önerilerinizi bekliyorum. 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.. ve assembler konularını işleyeceğiz. Bir assembly programcısı sadece mikroişlemci içindeki birkaç kaydediciyle ilgilenir.. 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. böylece programın başlangıç adresini doğru ayarlamış olursunuz. Bunun dışındaki birimler genelde okullarda bilgilendirmek amacıyla verilir. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .Adım adım programı işlemek Bir sonraki makalemizde sayı düzenleri ile ilgili birkaç önemli noktayı. neyse ki programcılar donanımsal olarak sistemleri fazla yakından bilmek zorunda değillerdir. örneğin 0D karakterini kodlardan çıkartın yada CX’e yüklenen değeri değiştirin.bu interrupt servisi hafızada 24 değerini bulana kadar ekrana yazma işlemine devam eder. Son olarak debug ile bu programı adım adım çalıştırabilirsiniz. Programcılık ve elektroniğin sınır noktası budur aslında. örneğin CPU içinde bir ALU biriminin olduğunu bir çok programcı bilir ama bu birimin çalışması ile ilgilenmezler. Bu programın kodları ile oynayarak konuyu daha iyi kavrayabilirsiniz.

Yukarıdaki şekilde bu birimleri görüyorsunuz. 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. Dikkat ederseniz bütün yollar CPU’ya çıkıyor.PC’nin kabaca iç organizasyonu Bir sisteme bilgisayar diyebilmeniz için o sistemin en az 1 CPU. CD-ROM kilitlenmelerinde Ctrl+Alt+Del kombinasyonun zorda olsa çalışması bundan dolayıdır. bunun böyle olması gerekir yoksa işler kontrolden çıkabilir. memory (RAMROM/Hafıza) ve I/O (Input-Output/Giriş-Çıkış) birimin olması gerekir. diğer birimler arsında doğrudan bir bağlantı yok.X ışınlı gözlerimiz PC üzerinde? Şekil 1 . 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. Ne demişler kontrolsüz güç. Ayrıca DMA özelliği kullanıldığında CPU veri transferinden elini ayağını tamamen değil kısmen çeker. 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 .

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

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

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

Hafıza denilince boyutu 8 bit olan bir dizi hücre ve bu hücrelerin numarası olan adresler akla gelir. Yukarıdaki gibi bir hafıza yapısı. adres ve kontrol yollarına bağlıdır. Hafızada bulunan veriler hexadecimal formatta gösterilirler. Hafıza chip’leri veri. X86 ailesi işlemciler. hafızadan verileri düşük değerlikli kısmından itibaren okurlar (little endian).Hafızanı fiziksel yapısı. Şayet veri yolu 32 bitlik ise daha fazla bank gerekir. örneğin 8086 işlemcisi için. 16 bitlik bir veri yolu bulunan işlemciler için uygundur.ise ayrıcalıklı mod. Hafızanın Fiziksel Yapısı Şekil 4 . 16 veya 32 bitlik bir değer işleyebilir. Böyle bir durumda hafızanın fiziksel yapısını bilmek işe yarayabilir. 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. x86 hafızası ne kadar byte olarak adreslense de programcı hafızadan tek bir komut ile 8. Örneğin 0. 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 . 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. adresten itibaren 16 bitlik (2 byte veya word) bir değerin işlemci kaydedicilerine herhangi bir işlem için çekileceğini varsayalım. sıra hafızada. Đşlemciyi kısaca anlatmaya çalıştım. Çok karışık bir konu olmasına karşın basit bir anlatımla bu konuyu kavramanızı umuyorum. HAFIZA Şimdi hafızanın fiziksel ve mantıksal yapısını anlatacağım. özetle data bus’ın (veri yolu) genişliği kullanılacak olan hafıza chip’ini belirler. bu binary formata en uygun sayı sistemidir.

Adres yolu 16 bit olan bir mikroişlemci 216 yani 65536 adet hafıza konumuna erişebilir. 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. karakter vs. Bu tür ayarlamalar assembly dilinde direktiflerle yapılır. Birde tek numaralı bir adresten örneğin 7. Protected mod çok daha karmaşıktır. Mikroişlemci hafızanın herhangi bir konumuna erişirken segment adresini segment kaydedicilerinden. 80286 işlemcisinin adres yolu 24 bitlik’ti ve 224= 16777216 hücreyi. Özetle çift numaralı adreslerden 1 byte’tan fazla bir değere erişilirse buna sıralı erişim (Aligned Memory Access). offset adresini de şayet erişilecek olan bir komut kodu ise IP kaydedicisinden alır. Erişilecek olan veri (değişken. X86 uyumlu tüm PC’ler Real Mod denilen çalışma modunda açılırlar. başka bir deyişle 16MB. örneğin erişilecek veri stack’ta (yığın bellekte diyebilirsiniz) ise buradaki verinin offset adresini SP (stack pointer) tutar. 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. Örneğin Linux yada Windows işletim sistemi yükleniyorsa hafıza Protected Mod (korumalı mod) denilen yapıya bürünür. bu tür bir hafıza erişimi daha uzun zaman alır. segmentler sayfalar ve adreslenebilen her byte ise satır olara düşünülebilir. Hafıza organizasyonuna yapılan bu yaklaşıma hafızanın mantıksal yapısı diyebiliriz. 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. 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. Sayfalama (paging). sanal bellek (virtual memory) ve multitasking (çok görevlilik) korumalı modun getirdiği büyük avantajlardır. 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.) ise verinin türüne göre offset adresini tutacak olan kaydedici değişir. 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. Yavaş yavaş 64 bit devri başlıyor. daha sonra işletim sistemine göre hafıza farklı bir şekil alabilir. buda 4 Milyar küsür hafıza konumuna denk gelir.yerleşecektir ve en hızlı hafıza erişimi bu şekilde yapılır. 8086 işlemcisi 20 bitlik bir adres yoluna sahiptir ve adresleyebileceği alan 220=1048576 yani 1 MB. 80286 ve sonrası işlemciler protected mod’a geçiş yapabilir. Ş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. Günümüzde kullanılan mikroişlemcilerin adres yolu çoğunlukla 32 bitliktir. DOS işletim sistemi yükleniyorsa (neydi o günler :)) hafıza real mod’da kalır. lık bir hafıza alanını adresleyebilirdir. Sıralı hafıza erişimi sırasızdan 2 kat daha hızlı olduğundan programlamada buna dikkat edilmelidir. a denk gelir. Bu durumda hafızanın tamamı bir kitap. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . adresten okuma yapıldığını varsayalım. tek numaralı adreslerden okuma yapılırsa buna sırasız hafıza erişimi (Unaligned Memory Access) denir. 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. 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.

DI) veya 16 bitlik olan IP kaydedicisinde tutulur. TITLE Kaydediciler ve Hafıza (regmem. Şekil 5 . real mod’da offset adresleri index kaydedicilerinin 16 bitlik kısımlarında (SP. Bu durum xxxx:xxxx formatında gösterilir. viteste sürmeye benzer. Hafızanın gerçek yapısını göz önüne alırsak örneğin 8086 işlemcisi en fazla 1MB.Programcı hafızayı adresleri olan byte tablosu olarak düşünür Real mod’da gerçek adres şu formülle bulunur. 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. 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. 045F:0032 adresi için.Segment kaydedicileri 16 bitliktir.asm) . lık alanını adresleyebilirsiniz.BP.SI. Şimdi’de hafıza ve kaydedicileri daha iyi anlamak için örnek program hazırlayalım. lık hafızayı adresleyebilir fakat xxxx:xxxx şeklinde bir gösterim 4GB’lık bir alana denk gelir (FFFF kere FFFF). 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.######################################## HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Gerçek modda bilgisayarınız Pentium 4 bile olsa hafızanın sadece 1MB. Bu son model ferrari’nizi otobanda 1. burada 3456 segment adresi iken 76A3 ofset adresidir. sonra buna offset adresi eklenir ve gerçek adres bulunur. ayrıca sadece kaydedicilerin 16 bitlik kısımlarını kullanabilirsiniz. Örneğin 3456:76A3 real modda bir hafıza adresini gösterir. 045F0h+0032h=04622h gerçek hafıza adresidir.

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

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

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

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

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

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. Aşağıdaki şekil. disp[bx][si] disp[bx+di] [bp+si+disp] [bp][di][disp] BP = 1000h. Đndeksli adresleme için. and disp[bp][di] adresleme modlarıdır. [bp]. CH’a SS:112A adresindeki veri yüklenir . [bx].8086 adresleme modları için yardımcı şekil. disp[bx][si]. al. ve taban indeksli artı direkt adresleme için değişik yazım şekillerini desteklerler. [bp][si]. ( 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. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . mov al. [bp][di].10h[bx+si] mov ch. DI = 5 olduğunu varsayalım. disp[bp]. al. [di]. bu 17 adresleme modunu ezberlemeniz yerine kolayca hatırlamanıza yardımcı olacaktır. Bunlar disp. disp[bp][si]. SI= 0120h.mov mov mov mov al. disp[si]. disp [bx][di]. AL’ye DS:2130 adresindeki veri yüklenir . [bx][di]. CS:2007 adresinden itibaten 2 byte’lık veri TASM ve MASM ‘ın adresleme modları için esnekliği. [si]. disp[di]. al. disp[bx] = [bx][disp] = [bx+disp] = [disp][bx] = [disp+bx] Taban indeksli adresleme için. [bx][si]. Şekil 1 . disp[bx].125h[bp+di] mov bx. [bx][si] = [bx+si] = [si][bx] = [si+bx] . Taban Đndeksli artı direkt adresleme için. MASM ve TASM "[ ]" sembollerine "+" operatörü gibi davranır.cs:2[bx][di] yüklenir . taban indeksli. BX= 2000h. TASM ve MASM assembler’ları indeksli.

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

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

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

. 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). Yukarıdaki adresleme modlarına sabit bir değer eklerseniz 80386 taban indeksli artı direkt adresleme yapmış olursunuz. al. Kullanımı. al. al. disp[index*n] [base][index*n] HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .için. . mov mov mov mov mov mov mov mov al. al. al. Bununla birlikte indeks adreslerini gösteren kaydedicilerin türü verinin hangi segmentten alınacağına etkisi olmaz. al. ikinci kaydedici ise indeks adresini gösterir.SS in ofsetleri için .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.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. al. . al. al.SS deki ofsetleri gösterirler.Taban indeksli adresleme . 80386 indeksli adresleme modlarında sadece tek bir kısıtlama söz konusudur. disp[eax][ebx] disp[ebx+ebx] [ecx+edx+disp] disp[edx+ebp] [esi][edi][disp] [edi][disp][esi] disp[ebp+ebx] [esp+ecx][disp] . 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. al. Bu örneklerde ilk kaydedici taban adresini gösterirken.mov mov mov mov al. al. al. c.SS deki ofsetleri gösterirler. esp kaydedicisini indeks kaydedicisi olarak kullanamazsınız ama esp nin taban kaydedicisi olarak kullanılmasının bir kısıtlaması yoktur. Yukarıda anlattığım 3 adresleme modu ile dizilerin elemanlarına rahatça erişebilirsiniz. al. al. al. 2. . mov mov mov mov mov mov mov mov al. al.modları. Bu adresleme modu ile indeks kaydedicisini 1. . Burada taban adresi olarak esp ve ebp kullanıldığında SS’deki bir ofset adresini göstereceğini unutmayın.Taban indeksli artı direkt adresleme . 4 veya 8 ile çarparak dizilerin elemanlarına erişmede daha esnek bir yapı sağlar. al.modları.SS deki ofsetleri gösterirler. Aşağıdaki örneklerde ise 80386 taban indeksli adresleme modları için çeşitli örnekler görünüyor. .DS deki ofsetleri gösterirler. disp[esi] disp[edi] disp[ebp] disp[esp] . [eax][ebx] [ebx+ebx] [ecx][edx] [edx][ebp] [esi][edi] [edi][esi] [ebp+ebx] [esp][ecx] .

Ayrıca operanda segment kaydedicisini de göstererek adresleme modunu zorlayabilirsiniz. için aşağıdaki örnekleri inceleyelim.DS’nin ofsetini gösterir. [si*2+bx][disp]. . 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.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. [bx+si*2+disp]. Aşağıdaki tüm operandlar aynı işi yaparlar. Zaten CPU tarihinde 80386 bir devrin kapanıp diğer bir devrin başladığı nokta olarak kabul edilir. .DS’nin ofsetini gösterir. [bx+disp][si*2]. al.1000h[ebx][ebx*2] .ds:1018h daki veriyi dan AL’ye kopyalar. . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . ö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.veya disp[base][index*n] "base" ve "index" 80386’nın herhangi bir genel amaçlı kaydedicisi olabilir. disp[si*2][bx]. [ebx][esi] al.SS’nin ofsetini gösterir. Ne var ki 8086 adresleme modları 80386 adresleme modlarına nazaran daha hızlı çalışırlar.SS’nin ofsetini gösterir. 80386 taban indeksli ve taban indeksli artı direkt adresleme modları. ebx = 1000h ve esi = 4. [si*2+disp][bx]. 2. Đlk yazılan kaydedici ölçekli olarak gösterilirse ("*n") bu bir taban adresi olmaktan çıkar bir indeks adresi olur.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. mov mov mov al. Taban/Đndeksli. 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. al. [ebx][esi*1] = mov al. disp[bx][si*2].ds:4000h daki veriyi dan AL’ye kopyalar. [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. 4 ve 8 değerlerini alabilir. 2[ebx][esi*1] = mov al.8[ebx][esi*4] . 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. 2[esi*1] = mov al.1000h[esi*8] . 80386 Đndeksli. 2[ebx][esi] al. "n" ise 1. [ebx][ebp] [ebp][ebx] [ebp*1][ebx] [ebx][ebp*1] [ebp][ebx*1] .

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

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

Programı buradan indirebilirsiniz. Şayet durum böyleyse önce konsola "mouse" yazdıktan sonra Turbo Debugger’ı çalıştırın. Turbo Debugger’ın ekranına ulaşacaksınız. sonra tam ekran yapın ve Turbo Debugger’i çalıştırın. Turbo Assembler’ı. Đndireceğiniz bu dosya Turbo Debugger. Şekil 2 . Turbo Linker paketini içermekte. 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 önce komut istemini açın. Turbo Debugger kullanımına ilişkin birkaç ipucu: Đlk olarak konsola "td" yazarak programı çalıştırın. Bu yüzden tam ekran modunda başlatmanızı öneririm. Turbo Debugger ile program dosyalarınızı açtıktan sonra bir çok işlem yapabilirsiniz. Programı pencere modunda başlattıktan sonra konsol penceresinin ayarlarından tam ekran yapmanızın da bir faydası olmaz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Turbo Debugger Microsoft’un debug’ı ile aynı işi yapar fakat daha kullanışlı bir kullanıcı ara yüzüne sahiptir.Yukarıdaki program sadece 8086 ve 80386 adresleme modlarına örnek olması için hazırlanmıştır. 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 ekranı. Sıra bu programı derledikten sonra Turbo Debugger ile açıp hafızada ve işlemcide hangi olayların olduğunu incelemeye geldi. içinizde belki hala DOS veya Windows 95 kullanan vardır diye bir mouse programı ekledim. 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.

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

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

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.Program adım-adım işleniyor.ax satırlarının işlenmiş olması gerekir. Verilerinizi görmek için 2. Açılan pencereye görmek istediğiniz adresi yazın. pencereye sağ tıklayıp "goto" yu seçin.exe tipindeki program dosyalarında verilerinizi görebilmek için mov ax.@data ve mov ds. Programınız satır-satır işlenme sürecinde. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Şekil 2 . Yalnız .Şekil 2 . Bu makalemizdeki programı incelerken bu özelliği sıkça kullanmanız gerekecek.Turbo Debugger ile hafıza pencerelerini kullanma.

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

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

Böyle bir işlemi yapmak için genel amaçlı bir kaydediciyi kullanmanız gerekir. bunlardan birincisi “mem.yanlış kullanım Yukarıdaki gibi bir komut satırı yazarsanız. MOV MOV AX. Yani acil adresleme modunu segment kaydedicilerine uygulayamazsınız. Doğru kullanım aşağıdaki gibi olmalıdır. MOV komutu ile yapamayacağınız ikinci şey ise segment kaydedicilerine doğrudan bir veri taşımaktır. Şayet acil adresleme kullanarak bir veri taşıyorsanız işlemci operandın boyutunu kaydediciye uyarlar.sayi1 ve sayi2 değişkenlerinin word türünden olduğunu varsayıyoruz. mem” tipinde bir kullanımdır. MOV sayi1. MOV AX. Bu komut işlenince AX’in içinde 0015h değerini görürsünüz. Derleyici bu komut satırına hata verir. Bu işlemi yapmak için taşınacak veri önce mikroişlemci kaydedicilerinden birine getirilmelidir. sayi1 sayi2. mov mov mov byte ptr [bx]. MOV MOV AX. 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. toplam . BX . Yani hafızanın bir konumunda diğer bir konumuna doğrudan taşıma yapamazsınız. sayi2 . 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. MOV DS. 5 dword ptr [bx]. bu kullanım hatalıdır. Örneğin MOV [BX]. Dikkat edilemesi gereken diğer bir husus ise hafıza operandlarıdır. MOV AX. 1525h . AX Bunların dışında operandların boyutları eşit olmak zorundadır. derleyiciniz hata mesajı verir.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.. AX . burada toplam değişkeninin boyutu kesinlikle word tipinde yani iki byte uzunluğunda olmalıdı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]. 1525h DS. 5 (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . gibi) MOV komutunu kullanırken yapamayacağınız iki şey vardır. 5 word ptr [bx]. 15h . Segment kaydedicilerine bir değer yükleyebilmek için genellikle genel amaçlı kaydedicileri kullanılır.

bunu “dd” direktifi ile oluşturabilirsiniz. reg ax. source reg16. XCHG komutu xchg (exchange) komutu operandlarındaki değerleri yer değiştirir. 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. 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. reg16 eax. mem32 reg16. 5 satırını açıklayalım. Genel kullanım formatı lea şeklindedir. 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. lea dest. 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. mem32 reg16. LES. mem32 reg16. 5 komut satırı için ds:0000 adresine 1 byte’lık bir veri yani 05 taşınır. mem HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . LEA Komutu LEA (Load Effective Address – Etkin Adresi Yükle) sadece offset adreslerini hedef operandına yükleyen bir pointer gibi düşünebilirsiniz. böyle bir durumda ds:0000 adresine bir taşıma işlemi gerçekleşeceltir. Ama bu adresten itibaren 05’mi yoksa 0005’mi yoksa 00000005’mi taşınacaktır? Đşte bunu ptr operatörü belirler. 80x86 ailesi için dört değişik kullanım şekli vardır. Ş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ı.mov byte ptr [bx]. Burada BX=0000 olduğunu varsayalım. mem32 reg16. LFS. LGS. kaynak Bu komutları aşağıdaki gibi kullanabilirsiniz. mem reg. Kullanım formatı aşağıdaki gibidir. xchg xchg xchg xchg reg. reg32 (*) (*) 80386 ve sonrası işlemcilerde kullanılabilir LDS. LxS hedef. mov byte ptr [bx]. lds les lfs lgs lss reg16.

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

AL’deki değer negatifse AH’ın tüm bitleri ‘1’ olur. 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. Unutulmaması gereken önemli bir hususta yığın hafıza bölgesine itilen en son değerin çekilecek olan ilk değer olmasıdır. CWD komutunda olduğu gibi word boyutundaki bir değeri double word boyutuna genişletmede kullanılır. CBW. movzx olmalıdır. MOVSX. kaynak . movsx olmalıdır. CWD AX’i DX:AX’e genişletirken bu komut AX’i EAX’e genişletir. cbw cwd (convert word to double word) komutu AX’in değerini DX:AX’e genişletir. Yığına bir şeyler itildikçe SP azalır eökildikçe artar. Tabiî ki bu yığına itilen veya yığından çekilen değerin boyutuna bağlıdır. SS:SP her zaman yığının tepesi olarak tabir edilen noktayı gösterir. cbw cwd cwde cdq bswap xlat hedef. Bu gibi durunlarda aşağıdaki komutlar 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 komutlar 8086 zamanından kalma ve günümüzdeki modern assembly programlarında pek kullanılmayan komutlardır. Şayet AL’deki değer pozitifse AH’ın tüm bitleri ‘0’ değerini alır.Hedef kaynağın iki katı büyüklüğünde reg32 MOVZX.Hedef kaynağın iki katı büyüklüğünde hedef. 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. cwd Bu komut 80386 ve sonrası işlemcilere özeldir. Yığın hafıza bölgesi ile ilgili unutulmaması gereken üç önemli kural vardır. CWD. Şayet yığına 4 byte’lık değer itilirse SP’nin değeri 4 azalır. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . kaynak . Segment kaydedicilerinden olan SS yığın hafıza bölgesinin segment adresini gösterir. 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. CBW komutundaki kurallar bu komut içinde geçerlidir. CWDE. 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.

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

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

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

programımın algoritmasını da yazdıktan sonra kodlarımı yazmaya başlayabilirim. Daha sonra 3 değeri ile çarpıp tablodan adresi buluyoruz.gerekiyor. tabiî ki bu bilgide data segmentinde bir adreste saklı kalsın. 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 . Bu noktadan sonra bu adresi DX kaydedisine yükleyip ekranda string yazdırma kesmesini çağırırsak işlem tamam olacaktı ama. Bununla beraber “:” karakterinide saat bilgisini yazdırırken saat ile dakika arasına yerleştirelim. Tabiî ki Uc bir değişken ve data segmentinde tanımlı olmalıdır. DI veya BX kaydedicilerinin birinde olmalıdır. Ayirac DB‘:’ Birde saat kelimesini data segmentte tanımlayalım. bu yüzden bizde hesapladığımız indeks değerini DI ya yükledik. 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. SaatTablo[AX] gibi bir komut satırı kullanamam çünkü böyle bir adresleme modu mevcut değil. Indeks olarak kullanılacak adresler 8086 assembly dilinde SI. SaatTablo taban adresine göre hesapladığımız indeks adresi halen AX kaydedicisinin içinde ve LEA DX. Uc DB 3 Al deki değer 3 ile çarpıldığında sonuç 16 bitlik AX kaydedicisinde saklanır. Saat DB ‘Saat $’ Şimdi kabataslak ne yapacağım belli oldu.

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

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

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

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

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

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

O=1 ise 1. operand’tan büyüktür. Şartlı dallanma komutlarının ilk harfi J ile başlar ve takip eden 1. C=0 ise 1. Bu tür komutları bundan sonra JXXX komutları olarak kullanacağım. C bayrağının işaretli sayılarda bize verdiği sonuçların bir anlamı yoktur.C bayrağı işaretsiz sayılarda.2 yada 3 harf şartı gösterir. JNAE JNB. O=1 veya S=1.S=0. mov ax. O=0 ise 2. Z=1 yani operandlar eşit.5 mov bx. Şartlı Dallanma Komutları: Đngilizce karşılığı Conditional Jump Instructions’dır. b. Tüm bu anlamlar ve komutları aşağıdaki 3 tabloda özetleyebiliriz.5 CMP ax. 3. 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.1. operand 1. operand’tan büyüktür. C=1 ise 2. 2.S ve O bayrakları işaretsiz sayılarda anlamsız olurken işaretli sayılarda 2 değişik durumu gösterirler.S=0. 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. Karar alma mekanizmaları bu komutlar ile yapıldığından çok önemli komutlar olduğunu sanırım tahmin edebilirsiniz.operand dan büyük demektir. a. operand büyüktür. JAE JE JNE JPE JP JPO JNP JNC JC JNZ JZ JNS JS JNO JO JNP JPO JP JPE HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . operand 1.Z bayrağı sayılar ister işaretli ister işaretsiz olsun eşitlik yada eşit olmama durumunu gösterir. Bunlar. O=0 veya S=1. operand 2.bx . JXXX komutlarının da CMP komutları gibi işaretli ve işaretsiz değerler için farklı anlamları vardır.

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. Bunlara örnek olarak JA ve JNBE’yi örnek verebiliriz. 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. Zero=0 Carry=0.Đş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. deyimler aslında şartlı dallanma komutları ile düzenlenmiş bir kaç assembly komutuna benzetilebilir. fakat programcıyı assembly kodlarını yazarken birazcık olsun rahatlatması için Intel bu tür yazımı uygun görmüştür. while vb. JNB JNAE JNC. JAE JB JC. xxx kısmı ise şarta göre değişir. for. 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. Tüm programlama dillerinde kullanılan if. Tablolarda aslında aynı işi yapan hatta makine düzeyinde aynı kodu üreten komutlar vardır. JNAE JNB JC. küçük. yukarısında veya aşağısında kelimeleri sayıların değerleri açısındandır. Aşağıdaki örnekle bu olayı daha iyi anlayabilirsiniz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Assembler her iki komut içinde aynı makine kodunu üretir.

Ş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

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. db db 2345h 100h HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . carpilan db 2345h . carpilan mov bx. mov mov mul ax.. .. . 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. 100h bx bu işlemden sonra DX=0023h ve AX=4500h olur.sayi al komutlarını kullanabilirsiniz.. mov ax. 100h ile 2345h değerlerini çarpalım.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. Şayet bu çarpılan değer sizin için önemliyse. DX’te daha önce ne olduğu önemli değildir çünkü çarpmadan sonra buraya sonucun yüksek değerlikli byte’ı yerleşir. Burada dikkat ederseniz çarpma işlemiyle birlikte AX kaydedicisindeki "çarpılan" da kaybedilecektir... Fakat çarpılan değer yani 2345h bu işlemden sonra kaybolacaktır. Aşağıdaki örnekleri inceleyin. Aynı şeyi tabi ki çarpan için yani 100h değeri içinde yapabilirsiniz. 2345h bx. . carpilan carpan . mov mul al. Sonucun düşük değerlikli byte’ı ise AX kaydedicisinde saklanır.Pratik olarak 8 bitlik bir değerin karesini almak için.

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

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

0105h olur. Đşaretli çarpma Word’u Byte’a Bölmek Örnek: 10h:3h işlemini yapmak istiyoruz. Div ve idiv komutlarının genel kullanım formatları aşağıdaki gibidir. Aynı şekilde sonucun işaretini öğrenmek için işaret bayrağı yerine C ve O bitlerinin sıfır olup olmadığı kontrol edilmelidir. Doubleword’u Word’e Bölmek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . çü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.Bununla beraber bu formattaki çarpma komutları Z bitini her zaman doğru bir şekilde etkilemeyebilir. bl’ye bölündü bu işlemden sonra AX. ş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. 10h şimdi 0010h ve AX’te bl . DIV ve IDIV Komutları DIV division yani bölme kelimesinin kısaltmasıdır. ax. 10h bl. bu değerlerin ikisinin de byte türünden olduğunu varsayalım. AH’taki 01h kalan ve AL’deki 05h ise bölümdür. 03h . 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. Bu durumda byte türünden bir değeri bölmek isterseniz bunu CBW komutu ile word boyutuna dönüştürmeniz gerekir. Đşaretsiz çarpma . Bu yüzden bölünenin boyutu en az word türünde olmalıdır. bl yerine başka bir kaydedicide olabilir! . Bölme işlemi çarpmanın tersine bölünen’e göre küçük sonuç üretir. hatırlarsanız bu tür komutları daha önceki makalelerimizde açıklamıştık. 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. Nitekim 16’nın (yani 10h) 3’e bölümü ile de bu sonuç üretilir. mov mov cbw div al. an azından Intel bu komutlar için böyle bir form öngörmüştür. div div idiv idiv reg mem reg mem . Bu konuya çok boyutlu dizileri ve karmaşık veri yapılarını anlatırken bir daha değinmeyi düşünüyorum.

şeklinde olur. 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. artık bu komutları kullanarak basit bir hesap makinesi programı yazmak isteyebilirsiniz. Malesef Tüm Sonuçlar Binary Toplama. aynı kağıt üzerinde normal bölme işlemi yapar gibi. çarpma ve bölme komutlarını gördük. Evet ekrana yazdırmak için daha önce programlar yazdık fakat bunu sadece stringler ile gerçekleştirdik. 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. 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. Quadword’u Doubleword’e Bölmek Peki ya sonuç tam değilse? Mesela 11h’ı (yani 17’yi) 3’e bölerseniz sonuç normalde 5. fakat floating point ünitelerini kullanmak inanın bu işten daha pratiktir ve daha kolay sonuç verir. 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. 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. bu işlemi div komutu ile yaptığınızda ise AX’te 0205h değerini görürsünüz. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . yani bölüm 5 ve kalan 2.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. Ondalıklı bölme işlemleri için floating point kaydedicileri kullanılır ve bu kaydediciler matematik işlemcisinin içindedir. Artık matematik işlemcisi normal işlemcinin içine gömülü olarak geliyor.666. Bu yöntem sıkça kullanılmaz. Ö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. çıkartma.. hatta daha önce bu iş için bu yöntemi kullanan bir program görmedim diyebilirim. 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. böyle bir programı yazmaya başladığınızda karşınıza sonuçları ekranda desimal formatta göstermek gibi bir problem çıkacaktır. bu tamamen kullanıcının hayal gücüne kalmış bir olaydır. Representation yani gösterme veya sunum işlemi çok geniş bir yelpazede incelenebilir..

Artık sonuc değişkenini referans göstererek ekrana yazdırma kesmesini kullanabilirsiniz. şimdi ekrana sırasıyla 33h’ı ve 32h’ı gönderirsek kullanıcı 32 yi görecektir. mikroişlemci hesaplamaları binary yapar bu yüzden ascii’den binary’ye dönüşüm yapmak gerekir. 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. 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. sonuc=3332h olur.AX’teki 0203h artık 3233h oldu. 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. Keşke AX’teki 0203h değerinde 0’ların yerine 3 gelseydi. mov sonuc. or ax. 20h bl.3030h . AAS Komutları Klavyeden giriş yapıldığında. x86 tabanlı işlemciler hafızayı adreslerken little endian byte sıralamasını kullanırlar. Şayet ekrana bir karakter basılacaksa bu karakter ekrana gönderilmeden önce ascii forma dönüştürülmelidir. mov mov div ax. harflerin ve bir dizi kontrol karakterinin kod karşılıkları vardır sayıların kod karşılıkları yoktur. basılan tuşa ait kod hafızada ascii formatta saklanır.sonuc ah. ax . lea mov int dx.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. Bu bağlamda biz 32 yi değil 3 ve 2 yi yan yana ekranda göstermeyi düşünmeliyiz.AX=0203 yapar. 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. 0Ah bl . Ama şu anda AL’de ne 3 ne 2 var sadece 20h var.9 21h AAA. Peki 32yi nasıl yazdıracağız? Unutmayın ki ascii kod tablosunda sadece rakamların. 20h ı 0ah yani 10’a bölsek zaten hex’den decimal’e dönüşüm işlemi yapmış oluruz. 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. Problemi özetleyelim elimizde bir baytlık 20h var ve bizim bunu 2 byte lık 3332h dizisine dönüştürmemiz gerekiyor. 30h ile 39h arası ascii kod tablosunda rakamlar için ayrılmıştır. 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. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . böylece ax ile al’nin içeriklerini takas etmemize de gerek kalmaz.

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

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

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

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

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. biti 1 olan bir byte seçilmiştir. çünkü sonuç 0’dan farklıdır.ax . imm mem. reg mem. ax=0 olur ve "mov ax. imm . IN ve OUT komutlarının kullanımı sonraki makalelerin konusudur. 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. Doğruluk tablosu.0" dan kat kat hızlı çalışır HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . and and and and and and and OR komutu Mantıksal veya işlemini gerçekleştirir. 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 komutu ile şifreleme ve paketleme işlemleri için örnekler şu anda belki de sizin için biraz ağır kaçabilir. Kullanım formatları AND komutundaki gibidir.yukarıdaki işlem yapılır ve AND komutu bayrak kaydedicisinin Z bitini 0 olarak kurar. mem reg. AND komutunun kullanım formatları. reg reg. Đşte burada maske olarak sadece 5. imm eax/ax/al. eXclusiveOR (özel veya) kelimesinin kısaltmasıdır. 1 1 0 0 | | | | 1 0 1 0 = = = = 1 1 1 0 hedef. kaynak reg.hedef := hedef & kaynak doğruluk tablosu yukarıdaki gibidir. xor ax. XOR komutu XOR olmadan şifreleme işlemleri sanırım çok zor yapılırdı.

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. Bayrakların Durumu Yukarıda anlattığım bu üç komut bayrak kaydedicisini aşağıdaki gibi etkiler. NOT komutu NOT komutu operandının mantıksal tersini alır.. Öncelikle Windows’un cmd.AX = 1234h ve BX=9876h olsun xor xor xor ax. not bl . Kullanım formatları aşağıdaki gibidir. NOT komutu hiçbir bayrağı etkilemez.bl = 0001 0101b iken bu komuttan sonra 1110 1010b olur. bx bx. Carry bayrağını 0 yaparlar.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. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bx . BL kaydedicisinin değeri 15h olsun. ax ax. Ş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 reg not mem . XOR komutunun kullanım formatları AND ve OR komutlarınınkiyle aynıdır. bu 3 komut sonrasında AX = 9876h ve BX = 1234h olur. Debug ile bu alana göz atalım.

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

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

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

SI registerine taşınacak bilgi dizisinin başlangıç adresini.stosd LODS lodsb.stosw. DI registerine de diziyi taşımak istediğimiz belleğin başlangıç adresini yerleştirerek HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . komutlarımız byte.scasw. word ve double word dizileri üzerinde işlemler gerçekleştirmek için kullanılmaktadır. "şayet assembly dili ile hafızanın her yerine erişebilecek deneyime sahipseniz yapamayacağınız şey yoktur" gerçeğiydi.cmpsd SCAS scasb. STOS ) incelemeye çalışacağız.Şekil 5 . SCAS.scasd STOS stosb. CMPS. Indis registerleri olarak adlandırılan SI ve DI registerlerinden.movsw. “Merhaba” kelimesi bir string’dir. LODS.lodsd String komutlarını ile işlem yaparken. Komut Kullanım Şekli MOVS movsb. Bu makalemizde 80 X 86 ailesinde kullanılan string komutlarını (MOVS. burada anlatmaya çalıştığım.kodsw. bellekteki bir bilgiyi bir adresten başka bir adrese taşırken kullanıyoruz.cmpsw. 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.movsd CMPS cmpsb. Bu programda özellikte. Aslında video işlemleri için daha pratik interrupt’lar mevcuttur.Klavyeden bir tuşa basıldığında görüntü tekrar normale döner. Aşağıda ilgili komutlar ve kullanım şekillerini tablo halinde görebilirsiniz. ASSEMBLY’de stringleri kontrol edebilen komutlar vardır ve bu komutlar hafıza blokları üzerinde çalışırlar.

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

istenilen word dizisi saklanır es:di ile gösterilen adresteki eax registerinde. word yada double word üzerinde işlemler yapmak için uygundur. ax registerindeki değeri karşılaştırarak arama yap ofset adresi ds:si registerinde bulunan double word dizisi içerisindeki değerle. Stos komutu byte. 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.scasw word dizisi içerisinde ara ofset adresi ds:si registerinde bulunan 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. Bu işlemden sonra yön bayrağının durumuna göre işlemci di registerini arttırır veya azaltır.

ax .13.13 yaz si al.13 .enter’e basılmışsa yaz’a atla . .klavyeden karakter isteniyor .stack 64 .01 int 21h cmp jz inc cmp jg jl degis: sub sbt: al. 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.Programın Ekran Görüntüsü. sonuc için ayrılan alan dizi_al: mov ah.al’deki değeri enter ile karşılaştır . kelime içerisindeki küçük harfler büyük harflere dönüştürülecek.al değerinden 20h çıkar HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .61h degis sbt .al içindeki değerle a=61h karşılaştır . 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.’ ’. Harf değerimizden küçükse büyük harf olduğuna karar vereceğiz ve çıkarma işlemi yapmayacağız. Umarım string komutlarının kullanımı konusunda faydalı olur.girilen al’de .@data ds.istenilen double word dizisi saklanır Şekil 1 .ax es.si ile kelime içinde bir sonraki karaktere ilerle .20h .code mov mov mov ax.model small .data snc db 10.girilen değerden kucukse sbt’e atla al.’$’. Sonuçta enter tuşuyla harf girişi tamamlanıp sonuç değeri elde edilmiştir. 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. Örneğimizde.10. Dönüştürme işleminden sonra programı terk edeceğiz.girilen değerden buyukse degis’e atla .

programı terket Aslında string komutları ile yapılan işlemler bilgisayar kullanıcılarına o kadar yakın ki. SS stack alanının segment adresini tutarken SP bu alandaki offsetleri işaret eder. RET bunlardan bazıları ve bu makalede anlatılacaklar arasındadır. bu hafıza alanını yadığımız tüm programlar kullandı.dizi başlangıcına atla ah.ekrana snc’de tutulan değer yazılıyor dosa: mov ah. Stack memory geçici değerlerin saklandığı bir hafıza alanıdır. mesela msword uygulamalarında kullanılan kopyala-yapıştır gibi.sub mov yukle jmp yaz: mov lea int al. POP.snc 21h .al değerinden 0h çıkar .al .4ch int 21h end .0h [snc+si]. Bununla beraber stack memory’yi kendi isteklerimiz doğrultusunda da kullanabiliriz. Bu makalede stack (yığın) hafıza bölgesini anlatmaya çalışacağım. Yorumlarınızı bekliyorum. PUSH. Stack hafıza alanını kullanmama diye bir lüksümüz yok. CALL. Mikroişlemci SS:SP kaydedicileri ile bu hafıza alanına erişir. Ö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. Bunun için bir çok komut mevcuttur.kelime içerisinde sıradaki harfe son al değerini dizi_al . HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .09h dx. bu makaleye kadar stack memory ile ilgili hiç bir komut yazmasakta. 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. Yığın hafıza alanını etkileyen komutların genel kullanım formatları aşağıdaki gibidir.stack talimatı ile belirliyoruz.Şekil 1 . Özetle PUSH komutu stack’a bir veriyi itmek için. Yukarıdaki şekilde kırmızı bloğu stack memory olarak düşünebilirsiniz. BU alanın büyüklüğünü kod yazarken . Stack’ta saklanan veriler veya adres bilgileri için genelde "stack’a itilen" kelimeleri kullanılır. POP ise verileri çekmek için kullanılır. Geçici verilerinizi saklamak için ne kadar alana ihtiyacınız varsa o kadar stack tahsis edebilirsiniz. . 32 bitlik çalışma modunda ise 32 bitlik değerler saklayabilirsiniz. Mesela .stack 32 diye direktif verdiyseniz SP=0020h ı gösterir. 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 . PUSH ve POP komutları Stack memory’de verilerinizi saklamak için kullanılan komutlardır.stack 100h gibi.Stack (Yığın) hafıza. . Yığına veri itildikçe SP’nin değeri azalır. bu değerler yığından çekildikçe SP artar. Stack’tan geri alınan veriler içinse "stack’tan çekilen" kelimesi kullanılır. x86 mimarisinde yığın hafızaya 16 bitlik çalışma modunda 16 bitlik değerler.stack 32.

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

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Ana prosedürden 3 kere alt prosedürlere dallanma gerçekleşiyor. Program çalıştığında komut isteminden bir yazının girilmesini ister. 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. Alt HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . Her dallanma sırasında geri dönüş adresi yığında saklanır. şayet yazıyı oluşturan karakterler büyük harfli ise bunları küçük harfe dönüştürür..Prosedürler kullanılarak yapılmış bir kaynak kod.Şekil 2 . 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.

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

al registerinde bulunan BCD sayısı.05 . 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. başka bir BCD sayısı ile bölünebilir duruma getirilmiş olur. sign ve zero flaglarını al’ye aktardığı değere göre uygun şekilde etkiler.adım Sonuç 23h = 0010 0011b _________________ =7 05h = 0000 0101b HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . bölme işlemi için uygun hale getiriyoruz.51h = 0101 I.ax = 03 05 aad . 0305 .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. adım 0001b al registerinin _________________ değerini = 08h 0Ah’a böl 0Ah = 0000 0Ah=d’10’ 1010b II. desimal 5’e bölünmekte ve sonuç yine desimal olarak elde edilmektedir. AAD komutunu kullanarak. 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. AAD komutu. ax üzerine paketlenmemiş olarak aktarılan sayıyı. parity.adım Sonuç ah = 08h al = 01h ax = 0801h AAD komutu ise bölme işleminde bölünenin sonucunda.AAD komutu.ax = 00 23 mov bl. AX registerinde oluşan değeri ASCII formata dönüştürme amaçlı kullanılır.ax = 00 07 I. Örneğimizde desimal 35 sayısı.adım bölümün sonuç değerini ah’a . kalan’ı al’ye aktar III. bl’ye al değerini koy div bl . mov ax.

bl . mov al.al=13h mov bl. Durum: al registerinin düşük seviyeli 4 biti 9’dan büyük veya AF set ise.al = 0Eh das . I. al registerindeki değerin desimal sayı olması için çıkartma komutunun ardından DAS düzenleyici komutu kullanılıyor.13 . II. carry.Durum: al registerinin yüksek seviyeli 4 biti 9’dan büyük veya CF set ise. AF set edilir.al = 08 HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . mov al. DAS komutu. adım 09h = 0000 1001b al 05h = 0000 1001b registerlerini +__________________ topla 0Eh = 0000 1110b II. al =14 I.bl=05h sub al. al registeri ile 60h toplanarak CF set edilir. al = 0E daa . al registerinden 6 çıkartılarak.09 . ADD komutunun arkasından kullanılan DAA komutu.05 . AF set edilir. auxiliary. Örneğimizde. 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. al = 9 add al. Durum: al registerinin düşük seviyeli 4 biti 9’dan büyük veya AF set ise.Durum: al registerinin yüksek seviyeli 4 biti 9’dan büyük veya CF set ise. sign ve zero flaglarını etkiler. al registerinden 60h çıkartılarak CF set edilir. al registeri 6 ile toplanarak. II.DAA ve DAS komutu: DAA komutu ile yapılan toplama işlemi sonucunda her bir byte’da iki adet desimal dijit bulunur. Örneğimizde 9 ve 5 değerlerini toplayarak komutumuzla istenilen sonucu elde edeceğiz. parity. desimal 13 ’den 5 ’i çıkartma işlemini al registerinde yaptığımız için sonuç 0E oluyor.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. I.05 .

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

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

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

RCR ve RCL Komutu: RCR Komutu. 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.shr ve rcl komutlarını kullanarak örnek bir program hazırladım.data aamsonuc db ’00$’. Đşlem ikinci operand değeri kadar tekrarlanır. Carry flağının değeri düşük seviyeli bit pozisyonuna.sola kaydır.model small .10. . yüksek seviyeli bit pozisyonundaki değer ise carry flağına aktarılır. Şekil 4 .Rcl komutu ile bitlerin sola kaydırılması Şekil 5 .stack 64 .Programın ekran görüntüsü Bu bölümde anlattığımız aam. Đşlem ikinci operand değeri kadar tekrarlanır. das ile ilgili prosedürde ise rcl komutuyla al registerinin içeriğini bir bit sola kaydırdım.13 dassonuc db ’00$’ HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . 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 sola kaydırır. işleme tabi tutulan bitlerin herbirini bir pozisyon sağa kaydırır. carry bayrağının değeride yüksek seviyeli bit pozisyonuna aktarılır.das. Şekil 3 . Düşük seviyeli bit pozisyonundaki değer carry bayrağına.Rcr komutu ile bitlerin sağa kaydırılması RCL Komutu.

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

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

0 ile assembly kod örneği şekil 4: Turbo Pascal 7.şekil 2: C ++ Builder içersindeki assembly bölümü _____________________________________________________________________________________ _______________________ Şekil 1 ve 2’deki assembly blokları içerisinde. assembly bloğu dışında programlama dilinin fonksiyonları ile sonucu görüntülüyoruz..0 Ekran Görüntüsü C++ Builder içerisinde kullanacağımız assembly bloğu dışındaki component ve fonksiyonları inceleyelim. iki sayının toplanması işleminin nasıl gerçekleştiğine bakalım: Turbo Pascal 7.END...0’da ASM. HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN . şekil 3: Turbo Pascal 7.} blokları arasında..0’da ASM{. 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. 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. ve C++ Builder 6. 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.

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

assembly’nin diğer diller içerisinde nasıl kullanılacağını en basit haliyle anlatabilmek için kısa kodlar kullandım. Makalemizde . daha gelişmiş kodları HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .0 Ekran Görüntüsü C++ Builder 6.ş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. Turbo Pascal 7.

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

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

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

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

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

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

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

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

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

HAZIRLAYAN : 05BP2030 ETHEM DEMĐRKIRAN .

Sign up to vote on this title
UsefulNot useful