Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Eren Erener
Eren Erener
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
12 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: adresini adresleme bitlik debugger direkt indeks indeksli kaydedici kaydedicileri kaydedicisi komutu kopyalama ofsetleri program segment X86 Assembly Eren Erener
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Başlangıç
Kategori : X86 Assembly
Yayınlanma Tarihi : 18.4.2005
Okunma Sayısı : 54564
Yorum Sayısı : 5     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 19.4.2024
Turhal Temizer
Mac OS/X Removing CUDA 19.4.2024
Burak Selim Şenyurt
Kurumsal Yazılımcının Oyun Geliştirme ile İmtihanı 19.4.2024
Burak Selim Şenyurt
Matematik ve Oyun Programlama - Missile Command - Final 19.4.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
x86 Adresleme Modları ve Turbo Debugger
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu makalede x86 adresleme modlarını anlatmaya çalışacağım, ayrıca sembolik kodlarımızı, verilerimizi daha rahat görebileceğimiz ve kontrol edebileceğimiz bir program olan Turbo Debugger’ı inceleyeceleyeceğiz.

Geçen makalemizde x86 kaydedicilerini hafızanın yapısını anlatmaya çalışmıştım. Bu makaleye kadar çoğunlukla x86 uyumlu sistemlerin yapısı üzerinde durdum. Bundan sonra yazacağım makaleler daha çok assembly programlama dilini kapsayacak.

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. Ayrıca CPU tüm giriş çıkış işlemlerini de hafızaya erişerek yapar. Bazen hafızadan doğrudan bir kod ya da veri alır, işler. Bazen hafızaya bir veri gönderdiğinizde birde bakmışsınız bu bir yazıcıdan belge olarak çıkmış vs. İş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. Sizlerde programlarınızı yazarken CPU’nun hafızaya nasıl erişeceğini yazdığınız kodlarla belirtmek zorundasınız. Assembly dilinin ilk basamağı olan adresleme modları da bu konuları kapsıyor.

Her mikroişlemci üreticisi bir mikro işlemci piyasaya sürdüğünde, komut setini ve adresleme modlarınıda yayınlar. Programcılar da bu belgelere göre programlarını yazarlar. Intel 8086 işlemcisini piyasaya sürdüğünde oldukça kullanışlı bir dizi adresleme modu sağladı. Intel’in şu ana kadar ürettiği işlemcilerde bu adresleme modlarını kullanabilirsiniz. Daha sonraları bir devrim niteliğinde olan 80386 işlemcisi ile ek adresleme modlarıda geldi. Bu özel adresleme modları sadece 386 ve sonrası işlemcilerde kullanılabilir. Tabi ki bu ek adresleme modları ile assembly programlama dili daha esnek bir yapıya bürünmüştü. Bizde bu makalemizde adresleme modlarını 386 öncesi ve sonrası olarak ikiye ayıracağız.

Ş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. MOV komutu assembly programlama dilinde en çok kullanılan komutların başında gelir. Çünkü bir program çalışırken genelde hafızaya yazar yada okur. MOV komutu da bu iş için biçilmiş kaftandır ve bu kadar çok kullanıldığından dolayı bir çok adresleme modunu destekler, yani bu komut ile hafızaya çok değişik yollardan erişebilirsiniz. Bu yüzden bu makalede adresleme modlarını anlatırken MOV komutunu örnek alacağım.

MOV komutunun genel kullanım şekli;

        MOV hedef, kaynak


8086 ADRESLEME MODLARI:

8086 Kaydedici Adresleme:

Adından anlaşılacağı gibi kaydediciden kaydediciye yapılan işlemlerde bu adresleme modları kullanılır. En hızlı adresleme modu’dur, çünkü işlem hafızada değil işlemcinin içinde gerçekleşir.

Genel amaçlı ve indeks kaydedicilerde kaydedici adresleme modları:
mov    ax, bx        ; BX teki değeri AX’e kopyalar
mov    dl, al         ; AL teki değeri DL’ye kopyalar
mov    si, dx         ; DX teki değeri SI’ya kopyalar
mov    sp, bp        ; SP deki değeri BP’ye kopyalar
mov    dh, cl         ; CL deki değeri DH’a kopyalar
mov    ax, ax        ; Bu da doğru bir kullanımdır!


Kaydedici adreslemede en çok dikkat etmeniz gereken husus hedef ve kaynağın boyutlarıdır. Örneğin 16 bitlik bir kaydediciden 8 bitlik bir kaydediciye taşıma yapılamaz!

        mov    al, bx         ;yanlış kullanım, derleme anında assembler hata verir.

Küçük boyuttaki kaynaktan büyük boyuttaki hedefe de kopyalama yapılamaz.

        mov    cx, al        ; Yanlış kullanım, AL’ile CX eşit boyutta değil.

Bunlara ek olarak segment kaydedicilerinin kullanımında dikkat edilmesi gereken noktalar vardır.

1- Segment kaydedicileri arasında bir transfer işlemi ancak genel amaçlı bir kaydedici vasıtasıyla yapılabilir.

        mov    ds,cs        ; doğru kullanılmayan segment kaydedicisi şeklinde assembler hata verir!

Bu işi yapmak için,

        mov    ax,cs
        mov    ds,ax

komut satırları kullanılabilir.


2- CS ve IP kaydedicilerinin değeri kaydedici adresleme ile değiştirilemez

        mov    cs, ax        ; kaynak genel amaçlı kaydedici olmasına rağmen bu işlem mümkün değildir!

Segment kaydedicileri programın icrası aşamasında hafızanın segment olarak adlandırılan bölümlerinin adreslerini tuttuklarından, bu kaydedicileri verilerinizi saklamak veya taşımak için kullanmanızı tavsiye etmem, kullanılmamalıdırlar. Bunun yerine genel amaçlı kaydedicileri kullanmanız daha uygun olur.

8086 Hafıza Adresleme Modları

a- Acil Adresleme ( Immediate Addressing )

Herhangi bir genel amaçlı veya indeks kaydedicisine doğrudan bir değer yükleye bilirsiniz. Yüklenecek olan veri kod segmentten alınacağından bu tür kullanımları şahsen ben pek tavsiye etmem. İyi bir program organizasyonu için, veriler hafızanın ayrı bir bölümünde (mesela data segmentte) değişkenler veya sabitler olarak belirtilmelidir.

        mov    al, 17            ; AL’ye 11h yüklenir.

b- Direkt Adresleme (Displacement Only Addressing )

Acil adreslemenin doğru kullanılmış şeklidir. Bu adreslemede segment:ofset adresi kullanılarak hafızaya erişilir.


        mov    al, ds:12        ; ds:000C adresinden 1 byte AL’ye kopyalanır.
        mov    ds:12, al        ; AL’nin içeriği ds:000C adresine kopyalanır.
        mov    ax, ds:12       ; ds:000C adresinden 2 byte AX’ye kopyalanır.
        mov    ds:12, ax       ; AX’nin içeriği ds:000C adresinden itibaren kopyalanır (2 byte)

Aslında kaynak kod hazırlanırken genelde bu şekilde bir kod yazımı yapılmaz. Değişkenler ve sabitler sembolik kelimelerle ifade edildiğinden buna gerek yoktur. Ne var ki debugger programlarında da sembolik değişken isimlerini değil adresleri görürüz. Aşağıdaki kod parçasını inceleyin;

        .data
        sayi1    db 5

        .code
        mov    ax, @data
        mov    ds, ax

        mov    al, sayi             ; 5 değerini al’ye yükler.
        mov    al, ds:0000        ; aynı işi yapar yani 5’i AL’ye yükler.
                                        ; veriler tanımlanırken sayi1 db 5 şeklinde değil de
                                        ; sadece db 5 yazılsaydı, bu komutu kullanmak zorunda kalırdık.


c- Kaydedici Dolaylı Adresleme ( Register Indirect Addressing )

Adının kaydedici olduğuna aldanmayın. Burada operand olarak kullanılan kaydedici köşeli parantez içine alınır ve bu andan itibaren bir offset adresi oluverir.

        mov    al, [bx]        ; hafızadan AL’ye 1 byte taşınır. Alınacak verinin offset adresi BX’in değeridir.

        mov    al, [bx]
        mov    al, [si]
        mov    al, [di]
        mov    al, [bp]

Yukarıdaki 4 örnekte AL’ye kopyalanacak verilerin offset adresleri ilgili kaydedicinin içindeki değerdir. Segment adresleri ise ilk üçünün DS sonuncusunun SS’dir. BP indeks kaydedicisi yalnız başına hafıza adreslemede kullanılırsa, daima stack segmentin (SS) offset adreslerini gösterir. Fakat BP kaydedicisi de dahil olmak üzere bu adresleme segment kaydedicileri de belirtilerek yapılırsa, o zaman ilgili segment:offset adresine erişilmiş olunur.

BX=0000, BP=0001, SI=0002, DI=0003 olduğunu varsayalım;

mov    al, cs:[bx]     ; AL’ye CS:0000’dan kopyalama yapılır
mov    al, [bx]         ; AL’ye DS:0000’dan kopyalama yapılır
mov    al, ds:[bp]    ; AL’ye DS:0001’den kopyalama yapılır
mov    al, [bp]        ; AL’ye SS:0001’den kopyalama yapılır
mov    al, ss:[si]     ; AL’ye SS:0002’den kopyalama yapılır
mov    al, [si]         ; AL’ye DS:0002’den kopyalama yapılır
mov    al, es:[di]     ; AL’ye ES:0003’den kopyalama yapılır
mov    al, [di]         ; AL’ye DS:0002’dan kopyalama yapılır

d- İndeksli adresleme ( Indexed Addressing )

Kaydedici dolaylı adreslemenin operandına sabit bir değer eklenmiş halidir.

Kullanım şekli;

        mov    al, disp[bx]
        mov    al, disp[bp]
        mov    al, disp[si]
        mov    al, disp[di]

