< Assembly programcısının bakış açısı - Computer & Technology & Science - Blogcu





26/3/2007

Assembly programcısının bakış açısı

Mikroişlemcinin ve hafızanın fiziksel yapısı ile programcının bu donanımlara bakışı biraz farklı olabilir. İşte biz bu makalemizde programcı gözüyle bu donanımları inceleyeceğiz. Ayrıca bu makalemizde yeni bir program yazarak kaydedicilerin nasıl çalıştığını ve mikroişlemcinin hafızaya nasıl eriştiğini anlamaya çalışacağız.

Assembly programcısı sisteme nasıl bakıyor?

Mikroişlemci bir çok karmaşık birimden oluşur, neyse ki programcılar donanımsal olarak sistemleri fazla yakından bilmek zorunda değillerdir. Bir assembly programcısı sadece mikroişlemci içindeki birkaç kaydediciyle ilgilenir. Bunun dışındaki birimler genelde okullarda bilgilendirmek amacıyla verilir, örneğin CPU içinde bir ALU biriminin olduğunu bir çok programcı bilir ama bu birimin çalışması ile ilgilenmezler. Bir assembly programcısı keskin bakışlarını mikroişlemcinin içinden çekip :) sistemin tamamına baktığında bile, donanımların ve donanımları birbirine bağlayan birimlerin çalışması ile ilgili fazla birşey göremez yada görmesine gerek yoktur. Programcılık ve elektroniğin sınır noktası budur aslında. Assembly programcıları kaydediciler, 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.

X ışınlı gözlerimiz PC üzerinde?


resim 1


Şekil 1 - PC’nin kabaca iç organizasyonu

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

Konuyu fazla dağıtmadan isterseniz X ışınlı gözlerimizle CPU’ya zoom yapalım :)

X ışınlı gözlerimiz CPU üzerinde?

resim2


Şekil 2 - Mikroişlemcinin kabaca iç yapısı

Sistemi içindeki birimleri birbirine bağlayan yollar, mikroişlemcinin içinde de devam eder. BUS dediğimiz bu yapılar birçok iletkenden oluşur. Kontrol yolunda R/W (oku/yaz) gibi kontrol sinyalleri, veri yolundan işlenecek veriler gidip gelir. Adres yolu iste tek yönlüdür ve CPU’dan diğer birimlere doğru sinyal akışı olur, örneğin hafızaya bir veri yerleştirilmeden önce adres yolundan verinin yerleştirileceği hafıza adresinin bilgisi gönderilir. Bunu daha iyi anlamak için aşağıdaki animasyonu izleyebilirsiniz yada animasyonu offline izlemek için download edebilirsiniz.

En temel 3 birimden biri olan ALU aritmetik ve mantıksal işlemleri yapan bir elektronik devredir. BIU ise komut kodlarının icrası ile ilgilenir yani emirleri icra eden birim olarak basitçe tanımlanabilir. Kontrol ünitesi ise sistemdeki birimleri harekete geçirmek için kontrol sinyalleri üretir. Bu üç birime programcının doğrudan müdahalesi söz konusu değildir. Programcı sadece CPU içindeki kaydedicilere erişebilir.

resim3

Şekil 3 - Kaydediciler işlemcideki, aynı zamanda tüm sistemdeki en hızlı depolama birimleridir. Bu şekil 32 bitlik işlemciler (P4 serisi gibi) için kaydedici yapısını gösteriyor.

Kaydedicileri tam olarak anlayabilmeniz için onları kullanmanız gerekir, 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.

Genel Amaçlı Kaydediciler

Bu kaydedicilerin 8,16 ve 32 bitlik kullanımı mümkündür. Örneğin AL ve AH Accumulator’ün 8 bitlik kullanımını AX 16 bitlik EAX ise 32 bitlik kullanımını simgeler. Genel amaçlı kaydedicilerin hepsi verileri geçici olarak üzerlerinde barındırabilir fakat bazı x86 komutları buradaki kaydedicilere özeldir. Mesela loop komutu ile CX kaydedicisinin değeri azalır.

