SİTE 
            İÇİ ARAMA | 
       
      
        | 
            
         | 
       
     
                    
                                     	
        
        
        
        
                    
    
                    
    
      
         Blogroll | 
       
      
        | 
              
         | 
       
     
                    
    
                    
                    
                     
                 | 
                
                    
    
        
            | 
                
             | 
         
        
            
                
                    
                        | 
                            X86 Assembly Dilinde Değişken Bildirimi - 1 | 
                        
                             | 
                                
                     
                    
                        
                            
	
    
		
            | Gönderiliyor lütfen bekleyin... |   
        
	 
    
 
                         | 
                     
                 
             | 
         
        
            
                
                
Daha önce üst seviye 
programlama dilleri ile uğraştıysanız değişkenler hakkında bilginiz muhakkak 
vardır. x86 assembly dilinde de programcılar programlarında kullanacakları bazı 
verileri, değişken olarak tanımlarlar. Aslında bunlar byte yada bytelardan 
oluşan dizilerdir. Hafızadaki bu veriler, programınızdaki kullanım şekline göre 
değişik haller alabilir.
  
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    
AL,5 
ADD    AL,4
  
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. İşte 
bu 1 ve 0’ları program içinde yorumlamak önemlidir, ancak o zaman anlam 
kazanırlar.
  
Aslında işlemci 
(CPU) sadece matematiksel, mantıksal ve veri taşıma işlemleri yapar. Bu bağlamda 
bizim için alt seviyede önemli olan 1 ve 0’lardır. 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. Örneğin 1111 1111 değeri onluk düzende 
255’mi yoksa -1’mi.
  
255’tir, çünkü 1111 
11112 = 20+21+22+23+24+25+26+27 
= 255
  
-1’dir, çünkü 1 ile 
toplandığında 1 byte’lık alanda 0000 00002 değeri elde edilir ve elde 
biti oluşur.
  
  
  Şekil 1 - 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.
  
  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, çünkü ayrılan fiziksel alan bu 
kadardır. 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. 
Daha önce işlemci durum kaydedicisinin bitsel olarak önemli olduğundan 
bahsetmiştim.
  
Bu kargaşa tamamen boyutların sınırlı olmasından 
kaynaklanıyor. 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. Bunu 
tam tersi de olabilir. Biz bunları ilerleyen makalelerimizde, 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. Yani 2 sayıyı toplayan program yerine, 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. DB 
İngilizce’de Define Byte yani byte tanımla anlamına gelir. Bu direktif ile 
hafızada 1 byte’lık bir alan tahsis eder ve bu alana adresi ile erişebilirsiniz. 
MASM ile DB direktifi yerine byte yada sbyte direktiflerini de kullanabilirsiniz, fakat 
sonuçta assembler’ın yapacağı iş aynıdır.
  
i       db      0
j       byte    255	;MASM için alternatif direktif
k       sbyte   -1	;MASM için alternatif direktif
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. Örneğin k değişkenine sonradan "mov k, 125" 
komutu ile pozitif bir değer atayabiliriz. Yapılamayacak olan ise "mov i, 300" 
veya "mov j, -150" gibi 1 byte’a sığmayacak değerleri bu değişkenlere atamaktır.
  
DB direktifi ile;
  
Ayrılan Hafıza Alanı 
: 1 Byte 
Tanımlanabilecek Değer Aralığı: -128...255
  
Word  Değişkenler
  
DW 8086’dan 80286 işlemcisine kadar offset 
adresleri, işaretli ve işaretsiz tamsayılar tanımlamak için kullanılan en geniş 
veri tipiydi.
  
