MSP430 Dersleri 6 – Bellek İşlemleri

Merhaba Arkadaşlar,
Bu yazımızda verilerin bellek bölgesinde nasıl saklandığı ve bellekte işlemler gerçekleştirirken nelere dikkat etmemiz gerektiği konularına değineceğiz. Birkaç tane püf noktası içerdiğinden dolayı bu yazıyı dikkatli okumanızı tavsiye ederim.

Bildiğiniz gibi bellek bölgeleri çeşitli amaçlar için ayrılmıştır. Bizi ilgilendiren kısımlar Flash ve RAM bölümleridir. Daha önce bahsettiğim gibi Flash bellekte yazdığımız programın kodları ikili olarak saklanır (inanmıyorsanız biraz sabırlı olun göstereceğim 🙂 ) ve program koştuğu sırada bu belleğe yazma işlemi yapılamaz. RAM bölümüne ise program çalıştığı sırada okuma ve yazma yapabiliyoruz. Bu nedenle yaptığımız işlemlerin sonuçlarını veya saklamak istediğimiz veriler belleğin bu bölümüne kaydediyoruz.

Şimdi yazdığımız kodların Flash bölümüne ikili olarak saklandığını kontrol edelim bakalım gerçekten öyle mi? Basit bir program yazalım ve bellek bölgesini gözlemleyelim. Şekil 1’de hiç bir iş yapmayan program yer almaktadır. 🙂

Şekil 1. Bellek bölgesi incelemesi

Programımıza baktığımızda “org” komutu ile kodların bellekte 0f800h adresine yazıldığı görülmektedir. Bunun gerçekten böyle olup olmadığını görme şansımız var. View menüsünden Memory>Memory 1 yolunu izleyerek bütün bellek bölgesini görebiliyoruz. Bu açılan bölümden 0f800h adresine baktığımızda diğer adres bölümlerinde “00” değeri olmasına rağmen bu adreste farklı sayılar bulunmaktadır. İşte bu sayılar yazdığımız programın işlemcimizin anlayacağı dile dönüştürülmüş halidir. Bir adres 8 bit veri saklayabildiğinden dolayı bu bölümde veriler hexadecimal formatında gösterilmektedir. O zaman yazdığımız programın boyutunu hesaplayalım. Bilindiği gibi 8 bit 1 byte dır. Baktığımızda 12 adet adres bölgesinde sayı bulunmaktadır. Yani hiç bir iş yapmayan bir programımız bile 12 byte yer kaplamaktadır. 🙂 Bundan sonra yazdığınız programları işlemcinizde nasıl sakladığını merak ederseniz bakacağınız yeri biliyorsunuz.

Şimdi gelelim birkaç program ile RAM bölgesi işlemlerine. İlk olarak basitten başlayalım. Bilindiği gibi bir bellekte saklayabildiğimiz veri 8 bittir. Ama bu 16 bitlik veya 32 bitlik işlem yapamayacağımız anlamına gelmiyor. Bellekte yan yana olan iki adrese 16 bitlik sayıyı yazarak 16 bitlik sayılarla veya daha fazla adresi yan yana kullanarak daha yüksek bitlik sayılarla da işlemler gerçekleştirebiliriz. Örnek olarak iki adet 32 bitlik sayıyı toplayıp bellekte belirli bir adrese yazan bir programı inceleyelim.

#include "msp430.h"

       org   0f800h
reset  mov.w #0280h,SP
       mov.w #WDTPW+WDTHOLD,&WDTCTL
       clr   R6
       clr   R7
 
       mov   &0202h,R6
       mov   &0206h,R7
       add   R6,R7
       mov   R7,&020ah
       mov   &0200h,R6
       mov   &0204h,R7
       addc  R6,R7
       mov   R7,&0208h 
aa     jmp   aa
 
       org   0fffeh
       dw    reset
       end

Bu programın nasıl çalıştığını anlatmayacağım programı çalıştırarak nelerin olduğunu anlayacağınızı umuyorum. (ipucu 0200h, 0204h ve 0208h adreslerine dikkat 🙂 )

Ufak bir not, “addc” komutu önceki yapılan işlemde oluşan eldeyi dikkate alarak toplama yapan komuttur. Yani addc R6,R7 komutu ile R7 = R6 + R7 + “elde” işlemi yapılmış olur.

Pratik olması açısından 8 tane 16 bitlik sayının ortalamasını alan bir programı inceleyelim. Bu program gerçekten çok önemli dikkatli olmanızı öneririm.

#include "msp430.h"

         org   0f800h
reset    mov   #0280h,SP
         mow   #WDTPW+WDTHOLD,&WDTCTL 
         call  #ortalama
loop     jmp   loop

ortalama 
         clr   R5
         clr   R6
         clr   R7
 