Accumulator (EAX, AX, AH, AL): En sık kullanacağınız kaydedicidir. Çok genel kullanım alanına sahiptir, daha önceki makalelerimizde yazdığımız kodlara bakarsanız çok değişik amaçlarla kullanıldığını görebilirsiniz. Bu kaydedici birçok giriş/çıkış işleminde ve aritmetik işlemlerde (çarpma, bölme ve taşıma gibi) kullanılır. Ayrıca bazı komutlar işlenmeden önce accumulator’den parametre alır veya bu kaydediciye işlemin sonucunu kaydeder.

Base (EBX, BX, BH, BL): Accumulator gibi genel amaçlı ve hafıza erişiminde indexleri göstermede kullanılır. Bir başka kullanım alanıda hesaplamalardır.

Counter (ECX, CX, CH, CL): Özel amaçlar ve hesaplamalarda kullanılacağı gibi genellikle bu kaydediciyi sayıcı olarak kullanılır, daha önce loop komutunun CX kaydedicisini otomatik olarak değiştirdiğini söylemiştik.

Data (EDX, DX, DH, DL): Bazı giriş/çıkış komutlarında bu kaydedicinin kullanılması gerekir, ayrıca çarpma ve bölme işlemlerinde accumulator ile birlikte büyük sonuçları bu kaydediciden okuruz.

Segment Kaydedicileri

Segment kaydedicilerinin hepsi 16 bitliktir ve hafızanın segment olarak adlandırılan kısımlarını adreslemede kullanılır.

Code Segment Kaydedicisi (CS): DOS işletim sisteminde programları oluşturan kodlar code segment’e yüklenir. CS kaydedicisi ise IP kaydedicisi ile birlikte programın çalışma sürecinde, programın oluşturan kodların adreslerini gösterirler.

Data Segment Kaydedicisi (DS): .exe türündeki bir programda kullanılacak olan veriler data segment denilen hafıza bölümünde tutulur. DS kaydedicisi ise bu bölgedeki verilerin konumlarını gösterir.

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.

Extra Segment Kaydedicisi (ES): Bazı string işlemlerinde DI kaydedicisi ile birlikte karakterlerin bulunduğu hafıza adreslerini tutarlar.

FS ve GS Kaydedicileri: 80386 ve sonrası CPU’larda bulunurlar ve diğer segment kaydedicilerinin yetersiz kaldığı durumlarda kullanılırlar.

Özel kaydediciler

IP ve EIP kaydedicileri: IP 16 bitlik DOS programlarının EIP ise 32 bitlik programların işlenmesi sürecinde, işlenecek olan bir sonraki komutun offset adresini gösterir.

FLAG ve EFLAG kaydedicileri: Flag kaydedicisi 16 Eflag kaydedicisi ise 32 bitten oluşur. Bildiğiniz gibi mikroişlemci matematiksel işlem yapar, bu kaydedicilerde her işlemden sonra o işleme özel sonuçları gösterirler. İşlemci durum kaydedicisi olarakta bilinen bu kaydediciler sonucun sıfır, pozitif veya negatif olduğunu veya işlemin sonucunda elde üretilip üretilmediği gibi birçok önemli veriyi bitsel olarak programcıya bildirirler.

Index Kaydedicileri

Bu kaydedicilerin E ile başlayanlar 32 bitlik programlarda, diğerleride 16 bitlik programlarda kullanılır. Hepsi de verilerin offset adreslerini tutmada kullanılır. SP ve BP, SS kaydedicisi ile birlikte SI ve DI, DS ve ES kaydedicileri ile birlikte hafıza adreslerine erişmek için kullanılır.

Burada açıklamadığım diğer kaydediciler: X86 ailesindeki işlemcilerde başka kaydedicilerde mevcuttur. Bunlardan bazılarını programcı kullanamaz bazıları ise ayrıcalıklı mod, 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.

İşlemciyi kısaca anlatmaya çalıştım, sıra hafızada.

HAFIZA

