SİTE 
            İÇİ ARAMA | 
       
      
        | 
            
         | 
       
     
                    
                                     	
        
        
        
        
                    
    
                    
    
      
         Blogroll | 
       
      
        | 
              
         | 
       
     
                    
    
                    
                    
                     
                 | 
                
                    
    
        
            | 
                
             | 
         
        
            
                
                    
                        | 
                            Sembolik kodlar ve X86 Assembly Dili | 
                        
                             | 
                                
                     
                    
                        
                            
	
    
		
            | Gönderiliyor lütfen bekleyin... |   
        
	 
    
 
                         | 
                     
                 
             | 
         
        
            
                
                Geçen makalemizde debug programını tanımış ve makine kodları ile küçük bir program hazırlamıştık. Sonra bu programı yine debug ile bir dosya haline getirmiştik. Şimdi bu dosya ile biraz 
  daha yakından ilgilenelim. Yine komut istemine geçiş yapıp debug 
  programını şekildeki gibi çalıştıralım.  
 
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.
 
 
   
   
  Şekil 1 - Debug ile program yükleme
   
Ekranın solunda bir 
- işareti göreceksiniz ve başka hiçbir şey olmamış görünecek ama aslında 
merhaba.com adlı program dosyasını oluşturan makine kodlarını çoktan hafızaya 
yüklediniz bile. Makine
 
 
kodlarını görmeden önce sizlere küçük bir tavsiye vermek istiyorum. Assembly 
programlama dilinde ayrıntılar çok önemlidir ve her bir ayrıntı kendi çapında 
bir araştırma konusu olabilir, örneğin burada yaptığınız program yükleme 
işlemini windows kullanıcıları, programın simgesine mouse ile tıklayarak 
yapıyorlar ve hatta bu şekilde program hafızaya yüklendikten sonra birde işletim 
sistemi tarafından çalıştırılıyor. Şimdi aklınıza şu soru gelmeli; program 
simgesinin üzerine gelip mouse ile tık-tık yapıldığı andan itibaren, 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 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. Neyse biz konumuza geri dönelim, program şu anda 
hafızada ve 0100h offset adresinden itibaren yüklenmiş durumda. Hemen kodları 
görelim o zaman.
   
   
  Şekil 2 - 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. 
Bizde burada kodları ekranda gösterdik. Neden 0100h adresinden itibaren hafızaya 
yerleşti? sorusunun yanıtı program dosyasının .com uzantılı olmasından 
kaynaklanır ve geçen makalemizde açıkladığımız gibi sonraki makalelerde ele 
alınacak bir konudur. 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. 
Tabi ki ekrana 
yazdırılacak olan MERHABA ASSEMBLY burada data sınıfına giriyor peki komutlar 
nerede?
  
 
   
   
  Şekil 3 - Datalarımız...
   
 
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. 
Tabi ki bu 
şekli ile bize pek bir şey çağrıştırmıyorlar şayet bunlar bizlerin anlayabileceği 
dile biraz yakın olsaydı anlardık.
  
 
   
   
  Şekil 4 - Makine ve Assembly Dili Yan yana
   
 
Yukarıdaki şekilde makine kodlarını sarı assembly kodlarını kırmızı 
çerçevede görebilirsiniz. Tabi ki assembly dili bizlere daha yakın bir dildir. 
Assembly dilindeki bu gösterim aynı zamanda sembolik kodlar olarak ta bilinir. 
Kodları assembly dilinde görmek için debug’ın "u" (unassembly) komutunu 
kullandık, u dan sonra gelen 0100 010A ise hafıza aralığıdır, yani biz burada 
0100h-010Ah offset adresleri arasınındaki makine kodlarını assembly dilinde 
görmüş olduk. Şimdi yukarıdaki şekilde gördüğümüz makine ve assembly kodlarını 
karşılaştıralım; 
 
  
 
Assembly dilindeki 
MOV AH,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.
  
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. 
Burada sadece opcode ile operandı ayırmanız yeterlidir assembly dilindeki 
ifadeleri ne anlama geldiğini şimdilik önemsemeyin. Intel’in opcode uzunluğu 1 yada 2 
byte’lıktır. 2 byte’lık olan opcode’ları 0F ile başlar. Biz şimdilik hep 1 
byte’lık opcodelar ile çalışacağız. Operandlar ise herzaman opcode’lardan sonra 
gelir ve X86 mimarisinde 1,2,4 veya 8 byte’lık olabilir. Böylece ortaya karma 
karışık bir komut seti çıkar, bu yüzdende Intel’in x86 ailesi CISC (Complex 
Instruction Set Computers) olarak anılırlar.
  
 
Burda 3 byte’lık bir 
komut satırı, opcode 1 byte’lık operand 2 byte’lık. Ama şimdi kafamızda 2 tane 
soru işareti var, 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,010B için operand 
kısmı makine dilinde 0B01 olarak ters bir biçimdedir?
  