aa       add   0200h(R5),R6
         adc   R7
         incd  R5
         mov   #010h,R4
         cmp   R4,R5
         jnz   aa     ; R5-R4 sonucu 0 degil ise ziplar
 
         rrc   R7
         rrc   R6
         rrc   R7
         rrc   R6
         rrc   R7
         rrc   R6
         ret
 
         org   0fffeh
         dw    reset
         end

Bu programda ortalama adında bir alt program oluşturularak bütün işlemler burada yaptırılmış. Ana programın karmaşıklığının azaltılması açısından alt programlar oldukça kullanışlıdır.

Şimdi gelelim önemli kısımlara. Öncelikle add 0200h(R5),R6 komutunun ne yaptığını inceleyelim. Buna indeksli adresleme denilmektedir (bizim için isminden çok işlevi önemli). Bu komut sonunda RAM bölgesinin 0200h+”R5″ adresindeki veri R6 kaydedicisine eklenecek. Görüldüğü gibi alt programa girdiğimizde R5, R6 ve R7 yi sıfırladık yani sonuç olarak R6 kaydedicisinde 0200h adresindeki veri saklanmış oldu.

Peki neden böyle yaptık! Bunun cevabı programın devamında gizli. Programın devamında bir döngü oluşturuluyor ve R5 kaydedicisi ikişer ikişer arttırılıyor (çünkü 16 bitlik toplama yapıyoruz). Böylelikle 200h, 202h, 204h … adreslerindeki sayılar toplanarak sonuç R6 kaydedicisinde saklanıyor. Her şey güzel ama R6 kaydedicisi 16 bitlik bir kaydedici 8 tane 16 bitlik sayı bu kaydediciye sığmayacaktır. Bu nedenle adc R7 komutu ile elde oluşması durumunda eldeler bu kaydediciye ekleniyor. Döngüden çıkmak için R5 kaydedicisi 10h (dikkat 10h = 16) sayısı ile karşılaştırılıyor ve döngü tamamlanıyor.

16 bitlik 8 adet sayının toplamının R6 kaydedicisine sığmayacağını söyledik. Şimdi bu taşma durumunu inceleyelim. Aşağıdaki formül yardımıyla toplama işlemi sonucunda en fazla kaç bit taşma oluşacağı hesaplanabilmektedir.

n=log_{2}k

Burada k toplanan sayı miktarını, n ise toplama sonucundaki oluşabilecek taşma biti sayısını temsil etmektedir. Örneğin programımızda 8 tane 16 bitlik sayıyı topladık. Bu durumda k yerine 8 yazdığımızda n=3 sonucunu elde ediyoruz. Yani en fazla 3 bit taşma olabilir ve bunun sonucunda toplam sayımız 19 bit olabilir. İşte bu nedenle toplam sayımız 16 bitlik R6 kaydedicisine sığmayacağı için R7 kaydedicisine de ihtiyacımız olmaktadır.

Programın devamında bir sürü “rrc” komutu görüyoruz. Bu komutlar ortalama almamız için gerekli olan bölme işlemini gerçekleştirmektedir. Bu bölme işlemine bir sonraki yazıda detaylı olarak değineceğim ancak kısaca bahsedecek olursak. İkili tabanda bir sayıyı 2’ye bölmek istersek basitçe sayının en soldaki basamağını silmemiz yeterlidir. “rrc” komutu kaydedicinin bitlerini bir basamak sola kaydırıp en sağdaki bite ise SR’deki elde bitini eklemektedir. Bizim sayımız iki farklı kaydedicide olduğundan dolayı önce R7 kaydedicisini daha sonra ise R6 kaydedicisini kaydırmamız ve 8’e bölmek için de bu kaydırma işlemini 3 defa yapmamız gerekmektedir. Şekil 2’de görsel olarak R6 ve R7 kaydedicilerinin “rrc” komutlarından önceki ve sonraki durumları görülmektedir.

Şekil 2. “rrc” komutları ile bölme işlemi

Böylelikle bir yazının daha sonuna gelmiş bulunmaktayız. Biraz uzun bir yazı oldu ancak işlemcide yapılan hesaplamalar açısından oldukça önemli olduğunu tekrar belirtmeliyim. Bir sonraki yazıda çarpma ve bölme işlemlerini nasıl yapacağımıza değineceğiz. O zamana kadar kendinize iyi bakın efendim. 🙂

“MSP430 Dersleri 6 – Bellek İşlemleri” için 2 yanıt

  1. Hocam merhabalar tekrardan,
    Kodlarınızı iar programında yazıp debug ettiğimde daha önce yazdığım çalışan programlardan birini açıp onu çalıştırıyor. Sizin yazdığınız kodları çalıştıramadım bu durumda. Nerede hata yapıyorum acaba?

    1. Ben daha önce böyle bir problemle karşılaşmamıştım ama her program için yeni proje oluşturman muhtemelen sorunu çözecektir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir