C Programlama diliyle şamatalar

Başlatan z, 23 Ekim 2011, 15:32:04

sayment

Hayır keilde denemedim.
Sorulardan ne anladıysam konu anlatımlarınız içerisinden cevap vermeye çalıştım. Cevap olarak yazdığım kodları anlayabiliyorum.
Hata mı yaptım ?

z

Gerbay

Hocam ne yaptin? C den sogutacagiz milleti.

Sayment sorun yok, sadece structure ile olan kisimda structure icerigini pointerin gosterdigi yere tasimissin. Ben bunu degil, structure'a pointer ile ulasmani istemistim.


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

EMG81

Alıntı yapılan: bunalmis - 22 Aralık 2011, 23:50:13
@EMG81

soyle oturakli islemcilerden birisi icin assembly biliyormusun. 

Hayır ne yazıkki bilmiyorum. Kısaca hayat hikayem şöyle;
6-7 yıl kadar 8 bit işlemciler ve asembly ile çalıştım. Assembly artık beni yormaya başlayınca bir ara Basic ile tanıştım ::) bu serüven birkaç ay kadar sürdü. Şimdi C ile çalışıyorum. Mutluyum :)

z

Hangi 8 bit islemcilerle index registeri olan bir islemci ile calistinmi?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

sayment

@gerbay
Hocam açıklama için teşekkür ederim fakat bu biraz üst düzey olmuş. Bilgi eksiği çok bende :(

@bunalmis
"Structure'a pointer ile ulaşmanı istemiştim." derken; Structure'nin içeriğine ulaşmamı istemediniz mi ?

z

Yok fark yok elbette de, burada anlatilmasi gereken konu yandaki yazim seklinde kirmizi renkli kisim. GPIOD->OSPEDR 
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

EMG81

Alıntı yapılan: bunalmis - 23 Aralık 2011, 00:07:52
Hangi 8 bit islemcilerle index registeri olan bir islemci ile calistinmi?

Pic ve ATmel ile çalıştım.

sayment

Alıntı yapılan: gerbay - 23 Aralık 2011, 00:11:54
arkadaşlar arka planda neler olduğunu göstermek için biraz detay gösterdim ama size bu karışık gelip gözünüzü korkutmasın.

sizin için tek bilmeniz gereken GPIO-D nin OutputSpeed registerına 0xFFFFFFFF değerinin atandığı bilgisi..
Bunu anladım hocam sağolun.

Alıntı yapılan: bunalmis - 23 Aralık 2011, 00:12:34
Yok fark yok elbette de, burada anlatilmasi gereken konu yandaki yazim seklinde kirmizi renkli kisim. GPIOD->OSPEDR 
Sormak istediğim tam olarak buydu.

sayment

Hocam pointer tam olarak ne iş yapar bunu tam kavrayamamışım okudukça kafam karışıyor.

z

Evet oncelikle pointer isleminin canina okumamiz gerekiyor  cunku pek cok kisi pointeri ezbere kullanmaya calisiyor.

Fakat -> icin ben de kisa bir aciklama yapacagim.

Keilde ornek bir proje olusturun. (Bunu ARM ogreniyoruz bolumunde Keil basliginda anlattik)

ardindan optimizasyon seviyesini 0 yapin. ve asagidaki kodlari main satirinin icine kopyalayin.
Derleyin ve debug moduna gecin. Memory window da adresi 0x20000000 e set edin.
Kodlari satir satir isletin ve her satir isletimi ardindan memory window da 0x20000000 den itibaren ilk bir kac degeri gozleyin.

void SystemInit()
{
}

typedef struct
{
   int x;
   short y;  
} MyStruct;           // MyStructure adinda structure tanimi yaptik

MyStruct A;           // A, MyStructure yapisinda olsun.

int main()
{

    MyStruct* Z;     // Z bir pointer olsun ve MyStructure tipindeki verilere ulasmaya yarasin
 
    A.x=1;           // A structurunda x elemanina 1 degerini yukle
    A.y=2;           // A structurunda y elemanina 2 degerini yukle 
   
    Z=&A;            // Z pointerimize A structure'inin adresini yukleyelim
    Z->x=3;          // Z pointerinin, point ettigi structure'in x elemanina 3 degerini yukle
    Z->y=4;          // Z pointerinin, point ettigi structure'in y elemanina 4 degerini yukle
     
    while(1);
}


Pointer icin sabah anlasilir bir yazi yazacagim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

sayment

Yani "adaminBiri" değişkenin içeri 0x12345678 adresinde tutuluyor diyelim. 

adaminBirineIsaretci = &adaminBiri;

Bu işlemden sonra "adaminBiriIsaretci" değişkeninin içeriği 0x12345678 mi oluyor ?

sayment

@gerbay
Teşekkür ederim hocam anladım. Ama bu aşamadan sonra bir kaç sorum daha olacak onları da yarın sorayım :)

@bunalmis
Hocam bu yazdıklarınızı sabah dinç kafa ile anlamaya çalışayım bende. Emeğiniz için teşekkür ederim.

z

Pointer hakkında

char A; //   1 Byte alan kaplayan bir değişken

A=1; gibi bir atamada yapılan işlem RAMda A için ayrılan 1 bytelık alana 0x01 verisini yerleştirmek demektir.

Bu işlem CPU tarafından şu şekilde yapılır.

Yukle32 Register1, A_Adres                     A nın adresini Register1 içine yükle
Yukle8   Register2, 1                              0x01 sayısal değerini Register2 içine yükle
Sakla8   Register2,[Register1]                  Register2 içeriğini Register1 içeriği olan adrese yerleştir.

Alt seviye bu işlemde Register1, Anın adresini saklamakta yani A registerini göstermekte yani A registerini point etmektedir.