Tablo 2 : 
Opcode ve Operand 
Bu sorların cevabı 
X86 uyumlu mikroişlemci mimarisini anlayarak bulabilirsiniz. İlk olarak B4 veya 
BA MOV’un karşılığı gibi görünse de öyle değildir, B4= MOV AH’ın BA=MOV DX’in 
opcode karşılığıdır. Yani ikisi de farklı assembly ifadeleridir ve farklı 
opcode’larının olması son derece normaldir. İkinci sorunun cevabı ise x86 
ailesindeki işlemcilerin hafızaya erişme şekillerinin ters sıralı olmasından 
kaynaklanır. Tabi ki birde düz olarak byte’ları yerleştirme olayı var, bunlar 
kitaplarda little endian byte ordering ve big endian byte ordering olarak geçer. 
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. Bu tür konuları öğrencilik yıllarımdayken 
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.
  
  
   
   
    |  
       
		İşlemci Türü 
     | 
     
       
		İşletim 
		Sistemi 
     | 
     
      Byte Düzeni | 
   
   
    |  
      Digital Alpha AXP | 
    
      Tru64 UNIX | 
    
      little-endian | 
   
  
   
    |  
      Hewlett Packard PA-RISC | 
    
      HP-UX | 
    
      big-endian | 
   
  
   
    |  
      IBM RS/6000 | 
    
      AIX | 
    
      big-endian | 
   
  
   
    |  
      Intel x86 | 
    
      Linux | 
    
      little-endian | 
   
  
   
    | 
      Windows | 
    
      little-endian | 
   
  
   
    | 
      Solaris x86 | 
    
      little-endian | 
   
  
   
    |  
      Motorola PowerPC | 
    
      Macintosh OS X | 
    
      big-endian | 
   
  
   
    |  
      Sun SPARC | 
    
      
		SunOS | 
    
      big-endian | 
   
  
   
    | 
      Solaris | 
    
      big-endian | 
   
  
   
    |  
      SGI R4000 | 
    
      Irix | 
    
      big-endian | 
   
  
   
 
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.
  
Assembly Kodlarına Bir Assembly 
Programcısı Gibi Bakmak
  
Yazdığımız 
programda 
iki tane iş yapılıyor. Birincisi ekrana bir dizi byte’ın ASCII görünümünü yazdırmak, 
ikincisi bilgisayarı tekrar kullanıcının ellerine bırakmak yani işletim 
sistemine geri dönüş.
  
  
   
   
  Şekil 6 - Programımızın parçaları
  
Yukarıdaki 
şekilde algoritmanızın assembly koduna dönüşmüş halini görüyorsunuz. Tamam, 
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, birincisi 9. 
fonksiyon olan "Display String", ikincisi fonksiyon numarası 4C olan "Terminate 
Program". 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. Buradaki acemi 
assembly programcı (AAP) azıcık assembly bilgisi olan birini, tecrübeli assembly 
programcısı (TAP) yeterli derecede bilgisi olan bir programcıyı ima ediyor.
  
Acemi 
programcının kafasının içinden geçenler;
  
AAP- Assembly 
dilinde ekrana bir şey yazdıracağım! 
AAP- Hafızaya dataları girer sonrada bunları ekran kartına gönderirim nasıl olsa 
ekran kartı daha sonraki işlemleri kendisi halleder, 
AAP- Ama gönderme işlemini nasıl yapacağım, hımmm ben en iyisi bir bilene 
sorayım. 
AAP- Merhaba TAP, sana bir sorum olacak ekrana MERHABA ASSEMBLY yazdırmak 
istiyorum ama ekran kartına byte’ları nasıl göndereceğimi bilmiyorum, bana 
anlatırmısın lütfen? 
TAP- Hangi işletim sistemini kullanıyorsun? 
AAP- Windows! 
TAP- Byte’ları ekran kartına göndermene gerek yok, onu senin yerine işletim 
sistemi yapar zaten. 
AAP- Peki nasıl olacak? 
TAP- INT 21’in 9. fonksiyonu senin için birebir, işlemcinin AH kaydedicisine 09, 
DX kaydedicisine karakterlerin başlangıç adresini yaz, sonrada 21. interrupt 
servisini çağır. Ha bu arada son karakterden sonra hafızaya bir $ işareti koy ki 
interrupt servisi yazılacak karakterlerin bittiğini anlasın. Anladın mı? 
AAP- Anlar gibi oldum? Ama ben bu işi kendim yapamaz mıyım? 
TAP- Yaparsın tabi ama çok ekmek yemen lazım :) 
AAP- Nasıl yani?(bu 
arada TAP’ın gülüşüne de kızar tabi) 
TAP- Bak 
AAP kardeş, Windows gibi işletim sistemini yazan programcılar senin gibi 
programcıların ekrana bir şey yazmak isteyeceğini, 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. Sende bu hizmetlerden 
faydalanır ve Amerika’yı yeniden keşfetmeye gerek duymazsın. 
AAP- Evet çok akıllıca düşünmüşler doğrusu... 
TAP- İşletim sistemi de bu demektir zaten AAP, programcıya, kullanıcıya 
bilgisayarı kolayca kullandırabilmek. 
AAP- Teşekkür ederim TAP sonra görüşürüz. 
TAP- (AAP’nin sonra tekrar gelip başka interrupt servislerini de soracağından 
endişelenerek) Hey AAP, bak
buradan diğer interrupt servislerine de bakabilirsin, hani lazım olur diye 
söylüyorum... 
AAP- Teşekkürler TAP.
  