Not : disp kısaltması İngilizcede displacement kelimesinin karşılığıdır. Buradaki anlamı ise referans alınan ofset adresidir. Komut setlerinde adresleme modları açıklanırken disp veya mem kısaltması ile çok sık karşılaşacağınızdan, komutları yazarken İngilizce ifadeler kullanmak durumunda kaldım.

Mesela BX=2000h olsun, mov dl, 20h[bx] şeklinde bir komut kullanıldığında, DS:2020h adresindeki 1 byte’lık değer dl’ye kopyalanacaktır. Aynı şekilde BP=3030h olduğunu varsayalım, mov dh,1020h[bp] gibi bir komut ile, SS:4050h adresindeki 1 byte’lık değer dh’a kopyalanır.

Bu adresleme modunda da BP segment kaydedicisi daima SS’in ofsetlerini gösterir. Fakat kaydedici dolaylı adreslemede de olduğu gibi bizzat segment kaydedicisinide belirterek bu adresleme modunu kullanabiliriz. Bu durumda ofset adresleri komutta belirtilen segmentin ofseti olur.

        mov    al, ss:disp[bx]        ; BX normalde DS’nin ofsetlerini gösterirken burada SS’in ofseti olmuş.
        mov    al, es:disp[bp]        ; BP normalde SS’nin ofsetlerini gösterirken burada ES’in ofseti olmuş.
        mov    al, cs:disp[si]         ; SI normalde DS’nin ofsetlerini gösterirken burada CS’in ofseti olmuş.
        mov    al, ss:disp[di]         ; DI normalde DS’nin ofsetlerini gösterirken burada SS’in ofseti olmuş.

e- Taban İndeksli adresleme ( Based Indexed Addressing )

Bu adresleme modu da kaydedici dolaylı adreslemeye çok benzer. Kullanım formatı aşağıdaki gibidir;

        mov al, [bx][si]
        mov al, [bx][di]
        mov al, [bp][si]
        mov al, [bp][di]

BX’in 0500h SI’nın 0360h olduğunu varsayalım,

        mov al,[bx][si]

gibi bir komut işlenince AL’ye kopyalanacak veri DS:0860 adresinden alınır.

Aynı şekilde;

BP=1598h DI=1004 ve mov ax,[bp+di] gibi bir komut işleniyorsa; AX, SS:259Ch ve SS:259Dh adreslerindeki veri ile yüklenir.

SI ve DI kaydedicileri için Intel’in özel komutları vardır, bu yüzden bu kaydediciler genellikle programlamada indeks değerlerini tutar, arttırır veya azaltırlar.

f- 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.

        mov al, disp[bx][si]
        mov al, disp[bx+di]
        mov al, [bp+si+disp]
        mov al, [bp][di][disp]

BP = 1000h, BX= 2000h, SI= 0120h, DI = 5 olduğunu varsayalım.

        mov al,10h[bx+si]           ; AL’ye DS:2130 adresindeki veri yüklenir
        mov ch,125h[bp+di]        ; CH’a SS:112A adresindeki veri yüklenir
        mov bx,cs:2[bx][di]        ; CS:2007 adresinden itibaten 2 byte’lık veri yüklenir


TASM ve MASM ‘ın adresleme modları için esnekliği.

TASM ve MASM assembler’ları indeksli, taban indeksli, ve taban indeksli artı direkt adresleme için değişik yazım şekillerini desteklerler;

İndeksli adresleme için;

        disp[bx] = [bx][disp] = [bx+disp] = [disp][bx] = [disp+bx]

Taban indeksli adresleme için;

        [bx][si] = [bx+si] = [si][bx] = [si+bx] ;