-32768...65535 
arasındaki tam sayları DW direktifi ile deklare edebiliriz. MASM için word ve 
sword direktifleri de aynı işi görür. Word değişkenler hafızada 16 bit yani 2 
byte’lık alan kaplarlar.
  
	
		| 
		sayi1 | 
		
		dw | 
		
		? | 
	 
	
		| 
		sayi2 | 
		
		dw | 
		
		? | 
	 
	
		| 
		isayi1 | 
		
		dw | 
		
		? | 
	 
	
		| 
		sayi_0 | 
		
		dw | 
		
		0 | 
	 
	
		| 
		sayi_eksi | 
		
		dw | 
		
		-1 | 
	 
	
		| 
		sayi_enbuyuk | 
		
		dw | 
		
		65535 | 
	 
	
		| 
		pointer   
		 | 
		
		dw          
		 | 
		
		sayi1 | 
	 
 
Özetle DW direktifi 
ile;
  
Ayrılan Hafıza Alanı 
: 2 Byte 
Tanımlanabilecek Değer Aralığı: -32768...65535
  
Double Word Değişkenler
  
4 byte’lık 
değişkenler tanımlamak için kullanılır. DD direktifi ile bu türdeki değişkeleri 
tanımlayabilirsiniz. MASM ile dword, sdword direktiflerini de kullanabilirsiniz.
  
	
		| 
		sayi1 | 
		
		dd | 
		
		? | 
	 
	
		| 
		sayi2 | 
		
		dd | 
		
		? | 
	 
	
		| 
		isayi1 | 
		
		dd | 
		
		? | 
	 
	
		| 
		sayi_0 | 
		
		dd | 
		
		0 | 
	 
	
		| 
		sayi_eksi | 
		
		dd | 
		
		-1 | 
	 
	
		| 
		sayi_enbuyuk | 
		
		dd | 
		4000000000 | 
	 
	
		| 
		pointer    
		 | 
		
		dd          
		 | 
		
		sayi2 | 
	 
 
DD direktifi ile;
  
Ayrılan Hafıza 
Alanı : 4 Byte 
Tanımlanabilecek Değer Aralığı: -2,147,483,648...4,294,967,295
  
6, 8 ve 10 Byte’lık Değişkenler
  
DF direktifi ile 6, 
DQ direktifi ile 8 ve DT direktifi ile 10 byte’lık değişkenler tanımlanır. Fakat 
bu direktifler aslında kayar noktalı BCD (ikilik düzende kodlanmış onluk 
sayılar) sayılar için kullanılır. Bu 3 direktifin asıl kullanım amaçları aşağıda 
açıklanıyor.
  
DF: 80386 ve üstü 
işlemcilerde, 32 bitlik korumalı modda, 48 bitlik pointer (indeksleme amacıyla, 
offset adreslerini göstermek için kullanılan bir işaretçi) olarak kullanılır. 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.
  
DQ: 64 bitlik kayar noktalı sayları 64 bitlik 
tamsayıları deklare etmek için kullanılır. Daha çok kayar noktalı sayıları 
deklare etmek için kullanılır, çünkü x86 ailesinin henüz 64 bitlik genel amaçlı 
bir kaydedicisi yoktur. Yani bu direktif ile 64 bitlik bir tam sayı deklare 
ettiğinizde, bu sayı ile doğrudan işlem yapamazsınız çünkü en büyük kaydedici 32 
bitliktir.
  
DT: Daha hassas (80 
bitlik) kayar noktalı sayılar ve 10 byte’lık BCD değerleri deklare etmek için 
kullanılır.
  
Yukarıdaki 
direktiflerle ilgili ayrıntılı bilgileri kayar noktalı sayılarla işlemler 
başlığı altında ilerleyen makalelerimizde vereceğim.
  
Pointer Veri Tipleri
  
Pointer işaretçi 
anlamına gelip adresleme modlarında gördüğümüz indeksli adresleme ile 
alakalıdır. x86 uyumlu işlemciler iki tür pointer’ı desteklerler. Bunlar near 
(yakın) ve far (uzak) pointer’lardır. Buradaki yakın ve uzak kavramı referans 
alınan adresin segmenti (64Kb.) aşmaması yada aşması durumunu ifade eder.
  
Near pointer’ler 16 
bitlik’tir ve bir segmentin offsetlerine erişmek için kullanılırlar. p bir 
değişken olsun, p=1000h için aşağıdaki kodları inceleyelim.
  