Şimdi hafızanın fiziksel ve mantıksal yapısını anlatacağım, 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. Çok karışık bir konu olmasına karşın basit bir anlatımla bu konuyu kavramanızı umuyorum.

Hafızanın Fiziksel Yapısı

resim 4


Şekil 4 - Hafızanı fiziksel yapısı.

Yukarıdaki gibi bir hafıza yapısı, 16 bitlik bir veri yolu bulunan işlemciler için uygundur, örneğin 8086 işlemcisi için. Şayet veri yolu 32 bitlik ise daha fazla bank gerekir, özetle data bus’ın (veri yolu) genişliği kullanılacak olan hafıza chip’ini belirler. Hafıza denilince boyutu 8 bit olan bir dizi hücre ve bu hücrelerin numarası olan adresler akla gelir. Hafıza chip’leri veri, adres ve kontrol yollarına bağlıdır. Hafızada bulunan veriler hexadecimal formatta gösterilirler, bu binary formata en uygun sayı sistemidir.

x86 hafızası ne kadar byte olarak adreslense de programcı hafızadan tek bir komut ile 8, 16 veya 32 bitlik bir değer işleyebilir. Böyle bir durumda hafızanın fiziksel yapısını bilmek işe yarayabilir. Örneğin 0. adresten itibaren 16 bitlik (2 byte veya word) bir değerin işlemci kaydedicilerine herhangi bir işlem için çekileceğini varsayalım. X86 ailesi işlemciler, hafızadan verileri düşük değerlikli kısmından itibaren okurlar (little endian). Bu örnekte hafızaya erişim çift numaralı adresten yapıldığı için ABFFh verisi data bus’a doğru bir şekilde yerleşecektir ve en hızlı hafıza erişimi bu şekilde yapılır. Birde tek numaralı bir adresten örneğin 7. adresten okuma yapıldığını varsayalım. 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, bu tür bir hafıza erişimi daha uzun zaman alır. Özetle çift numaralı adreslerden 1 byte’tan fazla bir değere erişilirse buna sıralı erişim (Aligned Memory Access), tek numaralı adreslerden okuma yapılırsa buna sırasız hafıza erişimi (Unaligned Memory Access) denir. Sıralı hafıza erişimi sırasızdan 2 kat daha hızlı olduğundan programlamada buna dikkat edilmelidir. Bu tür ayarlamalar assembly dilinde direktiflerle yapılır.

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. Adres yolu 16 bit olan bir mikroişlemci 216 yani 65536 adet hafıza konumuna erişebilir. 8086 işlemcisi 20 bitlik bir adres yoluna sahiptir ve adresleyebileceği alan 220=1048576 yani 1 MB. a denk gelir. 80286 işlemcisinin adres yolu 24 bitlik’ti ve 224= 16777216 hücreyi, başka bir deyişle 16MB. lık bir hafıza alanını adresleyebilirdir. Günümüzde kullanılan mikroişlemcilerin adres yolu çoğunlukla 32 bitliktir, buda 4 Milyar küsür hafıza konumuna denk gelir. Yavaş yavaş 64 bit devri başlıyor, 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. 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. Hafıza organizasyonuna yapılan bu yaklaşıma hafızanın mantıksal yapısı diyebiliriz.

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. X86 uyumlu tüm PC’ler Real Mod denilen çalışma modunda açılırlar, daha sonra işletim sistemine göre hafıza farklı bir şekil alabilir. Örneğin Linux yada Windows işletim sistemi yükleniyorsa hafıza Protected Mod (korumalı mod) denilen yapıya bürünür. DOS işletim sistemi yükleniyorsa hafıza real mod’da kalır. Birde korumalı mod altında DOS programlarını çalıştırmak ve korumalı mod ile real mod programları arasında geçiş yapmak için windows işletim sisteminin Virtual Protected Mod’u vardır. 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. Ş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.

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. Bu durumda hafızanın tamamı bir kitap, segmentler sayfalar ve adreslenebilen her byte ise satır olara düşünülebilir. Protected mod çok daha karmaşıktır. 80286 ve sonrası işlemciler  protected mod’a geçiş yapabilir. Sayfalama (paging), sanal bellek (virtual memory) ve multitasking (çok görevlilik) korumalı modun getirdiği büyük avantajlardır.