Taban İndeksli artı direkt adresleme için;

        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. MASM ve TASM "[ ]" sembollerine "+" operatörü gibi davranır. ( 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. Bunlar disp, [bx], [bp], [si], [di], disp[bx], disp[bp], disp[si], disp[di], [bx][si], [bx][di], [bp][si], [bp][di], disp[bx][si], disp [bx][di], disp[bp][si], and disp[bp][di] adresleme modlarıdır. Aşağıdaki şekil, bu 17 adresleme modunu ezberlemeniz yerine kolayca hatırlamanıza yardımcı olacaktır.




Şekil 1 - 8086 adresleme modları için yardımcı şekil.

Bu şekil ile 17 adresleme modunu kolayca görebilirsiniz. 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.

Örnekler;

Bir tek eleman seçin;

        disp, [bx], [bp], [si], [di]

3. sütunu yok sayın ve diğer elemanların birleşimini çıkartın

        disp[bx], disp[bp]

2. sütunu yok sayın ve diğer elemanların birleşimini çıkartın

        disp[si], disp[di]

1. sütunu yok sayın ve diğer elemanların birleşimini çıkartın

        [bx][si], [bx][di], [bp][si], [bp][di]

Son olarak tüm sütunların birleşimi ile aşağıdaki geçerli adresleme modlarını kolayca çıkartabilirsiniz.

        disp[bx][si], disp [bx][di], disp[bp][si], disp[bp][di].

Not:Hafıza adresleme modlarında şayet hesaplanan etkin adres 0FFFFh değerinden büyük olursa, CPU bu hesaplama sonucu oluşan taşmayı göz ardı eder ve FFFFh’e ekleneni 0 dan itibaren ekler. Örneğin BX=10h olsun ve mov al,0FFFFh[bx] komutu işlensin. Bu durunda AL kaydedicisine ds:1000Fh adresindeki veri değil ds:000Fh adresindeki veri yüklenir. (FFFFh+1h=0000, FFFFh+2h=0001,….. FFFFh+16h=000Fh)
 

Sonuç:

8086 adresleme modlarını 2 bölümde inceledik, ilk olarak kaydedici adresleme modlarını anlatmaya çalıştım. Kaydedici adresleme de segment kaydedicilerini kendi amaçları dışında kullanmanız tavsiye edilmez, bu iş için yeterince genel amaçlı ve indeks kaydedicisi var zaten.

Karışık olan kısım ise hafıza adresleme modlarıdır. Hafıza adresleme modlarında belirtilen operand daima bir offset adresini işaret eder, buna etkin adres hesaplama da denir. Hafıza adresleme modlarını unutmamanız için sizlere kolay bir yol göstermeye çalıştım. Adresleme modlarının isimlerinden ziyade kullanım formatları önemlidir. Her komut her adresleme modunu desteklemez. Hangi komutun hangi adresleme modunda kullanılacağı komut setlerinden faydalanılarak bulunur.

Bugüne kadar gerek internetten gerekse Türkçe assembly kitaplarından yaptığım araştırmalarda, Türkçe olarak yayınlanmış ayrıntılı bir komut seti bulamadım bu yüzden İngilizce komut setlerinden faydalanıyorum.

“8086 instruction set” veya “x86 instruction set” anahtar kelimelerini internetten aratacak olursanız karşınıza yığınla komut seti gelecektir. Genelde komut seti kılavuzları aşağıdaki tablo gibidirler.

        MOV - Move Byte or Word
        Usage: MOV dest,src

 

Operands Clocks Size Bytes
  286 386 486  
reg, reg 2 2 1 2
mem, reg 3 2 1 2-4
reg, mem 5 4 1 2-4
mem, imm 3 2 1 3-6
reg, imm 2 2 1 2-3
segreg, reg16 2 2 3 2
segreg, mem16 5 5 9 2-4
... ... ... ... ...
... ... ... ... ...
... ... ... ... ...
Tablo 1 - 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. Örneğin mem,imm (displacement,immediate) acil adresleme yi desteklediğini gösterir. reg,reg (register,register) kaydedici adreslemenin yapılabileceğini, segreg,reg16 (segment register, register 16 bit ) bir segment kaydedicisine 16 bitlik bir kaydediciden kopyalama işleminin yapılabileceğini gösterir.

“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), “size bytes” sütunu ise hafızada makine kodlarının byte olarak kapladığı alanı gösterir. Çoğu zaman assembly programcıları programlarının, işlenme sürecindeki nano saniyeleri ve hafızada kapladığı alanını byte düzeyinde önemi yoksa bu kısımlarla ilgilenmezler. Yani 1. derecede “operands” sütunu önemlidir ve ilgili komutu bu sütunda belirtilen formatların dışında kullanamazsınız.

Son olarak x86 uyumlu hiçbir işlemci mem,mem şeklinde yani hafızadan hafızaya doğrudan bir adresleme modunu desteklemez, aslında bu güne kadar bunu destekleyen hiç bir işlemci görmedim, zaten böyle bir adresleme modunun desteklenmesi durumunda o sistem için yapılan programların çökme olasılığı çok büyüktür.

80386 ADRESLEME MODLARI

80386 Kaydedici Adresleme (80386 Register Addressing)


80386 den itibaren, günümüzde kullandığımız Pentium işlemcilerin 32 bitlik kaydedicileri vardır. 8086 adresleme modlarına ek olarak bu işlemcilere de kaydedici adresleme yaparken bu 32 bitlik kaydedicileri de kullanabilirsiniz. Bu kaydediciler geçen makalemizde bahsettiğimiz;

        eax, ebx, ecx, edx, esi, edi, ebp, ve esp kaydedicileridir.

kullanım formatı;



        mov    eax, ebx

Not: Şayet programınızda 32 bitlik kaydedicileri kullanacaksanız kaynak dosyası hazırlarken .386 talimatını kullanmanız gerekir.


80386 Hafıza Adresleme (80386 Memory Addressing)

a- 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. Segmentlerin her zaman gerçek moda 64Kb. olduğunu unutmamak gerekir, bu yüzden offset adresleri gerçek modda 0...0FFFFh arasını gösterir. Yani 64Kb.’ı geçecek ofset adreslerini gerçek moda değil ancak korumalı moda (Protected mode) kullanabilirsiniz. Fakat gerçek moda 32 bitlik kaydedicileri hesaplamalarda kullanmanızda bir engel yoktur. 80386 kaydedici dolaylı adreslemede kullanabileceğiniz tüm geçerli adresleme formatı aşağıdaki gibidir.