mov     
bx, p           ;BX’e p 
pointerını yükle. 
mov     ax, [bx]       ;p’nin 
gösterdiği konumdaki veriyi AX’e getir.
  
Örnekte AX 
kaydedicisinin değeri pointer’ın işaret ettiği adresten alınacak 2 byte’lık 
değer ile değişecektir. Bir başka deyişle DS:1000h ve DS:1001h adresindeki 
değerler AX’e yüklenecek. Bu işlem aynı segment içinde olduğundan dolayı, 
pointer near yani yakın bölgedeki bir adresi göstermiş oldu. Aslında mov ax,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ı.
  
Far (uzak) 
pointer’lar ile hafızanın istediğiniz bölgesine erişip işlem yapabilirsiniz. 
Bunun için pointer deklare edilirken DD direktifinin kullanılması gerekir, yani 
pointer 32 bitlik olmalıdır. BX, BP, 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. İsterseniz bunu bir örnek 
ile açıklamaya çalışalım.
  
5555:3333 adresine 
erişip, buraya FFh değerini kopyalamaya çalışacağız. Bu işlemi yapan program 
aşağıdaki gibidir. Kaynak kodları buradan 
download edebilirsiniz.
  
  
  Şekil 
2 - Uzak adreslere erişmek için 32 bitlik pointer’lar kullanılır.
  
Bu örnekte pointer 
32 bitlik’tir ve erişeceğimiz segment:offset adresini gösterir. LES komutu ES 
kaydedicisine pointer değişkeninin yüksek değerlikli 2 byte’ını (5555h) 
yüklerken, operandında gösterilen kaydediciye de (bu örnekte BX) düşük 
değerlikli 2 byte’ını (3333h) yükler. MOV ES:[BX], 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.
  
  
  Şekil 
3 - LES BX, P komutu işlenmeden önce ES ve BX’in durumu
  
  
  Şekil 
4 - Pointer değişkeni ilgili kaydedicilere yüklendikten sonra
  
  
  Şekil 
5 - 5555:3333 adresine FF değeri yüklendikten sonra
  
ÇOKLU DEĞİŞKENLER
  
Bu tür değişkenler 
birden fazla parçadan oluşur. Tek boyutlu ve çok boyutlu diziler (arrays) ve 
yapılar (structures) bu tür değişkenlerdir. Bu makalede sadece tek boyutlu 
dizileri anlatmaya çalışacağım, çok boyutlu diziler ve yapıları başka bir 
makalede güzel örneklerle, amacına uygun bir şekilde anlatacağım.
  
Diziler
  
Dizilerlerde diğer 
değişkenler gibi hafızaya yerleştirilmiş verilerden oluşur. Ard-arda gelen byte, 
word veya double word değişkenler dizileri oluşturabilir. Daha önceki 
makalelerimizde "Merhaba Assembly" yazısını ekrana yazdırmıştık, işte bu 
karakterlerde hafızada dizi olarak saklanır. Şu anda yazdığım karakterlerde 
hafızada bir dizi veri olarak saklanacak.
  
Dizi kavramının 
yanında getirdiği bazı terimler vardır, bunlar indeks, taban adresi, dizi 
elemanı ve eleman tipi’dir. Burada dikkat edilmesi gereken en önemli nokta 
diziyi oluşturacak elemanların aynı türden olma koşuludur. Diğer terimleride 
isterseniz aşağıdaki şekille açıklamaya çalışalım.
  
  
  Şekil 
6 - Diziler ile ilgili terimler.
  
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. Dizinin elemanlarına erişmek için 
bu adres referans olarak alınabilir. Son olarak dizinin ilk elemanından itibaren 
adresler artarak devam eder ve bu adreslerdeki her elemana indeks değerleri ile 
erişilir. Dizinin herhangi bir elemanına erişmek için kullanılacak klasik 
formül;
  
Eleman_Adresi = 
Taban_Adresi + ((Indeks - İlk_Index) x Eleman_Boyutu)
  