Makine kodlarıyla C dilindeki A=1 atamasını yapmanın en sık kullanılan ve en yalın hali budur.

Örneğin

int A;

ardından A=1; gibi program parçacığı derlendiğinde derleyici derhal A nın adresi olan sayısal değeri belirler (diyelimki A nın adresi 0x20000000) ve

Yukle32   Register1, 0x20000000
Yukle8     Register2, 0x01         
Sakla8     Register2,[Register1]                   

program parçaçığını oluşturur.

Görüldüğü üzere burada derleyici, A değişkenine değer atılacağını bildiği için derhal A değişkeninin adresini daha derleme aşamasında hemen kodların arasına sıkıştırmıştır.

-------------------------------

Peki programımızda hangi değişkene değer atılacağını yazım aşamasında değilde  kodların işlenmesi aşamasında bildirmek istersek bu nasıl yapılır?

Örneğin A ve B adında 8 bitlik iki değişkenimiz olsun.

char A, B;

Bu durumda hangi değişkenle uğraşacaksak bu değişkenin adresini tutacak aracı bir değişkene (pointer) ihtiyaç duyarız.

bu aracı değişken char *P gibi tanımlanır.  Burada * pointerdan bahsedildiğini yani *P, P bir pointer demektir anlamına gelir.

char *P ise P nin 8 bitlik verilere ulaşmak için tanımlanmış bir pointer olduğunu söyler.

Her hangi bir değişkenin adresini bilirsek pointer ile bu değişkenin Ramda kapladığı alana ulaşabilir buraya istediğimiz veriyi yazabilir yada tersine okuyabiliriz.

Bir değişkenin adresini öğrenmek istediğimizde değişkenin hemen önüne & sembolü koyarız.

Bu durumda P=&A yazdığımızda Anın adresi P pointerine yazılmış olur. Şimdi bu adrese 0x01 değerini yerleştirmek istersek

       *P=0x01; dememiz yeterlidir.

tekrar edecek olursak;

        P=&A;    A değişkeninin adresini P ye yaz.
      *P=0x01;  P de saklı olan adresin gösterdiği yere 0x01 değerini yerleştir.

-----------------------------------------------------------------------------------------

8 bitlik A , 16 bitlik B, 32 bitlik C değişkenimiz olsun.

Bunların her birisine 1 sayısını yüklemek isteyelim.

char A;
short B;
int C;

char* PA;
short* PB;
int* PC;

             *PA=1;
             *PB=1;
             *PC=1;

Neden pointerleri char, short yada int tanımlama ihtiyacı duyuyoruz?

8 bitlik   1 sayısı  01
16 bitlik 1 sayısı  0001
32 bitlik 1 sayısı  00000001

Örneğin int pointerin gösterdiği adrese 1 sayısı yazılacaksa ramda bu adrese 0x00 takip eden bir sonrakine 0x00 bir sonrakine 0x00 bir sonrakine ise 0x01 yerleşir. (Aslında tam tersi)

Bu nedenle point edilecek değişken adresinin uzunluğunu pointer tanımında net şekilde belirleriz.

-----------------------------------------------------------------------------

Peki CPU pointer ile çalışırken nasıl kod işletir.

Örneğin aşağıdaki kod, yazımın en başında yazdığım koddan alıntıdır.

Yukle8   Register2, 1                              0x01 sayısal değerini Register2 içine yükle
Sakla8   Register2,[Register1]                  Register2 içeriğini Register1 içeriği olan adrese yerleştir.

Burada Register1 içine hangi 8 bitlik değişkenin adresi yazılırsa o değişkene 0x01 değeri yazılmış olur.

P=&A gibi bir C komutu, alt seviyede

Yukle32 Register1, A_Adres                   şeklinde makina kodlarına dönüşür.

-------------------------

P=&A ;
*P=0x01;

iki satırlık C kodu ise, makine dilinde aşağıdaki koda dönüşür. Bu da yazımızın en başındaki kırmızı kodların ta kendisidir.

Yukle32   Register1, 0x20000000        // P=&A ;
Yukle8     Register2, 0x01         
Sakla8     Register2,[Register1]                   

Yukarıdaki kodda derleyicinin  RAMda 0x20000000 adresini A değişkene reserve ettiğini görüyoruz.

Pointer sonuçta postacıdır. Postacıya bir paket ve bunun teslim edileceği adresi verirseniz, postacı paketi alıcısına teslim eder.

P=&Ahmet;   Postacı, Ahmetin adresi bu
*P=0x01;     0x01 i bu adrese teslim et.

Pointer kullanmasaydık

Ahmet=0x01    ; Ahmet bu 0x01 senin.

int    A;
short B;
char  C;
char  D;

int* P;

      A=0x02;
      P=&A;
      P++;
      *P=0x01;
       
Bu soruya kafa yorunuz. Sorum bu program ne yapar?

Bu soruyu çözen pointeri anladı demektir.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

sayment

      A=0x02;     // A değişkenine 2 sayısını yükle(A=2)
      P=&A;        // A değişkeninin adresini pointere kaydet
      P++;          // A değişkeninin içeriğini 1 arttır (A=3)
      *P=0x01;  // A değişkenine 1 sayısını yükle (A=1)


Doğru mudur ?

muhittin_kaplan

#194
Hocam Şurada Bir Yanlışınız mı var Benmi Yanlış Anlıyorum.
Yukle8   Register2, 1                              0x01 sayısal değerini Register2 içine yükle
Sakla8   Register2,[Register1]                  Register2 içeriğini Register1 içeriği olan adrese yerleştir.

Sakla8 Reg2,[Reg1]
burada Reg1 içeriğindeki bilgiyi Adress olarak kabul et ve o adrese giderek içeriği al ve Reg2 ye kaydet değilmidir. (Dolaylı adresleme)