mov    al, [eax]        ; DS in ofsetleri için
mov    al, [ebx]        ; DS in ofsetleri için
mov    al, [ecx]        ; DS in ofsetleri için
mov    al, [edx]        ; DS in ofsetleri için
mov    al, [esi]         ; DS in ofsetleri için
mov    al, [edi]         ; DS in ofsetleri için
mov    al, [ebp]        ; SS in ofsetleri için
mov    al, [esp]        ; SS in ofsetleri için

b- 80386 İndeksli, Taban/İndeksli, ve Taban/İndeksli/Direkt Adresleme modları ( 80386 Indexed, Base/Indexed, and Base/Indexed/Disp Addressing )

80386 İndeksli adresleme modu 32 bitlik bir kaydedici ile sabit bir değerin birleşiminden meydana gelir. 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. Hiçbir zaman unutmamalısınız ki bu adresleme modları ne kadar 32 bitlik olsa da, şayet 16 bitlik gerçek moda kullanılırlarsa erişebilecekleri ofset adresleri 16 bit’i geçemez.

80386 taban indeksli hafıza adresleme modlarında taban adres ve indeks adresi diye iki tane terim kullanılır. Taban adresini ilk operand iken indeks adresini son operand gösterir. Bu kural kaydedici ismi ne olursa olsun geçerlidir. Fakat 8086 indeksli veya taban indeksli hafıza adresleme modlarında, taban adresini sadece BX veya sabit bir değer gösterebilirken, indeks adreslerinide SI, DI, BP ve BX gösterebiliyordu. 80386 ve sonrası işlemcilerde bulunan bu esneklik şüphesiz ki programcıların işini kolaylaştırır.

Aşağıda 80386 indeksli hafıza adresleme modları için birkaç örnek görülüyor;

mov    al, disp[eax]        ;İndeksli adresleme
mov    al, [ebx+disp]      ;modları.
mov    al, [ecx][disp]
mov    al, disp[edx]
mov    al, disp[esi]
mov    al, disp[edi]
mov    al, disp[ebp]        ;SS in ofsetleri için
mov    al, disp[esp]        ;için.

Aşağıdaki örneklerde ise 80386 taban indeksli adresleme modları için çeşitli örnekler görünüyor. Bu örneklerde ilk kaydedici taban adresini gösterirken, ikinci kaydedici ise indeks adresini gösterir. Tabi ki sonuçta bu iki kaydedicinin içindeki değerler toplanarak etkin olan hafıza adresini işaret edecekler. Kaydedicilerin 32 bitlik olduğunu düşünecek olursanız 4GB’lık hafızanın istediğiniz bir konumuna erişebilineceğini de görebilirsiniz (tabi ki korumalı modda). Burada taban adresi olarak esp ve ebp kullanıldığında SS’deki bir ofset adresini göstereceğini unutmayın. Bununla birlikte indeks adreslerini gösteren kaydedicilerin türü verinin hangi segmentten alınacağına etkisi olmaz.

mov    al, [eax][ebx]       ;Taban indeksli adresleme
mov    al, [ebx+ebx]        ;modları.
mov    al, [ecx][edx]
mov    al, [edx][ebp]       ;DS deki ofsetleri gösterirler.
mov    al, [esi][edi]
mov    al, [edi][esi]
mov    al, [ebp+ebx]        ;SS deki ofsetleri gösterirler.
mov    al, [esp][ecx]        ;SS deki ofsetleri gösterirler.

Yukarıdaki adresleme modlarına sabit bir değer eklerseniz 80386 taban indeksli artı direkt adresleme yapmış olursunuz.

mov    al, disp[eax][ebx]         ;Taban indeksli artı direkt adresleme
mov    al, disp[ebx+ebx]          ;modları.
mov    al, [ecx+edx+disp]
mov    al, disp[edx+ebp]          ;DS deki ofsetleri gösterirler.
mov    al, [esi][edi][disp]
mov    al, [edi][disp][esi]
mov    al, disp[ebp+ebx]          ;SS deki ofsetleri gösterirler.
mov    al, [esp+ecx][disp]        ;SS deki ofsetleri gösterirler.

80386 indeksli adresleme modlarında sadece tek bir kısıtlama söz konusudur; esp kaydedicisini indeks kaydedicisi olarak kullanamazsınız ama esp nin taban kaydedicisi olarak kullanılmasının bir kısıtlaması yoktur.


c- 80386 Ölçekli İndeksli Adresleme Modu (80386 Scaled Indexed Addressing Modes)

Programcılıkla az çok uğraşan arkadaşlar diziler konusu bilirler. Yukarıda anlattığım 3 adresleme modu ile dizilerin elemanlarına rahatça erişebilirsiniz. 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. Bu adresleme modu ile indeks kaydedicisini 1, 2, 4 veya 8 ile çarparak dizilerin elemanlarına erişmede daha esnek bir yapı sağlar.

Kullanımı;

        disp[index*n]
        [base][index*n]

veya

        disp[base][index*n]

"base" ve "index" 80386’nın herhangi bir genel amaçlı kaydedicisi olabilir. "n" ise 1, 2, 4 ve 8 değerlerini alabilir.

ebx = 1000h ve esi = 4, için aşağıdaki örnekleri inceleyelim;

mov    al,8[ebx][esi*4]            ;ds:1018h daki veriyi dan AL’ye kopyalar.
mov    al,1000h[ebx][ebx*2]     ;ds:4000h daki veriyi dan AL’ye kopyalar.
mov    al,1000h[esi*8]             ;ds:1020h deki veriyi dan AL’ye kopyalar.


80386 İndeksli, Taban/İndeksli, 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    al, 2[ebx][esi*1]   =     mov al, 2[ebx][esi]
mov    al, [ebx][esi*1]     =     mov al, [ebx][esi]
mov    al, 2[esi*1]          =     mov al, 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. Aşağıdaki tüm operandlar aynı işi yaparlar.

        disp[bx][si*2], [bx+disp][si*2], [bx+si*2+disp], [si*2+bx][disp], disp[si*2][bx], [si*2+disp][bx], [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. 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. Zaten CPU tarihinde 80386 bir devrin kapanıp diğer bir devrin başladığı nokta olarak kabul edilir. Ne var ki 8086 adresleme modları 80386 adresleme modlarına nazaran daha hızlı çalışırlar. 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.

80386 taban indeksli ve taban indeksli artı direkt adresleme modları, ö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. 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. İlk yazılan kaydedici ölçekli olarak gösterilirse ("*n") bu bir taban adresi olmaktan çıkar bir indeks adresi olur. Ayrıca operanda segment kaydedicisini de göstererek adresleme modunu zorlayabilirsiniz.


[ebx][ebp]            ;DS’nin ofsetini gösterir.
[ebp][ebx]            ;SS’nin ofsetini gösterir.
[ebp*1][ebx]         ;DS’nin ofsetini gösterir.
[ebx][ebp*1]         ;DS’nin ofsetini gösterir.
[ebp][ebx*1]         ;SS’nin ofsetini gösterir.
[ebx*1][ebp]         ;SS’nin ofsetini gösterir.
es:[ebx][ebp*1]     ;Zorlanmış,ES’nin ofsetini gösterir.

 



Şimdi sıra uygulamada. Bu uygulama ile hem adresleme modlarını hem de Turbo Debugger programının kullanımını açıklamaya çalışacağım.

TITLE Adresleme Modları (admod.asm)
;########################################
;# Bu program 8086 ve 80386 adresleme modlarının           #
;# iyi kavranması için yazılmıştır.                                    #
;# Son Güncelleme: 17/04/05                                        #
;# Yazan --> Eren ERENER                                            #
;########################################

            .MODEL     SMALL
            .STACK     32
            .DATA

               VerilerByte               DB      5h, 17h, 8Dh, 0AFh
               VerilerWord              DW     1234h, 7h, 0C01Dh
               VerilerDoubleWord     DD     3DF0178Ah, 11223344h, 12345678h

            .CODE

             ANA       PROC

             MOV      AX, @DATA         ; Data segment
             MOV      DS, AX               ; ayarlanıyor.


             MOV      AX, 5566h           ; Acil adresleme.
             MOV      BX, AX                ; Kaydedici adresleme.

             ;----------------------------------------
             ;8086 Hafıza Adresleme Modlarına Örnekler
             ;----------------------------------------

             MOV      DX, DS:0000h       ; Direkt adresleme.

             MOV      BX, 0000h
             MOV      AL, [BX]              ; Kaydedici dolaylı adresleme, DS:0000h adresindeki 5h değeri AL’ye kopyalanır.

             MOV      AL, 3[BX]             ; İndeksli adresleme, DS:0003h adresindeki AFh AL’ye yüklenir
             MOV      AL, 3[VerilerByte]  ; Yukarıdaki ile aynı işi yapar,
                                                   ; zaten assembler VerilerByte değişken ismini ds:0000h olarak çevirecektir.


             MOV      SI, 0                    ; SI = 0 oldu.
             MOV      AL, [BX][SI]          ; zaten BX=0’dı, şu anda AL’ye kopyalanacak değer DS:0000h’daki 05h’tır.
             INC       SI                        ; SI’yı 1 arttırdık,
             MOV      AL, [BX][SI]          ; şimdi AL’ye kopyalanacak değer DS:0001h’daki 17h’tır.
             INC       SI                        ; SI’yı,
             INC       SI                        ; 2 arttırdık, şimdi SI=3 oldu.
             MOV      AL, [BX][SI]          ; şimdi AL’ye kopyalanacak değer DS:0003h’daki AFh’tır.
                                                   ; Burada BX taban SI indeks kaydedicisi oldu.
             MOV      AL, [BP][SI]          ; DS değil SS ’in offsetlerini adresler, şu anda Stack Segment’in içinde ne olduğunu bilmiyoruz!!!

             ;Taban indeksli artı direkt adresleme
             MOV      SI, 0                    ; SI=0 oldu.
             MOV      AX, 4[bx+si]          ; BX’i değiştirmediğimizden hala sıfır ve AX’e getirilecek 2 byte’lık veri ds:0004h adresinden alınacak,
                                                    ; çünkü 4+0+0 = 4’tür. Bu adres VerilerWord değişkenin adresidir ve bu adreste 1234h vardır.
             INC        SI                       ; SI,
             INC        SI                       ; 2 kere arttırılıyor ve,
             MOV      AX, 4[bx+si]          ; VerilerWord dizisinin 2. elemanına erişiliyor.
                                                   ; çünkü 4+0+2 = 6’dır. Bu adreste 0007h vardır.

             ;----------------------------------------
             ;80386 Hafıza Adresleme Modlarına Örnekler
             ;----------------------------------------

             .386                                      ; 80386 adresleme modlarını ve 32 bitlik kaydedicileri kullanmak için bu direktifin yazılması gerekir!!!

             MOV      ESI, 0                        ; İndeks’i 1 olarak ayarlandı.
             SUB       EBX, EBX                    ; ebx = 0 yapıldı. SUB (Subtract) yani çıkartma komutu,
                                                         ; burada "MOV ebx, 0" ile aynı işi fakat daha hızlı yapar.
             MOV      AX, 4[ebx][esi*2]         ; 80386 ölçekli indeksli adresleme modu ile VerilerWord dizisinin 1. elemanı (1234h) AX’e kopyalandı.
             INC       ESI
             MOV      AX, 4[ebx][esi*2]         ; 80386 ölçekli indeksli adresleme modu ile VerilerWord dizisinin 2. elemanı (0007h) AX’e kopyalandı.

             LEA      EAX, VerilerDoubleWord   ; LEA komutu (Load Effective Address) VerilerDoubleWord dizisinin başlangıç adresini EAX’e kopyalıyor,

             ; 80386 kaydedici adresleme
             SUB      EBX, EBX                      ; EBX = 0 oldu.

             ; 80386 taban indeksli adresleme.
             MOV     ECX, [EBX][EAX]            ; ve bu dizideki ilk eleman (3DF0178Ah) ECX’e kopyalanıyor.

             MOV      AH,4CH                       ;DOS’a
             INT        21H                           ;dönüş

             ANA       ENDP

                         END  ANA
 
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.

Sıra bu programı derledikten sonra Turbo Debugger ile açıp hafızada ve işlemcide hangi olayların olduğunu incelemeye geldi. 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. Programı buradan indirebilirsiniz. İndireceğiniz bu dosya Turbo Debugger, Turbo Assembler’ı, Turbo Linker paketini içermekte. Ayrıca bu pakete, içinizde belki hala DOS veya Windows 95 kullanan vardır diye bir mouse programı ekledim. Şayet durum böyleyse önce konsola "mouse" yazdıktan sonra Turbo Debugger’ı çalıştırın.

Turbo Debugger Microsoft’un debug’ı ile aynı işi yapar fakat daha kullanışlı bir kullanıcı ara yüzüne sahiptir. Turbo Debugger ile program dosyalarınızı açtıktan sonra bir çok işlem yapabilirsiniz.

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. Bu yüzden tam ekran modunda başlatmanızı öneririm. Programı pencere modunda başlattıktan sonra konsol penceresinin ayarlarından tam ekran yapmanızın da bir faydası olmaz. Bu yüzden önce komut istemini açın, sonra tam ekran yapın ve Turbo Debugger’i çalıştırın.

Turbo Debugger kullanımına ilişkin birkaç ipucu:

İlk olarak konsola "td" yazarak programı çalıştırın. Turbo Debugger’ın ekranına ulaşacaksınız.


Şekil 2 - Turbo Debugger ekranı.

Turbo Debugger ekranı 5 bölümden oluşuyor. Şekildeki 1, 2 ve 3 nolu kısımlar hafızayı incelemek için kullanılırlar. 4. kısım mikroişlemci kaydedicilerini ve 5. kısımdada yine mikroişlemci kaydedicilerinden olan flag register’ı bitsel olarak görebilirsiniz. Genellikle 1. bölge programı oluşturan kodları, 2. bölgede verilerin incelenmesi için kullanılır. 3. bölgeyi yığın hafızayı gözlemlemek için kullanabilirsiniz.

Turbo Debugger açıldıktan sonra "File" menüsünden derlediğiniz program dosyasını açıp kodlarını inceleyebilirsiniz. Program dosyanızı açtıktan sonra "Program has no symbol table" diye bir mesaj gelebilir. Bu mesaj penceresinde "OK" e tıklayıp çalışmaya başlayabilirsiniz.


Şekil 3 - Turbo Debugger ile dosya açma.

Ayrıca menülerden sırasıyla View/Another/File seçeneklerini tıklayarak başka bir dosyayı diğer bir pencerede açabilirsiniz. (Mesela kaynak dosyasını)



Şekil 4 - Turbo Debugger ile aynı ekranda kaynak dosyanızı da görebilirsiniz.

Şayet bu pencerede yazı yerine hex kodları görürseniz, pencerenin üzerine sağ tıklayıp açılan menüden "Display As" ı seçin.

Programı çalıştırma seçeneklerini "Run" menüsünden seçebilirsiniz. F8 tuşu programı adım adım işletmek için kullanılır, F7 ise adım-adım program işlenirken döngüleri incelemenizi sağlar. 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. Değişikliğe uğrayan kaydediciler beyaz görünür. Programın tekrar çalıştırmak için "Run" menüsünden "Program Reset" seçeneğini seçebilirsiniz.


Şekil 2 - Program adım-adım işleniyor.

Verilerinizi görmek için 2. pencereye sağ tıklayıp "goto" yu seçin. Açılan pencereye görmek istediğiniz adresi yazın.


Şekil 2 - Turbo Debugger ile hafıza pencerelerini kullanma.

Yalnız .exe tipindeki program dosyalarında verilerinizi görebilmek için mov ax,@data ve mov ds,ax satırlarının işlenmiş olması gerekir.

Programınız satır-satır işlenme sürecinde, adresleme yapılan bir komutun işlenmesi anında kod penceresinin sağ üst köşesinde hafızanın hangi bölgesine erişildiği görülebilir. Bu makalemizdeki programı incelerken bu özelliği sıkça kullanmanız gerekecek.


Şekil 2 - Turbo Debugger ile adresleme modlarının işlevleri rahatça görülebilir.

Mesela yukarıdaki şekilde mov al, [BX] komutu işleniyor ve kaydedici dolaylı hafıza adresleme yapılıyor. Burada AL kaydedicisine kopyalanacak olan veriyi "ds:0000 = 05" şeklinde görebilirsiniz.

32 bitlik kaydedicileri görmek içinse kaydedicileri gösteren kısıma (4. kısım) sağ tıklayıp "Registers 32 bit" i seçebilirsiniz.

Turbo Debugger’ın daha bir çok özelliği var ama şu anda bizlere bu kadarı yeter. Şimdi sizler Turbo Debugger ile bu makaledeki programı inceleyerek pratik yapın, ayrıca bu güne kadar yazdığımız programları da Turbo Debugger ile inceleyerek programı kullanmasını daha iyi kavrayın.

Bir sonraki makalemizde veri tipleri ve x86 komutlarını inceleyeceğiz. Daha sonra prosedür ve makrolarıda gördükten sonra nihayet kendi programlarınızı yazabilir seviyeye geleceksiniz. Genelde sizlerden makalelerin daha sık aralıklarla yayınlanması ile ilgili mailler alıyorum. Fakat bir makale hazırlamak en az 1 haftamı alıyor ve  üniversitedeki derslerden ve işlerden dolayı çok az vaktim oluyor. Bu yüzden makalelerimin yayınlanma aralığı birden 20 güne sıçrayabiliyor. Hal böyleyken sizlerin arayı soğutmamak için başka kaynaklardan faydalanmasını tavsiye ediyorum. Bu şekilde çalışan bazı arkadaşlar internetten kaynak kod bulup, derleyip takıldıkları yerlerde bana mail atıyorlar, bunlara cevap vermesi daha az zamanımı alıyor ve sizler içinde çok faydalı olacağından eminim. Şayet İngilizce okuduğunuzu anlıyorsanız sizlere Art of Assembly’yi tavsiye ederim. İnternetten okuyabileceğiniz bedava bir kitap. Mesela bu makaleyi yazarken bu kaynaktan çok yararlandım ve sizlere de tavsiye ederim.

Evet yine geldi ayrılık vakti. Sizlere bol assembly’li günler dileyerek huzurlarınızdan ayrılıyor ve bir sonraki makalede görüşmek dileğiyle esen kalın diyorum. (TV programı sunucusu olabilirdim aslında :))

Makale:
x86 Adresleme Modları ve Turbo Debugger Assembly ve X86 Programlama Eren Erener
  • Yazılan Yorumlar
  • Yorum Yaz
KAS
21
2006
turbo debugler a nasıl program atacağız.File dan exe uzantılı bir şey seçiyorum ama açmadı.Ve bir türlü yapacağımı bulamadım bana bu konuda yardımcı olabilirseniz çok memnun olurum.Bu güzel çalışmalarınızdan dolayı çok teşekkür ederim,ben çok faydasını gördüm...
OCA
3
2006
Hocam merhaba dersler cok eğitici.Kesmeler konusunda bizi biraz aydınlatabilirmziniz.Yazılım kesmesi,donanım kesmesini anlatabilirmisniz.Aynı zamanda işlemci ye kesme geldiğinde ne yapiyor,geri dönüş adresi nerde saklaniyor,bunları anlamakta zorluk cekiyoruz.yardımcı olursanız sevinirim hocam ....
EYL
16
2005
xfdfzugkj
EYL
3
2005
eren harbi diom asm derslerin güzel olmuş ellerine sağlık dostum
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • 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