Bu formülde 
ilk_indeks 0 ise göz ardı edilebilir.
  
Dizilerin Deklare Edilmesi
  
Başlangıçta elemanların değerleri önemli değilse;
  
Dizi    
DB     100    DUP (?)    ;byte 
türünden 100 elemanlı bir dizi 
Dizi    DW    100    DUP (?)    
;word türünden olduğundan dolayı hafızada 200 byte’lık alan kaplar.
  
Buradak DUP 
direktifi ingilizcedeki duplicate (diğerinin aynısı) kelimesinin karşılığıdır.
  
Elemanlar aynı olacaksa;
  
Dizi    
DB     100    DUP (12h)    ; 
Hafızaya 100 adet 12h yerleştirir.
  
Elemanlar farklı ise;
  
Dizi    
DB    32, 45, 67, 3F, 0, 7, 11    ;7 tane byte 
türünden elemandan oluşan bir dizi. 
Yazi    DB    ’Merhaba Assembly’         
;16 elemanlı bir karakter dizisi, hafızada ascii kod karşılıkları saklanır.
  
Unutulmaması gerekir 
ki taban adresi dizinin başında yazdığımız etikettir, örneğin yukarıda ’Merhaba 
Assembly’ karakterlerinden oluşan byte türündeki dizinin taban adresi
Yazi’dır.
  
Tek Boyutlu Dizilerin Elamanlarına Erişmek
  
WordDizi    
DW    1, 45, 1234h, 567Ah, 99, 105Eh
  
Yukarıdaki dizinin 
2. elemanına erişmek demek o elemanın adresini bulmak ile aynı anlama gelir. 
Bunun için formülümüz vardı;
  
Eleman_Adresi = 
Taban_Adresi + ((Indeks - İlk_Index) x Eleman_Boyutu)
  
Bu formülü word 
tipindeki dizimize uygulayacak olursak;
  
Eleman_Adresi = 
WordDizi + ((2 - 0) x 2)
  
yada;
  
Eleman_Adresi = 
WordDizi + 2 olarak bulunur.
  
Tabi ki bu işlemi 
bir program ile yapmak lazım. Aynı işi yapan program parçası aşağıda 
verilmiştir.
  
mov    
bx, 2                    
; indeks değeri BX’e yükleniyor, 
add     bx, bx                  
; 2*bx işlemi yapılıyor, 
mov    ax, WordDizi [bx]    ; AX’e dizinin 2. 
elemanı (1234h) yükleniyor.
  
Dizi elemanlarına 
erişmek için çok değişik teknikler mevcut, fakat bunları ilerleyen 
makalelerimizde açıklayacağım. Bazen assembly programcıları dizilerini deklare 
ederken, dizinin ilk elemanı olarak indeks değerini koyarlar. Tabi ki bu durumun 
doğruluğu görecelidir. Örneğin byte türünden bir dizi için bu teknikle en fazla 
255 elemandan oluşan bir dizi deklare edebilirsiniz. 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.
  
Diziler usta 
programcıların vazgeçemediği veri yapılarıdır. Önemli olan dizinin elemanlarına 
erişmek için kullanılacak olan fonksiyonu assembly dilinde yazabilme 
kabiliyetidir. Örneğin;
  
Yildizlar    
DB    10  DUP    (’*’) 
  
dizisinden 
aşağıdaki üçgeni ekrana yazdırmak gibi.
  
* 
** 
*** 
****
  
Alın size ödev, 
bir daha ki makaleye kadar bu programı yazmaya çalışın, böylece hem adresleme 
modlarını hem de tek boyutlu dizileri kavramış olursunuz. Sakın zor demeyin elin 
oğlu dizilerden matrix türetip, sonra ona felsefi bir boyut ekleyip filim 
yapıyor :)
  
                
                Makale: 
                X86 Assembly Dilinde Değişken Bildirimi - 1 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
                         
                     
                 
                
                
             | 
         
        
            | 
                
             | 
         
     
                 |