Mikroişlemci hafızanın herhangi bir konumuna erişirken segment adresini segment kaydedicilerinden, offset adresini de şayet erişilecek olan bir komut kodu ise IP kaydedicisinden alır. Erişilecek olan veri (değişken, karakter vs.) ise verinin türüne göre offset adresini tutacak olan kaydedici değişir, örneğin erişilecek veri stack’ta (yığın bellekte diyebilirsiniz) ise buradaki verinin offset adresini SP (stack pointer) tutar.

Segment kaydedicileri 16 bitliktir, real mod’da offset adresleri index kaydedicilerinin 16 bitlik kısımlarında (SP,BP,SI,DI) veya 16 bitlik olan IP kaydedicisinde tutulur. Bu durum xxxx:xxxx formatında gösterilir. Örneğin 3456:76A3 real modda bir hafıza adresini gösterir, burada 3456 segment adresi iken 76A3 ofset adresidir. 3456:76A3 gibi bir adres gösteriminde 3456’yı sayfa numarası olarak düşünürsek bu sayfada 0000-FFFF arasında 65536 adet offset adresi (satır) mevcuttur diyebiliriz ve bu konumların her biri 1 byte’a denk gelir.

Hafızanın gerçek yapısını göz önüne alırsak örneğin 8086 işlemcisi en fazla 1MB. 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.


resim 5

Şekil 5 - Programcı hafızayı adresleri olan byte tablosu olarak düşünür

Real mod’da gerçek adres şu formülle bulunur;

045F:0032 adresi için, 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, sonra buna offset adresi eklenir ve gerçek adres bulunur. 045F0h+0032h=04622h gerçek hafıza adresidir.

Gerçek modda bilgisayarınız Pentium 4 bile olsa hafızanın sadece 1MB. lık alanını adresleyebilirsiniz, ayrıca sadece kaydedicilerin 16 bitlik kısımlarını kullanabilirsiniz. Bu son model ferrari’nizi otobanda 1. viteste sürmeye benzer.

Şimdi’de hafıza ve kaydedicileri daha iyi anlamak için örnek program hazırlayalım.

TITLE Kaydediciler ve Hafıza (regmem.asm)
;########################################
;# Bu program hafızadaki 2 adet byte’ı toplar ve sonucu     #
;# tekrar hafızaya kaydeder.                                         #
;# Son Güncelleme: 05/03/05                                        #
;# Yazan --> Eren ERENER                                            #
;########################################

            .MODEL     SMALL
            .STACK     32
            .DATA

               Sayi1      DB     5
               Sayi2      DB     6
               Sonuc     DB     ?

            .CODE

             ANA       PROC

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

             MOV      AL, Sayi1            ;AL’ye 5 değeri yüklendi.
             ADD       AL, Sayi2            ;AL’deki 5 ile 6 toplandı sonuç tekrar AL’de.
             MOV      Sonuc, AL           ;toplama işlemini sonucu hafızaya yüklendi.

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

             ANA       ENDP

                         END  ANA
 

Bir programın çalışma süreci genel olarak şöyledir, program önce hafızaya yüklenir ve mikroişlemci ilk komuttan itibaren programı satır-satır icra etmeye başlar. Bu program hafızaya yüklenirken hafızada mantıksal olarak 3 tane segment oluşturacak 1.si 32 byte’lık stack segment bölgesi 2.’si 3 byte’lık data segment bölgesi ve 3.sü kodlarımın kapladığı alan kadar code segment bölgesi. İşlemci kaydedicileride programın yüklenme sürecinde ilk değerlerini alırlar. Ö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.

EkleBunu Sosyal Paylaşım Butonu

Yorum yaz! :: Arkadaşına Gönder!

0 yorum yazılmıştır

« Önceki :: Sonraki »

Reklamlar