Daha sonra AAP 
bilgisayarının başına gider yukarıdaki şekildeki programın ilk üç satırını yazar 
ve çalıştırır, tabi ki ekranda MERHABA ASSEMBLY görünür ama komut istemindeki 
penceresini kilitlenir, çünkü ekrana yazdırma işleminden sonra programı 
sonlandırmamıştır. Bunun üzerine programı sonlandırmak için tekrar interrupt 
servislerini araştırmaya koyulur ve interrupt 21’in 4C fonksiyonunu keşfeder. 
MOV AH,4C ve INT 21 satırlarını da programına ekledikten sonra programı kusursuz 
çalışır.
  
Interruplar 
hakkında şimdilik bu bilgiler umarım sizi tatmin etmiştir. İlerleyen 
makalelerimizde interruptları daha yakından ele alacağız, bu konular gerçektende 
çok zevkli.
  
Yukarıdaki 
diyalog ta kaydediciler (register) diye bir kavram geçti, bunları şimdilik 
mikroişlemci içindeki hafıza konumlarına (memory location) benzeyen yapılar 
olarak düşünün. Kaydedicilerin listesini görmek için debug programını 
kullanabilirsiniz.
  
  
   
   
  Şekil 7 - Kaydedicileri debug ile görmek 
için r (registers) komutunu kullanabilirsiniz.
  
X86 
kaydedicilerinin AX, BX, CX, DX, SP, BP... diye adları vardır ve bunların 
hepsinin değişik işlevleri mevcuttur. Program yazarken elbette bunları 
kullanacağız ama şimdilik üzümünü yiyin bağını sormayın, çünkü bağın yerini 
söylersem ve sizde gider o bağa bakarsanız iştahınız kaçabilir. Kafalar fazla 
karışmadan yeni bir uygulama yapalım.
  
10 defa Merhaba Assembly 
Yazdırıyoruz 
  
Tabi böyle bir 
işi yaptırmanın değişik yolları mevcut ( bir .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. C dilindeki for döngüsü gibi. 
Aşağıdaki işlemleri takip edin.
  
  
   
   
  Şekil 8 - 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, byte’ları saymada sizler için pratik olur. Burada 
CX kaydedicisine (0A)16=(10)10 değerini sayaç olarak yüklüyoruz. LOOP komutu 
CX’in değeri kadar operandı ile belirtilen adrese dallanır, burada dallanılacak 
adres 0103 offset adresidir ve bu işlem sayesinde ekrana 10 defa MERHABA 
ASSEMBLY yazılır. Daha sonra programımız fonksiyon:4C interrupt 21 
ile sonlanıyor. Buradaki string’e dikkat, debug ile assembly modunda hafızaya 
bir dizi karakter girmek için DB (Define Byte) talimatını kullanıyoruz. 
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, string veri 
tipleri 
gibi. DB’den sonra şayet byte’ları karakter olarak girmek isterseniz " " arasına 
yazmalısınız. Bu işlemi karakterlerin hexadecimal kodlarını yazarak ta 
yapabilirsiniz bu sefer her bir karakterden sonra "," koymanız gerekir. Burada her 
iki teknikte kullanılmıştır. 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, zaten CR ve LF kontrol karakterleri olduğundan dolayı 
standart ASCII kod tablosunda A,C,P,Z gibi normal karakter olarak karşılıkları 
yoktur mecburen hex. kod karşılıklarını kullanmak zorunda kaldık. INT 21 
fonksiyon 9 ile yazdıracağınız karakter dizilerinin sonunda mutlaka 24=$ 
bulunmalı yoksa bu interrupt servisi hafızada 24 değerini bulana kadar ekrana yazma 
işlemine devam eder.
  
Bu programın 
kodları ile oynayarak konuyu daha iyi kavrayabilirsiniz, örneğin 0D karakterini 
kodlardan çıkartın yada CX’e yüklenen değeri değiştirin.
  
Son olarak debug ile bu 
programı adım adım çalıştırabilirsiniz, 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.
  
  
   
   
  Şekil 9 - Adım adım programı işlemek
  
Bir sonraki 
makalemizde sayı düzenleri ile ilgili birkaç önemli noktayı, ve assembler 
konularını işleyeceğiz. Yorumlarınızı ve önerilerinizi bekliyorum....
  
 
  
                
                Makale: 
                Sembolik kodlar ve X86 Assembly Dili Assembly ve X86  Programlama Eren Erener 
             | 
         
        
            | 
             | 
         
        
            | 
                 
             | 
         
        
            
                
                
                    
                        - 
                            
                        
 
                        - 
                            
Eklenen Son 10  
                         
                        - 
                            
Bu Konuda Geçmiş 10 
                         
                     
                    
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                        
                            Son Eklenen 10 Makale Yükleniyor
                         
                        
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         
                     
                 
                
                
             | 
         
        
            | 
                
             | 
         
     
                 |