PDA

Tam Sürümünü Görmek İçin : volatile


quasimodo
08/02/2007, 20:51
volatile : degiskenleri yazmaclarda degilde onlari bellekteki
asil yerlerinde tut anlami disinda bilmem gereken birseyi var mi?
Yani bir nevi register in tersi degilmi ?
register da degiskenleri daha hizli islem yapabilmek adina
CPU da degilde ram da tutuyor du ya...


myavuzselim
08/02/2007, 21:34
Evet, bildigim kadariyla volatile degiskenin her seferinde tekrar hafizadan okunmasini/hafizaya yazilmasini sagliyor. Derleyici degiskenin degismeyecegi gibi bir varsayimda bulunmuyor.

Mingitau
08/02/2007, 21:39
degisken cpu da ise daha hızlı işlem yapılır. Ram de ise daha yavaş zira transistor yapısı farklı ram ile işlemcinin.

acehreli
08/02/2007, 21:48
Etkileri birbirlerinin tersi olarak gozlemlenebilse de, register ile volatile birbirlerinin tersi degildirler. Aslinda volatile'in taniminda yazmac gibi gercekleme unsurlarindan da soz edilmez.

volatile: "Bu nesnenin degeri, dilin tanimladigi kurallar disinda degisebilir; onun icin eniyilestirmelerden kacin." (Eger bu eniyilestirmeler yazmacta tutmayi da iceriyorsa, evet, derleyici onu da yapmamalidir.)

auto: "Bu, otomatik bir nesnedir; o yuzden ancak otomatik nesne olarak kullanilabilir." (Derleyicinin otomatik olarak sonlandirdigi ve kod bloklarinda tanimlanmis nesneler gibi.) auto'nun kullanimi tamamen gereksizdir.

register: "Bu da bir auto nesnedir; ek olarak, cok erisildigi icin yazmacta tutulmasi iyi olabilir." Bunun yaninda, kendisine & isleci uygulanamaz. register tamamen bir "ricadir"; derleyici dikkate alip almamakta serbesttir. Derleyici register olarak tanimlanmayan nesneleri de yazmaclarda kullanabildigi icin, register da etkisiz bir anahtar sozcuk olarak kabul edilir. Bu yuzden register modern kodda kullanilmaz.

Ali

quasimodo
08/02/2007, 22:11
degisken cpu da ise daha hızlı işlem yapılır.
Ram de ise daha yavaş zira transistor yapısı
farklı ram ile işlemcinin.

Ben bunun tam tersini biliyorum. CPU da daha yavas
Ram de daha hizli. yaniliyormuyum ???

volatile: "Bu nesnenin degeri, dilin tanimladigi kurallar
disinda degisebilir; onun icin eniyilestirmelerden kacin."
(Eger bu eniyilestirmeler yazmacta tutmayi da iceriyorsa,
evet, derleyici onu da yapmamalidir.)

Ali hocam yazmac denilen ram dimi ben hep oyle anliyorum cunku ...

myavuzselim
08/02/2007, 23:10
Ben bunun tam tersini biliyorum. CPU da daha yavas
Ram de daha hizli. yaniliyormuyum ???
Islem CPU'nun kendisinde gerceklesiyor. Register'lar (yazmaclar) CPU'nun icindeki hizli, ama sinirli sayida hafiza hucreleri. CPU islemini direkt bu yazmaclar ustunden gorebiliyor.
RAM ise CPU'ya bagli ana hafiza. Yazmaclara gore cok daha yavas. CPU RAM'daki veri ustunde bir islem yapmak istedigi zaman once bunu okuyup bir yazmaca yazmak zorunda, ki sonra islemi yapsin (istisnalar olabilir, kaideyi bozmaz :)).



Ali hocam yazmac denilen ram dimi ben hep oyle anliyorum cunku ...
yazmac = register

acehreli
08/02/2007, 23:12
quasimodo, bir karisiklik var :) Butun islemler sonucta CPU'da yapildigi icin ve yazmaclar (register) da CPU'nun islemlerde kullandigi ic yapilari oldugu icin, en hizli islem yazmaclarda olur.

for ( /* ... */; ++i)

gibi bir islem icin normalde i
1) bellekte (RAM) bulundugu yerden bir yazmaca kopyalanir
2) o yazmacin degeri bir arttirilir
3) deger tekrar i'nin bulundugu yere yazilir.

Eger derleyici iyi olacagini dusunurse ve bu is icin ayirabilecegi bos bir yazmaci varsa, i icin bellekte yer ayirmaz ve yazmaclardan birisini i olarak kullanir. Boylece bellege erisim icin zaman harcanmamis olur.

register anahtar sozcugu derleyiciye bu konuda yardimci olmak icin kullanilir ama daha once de soyledigim gibi, hemen hemen hicbir etkisi yoktur: soylesek bile yazmac kullanilamayabilir (ornegin bos yazmac yoktur); soylemesek bile zaten derleyici olabiliyorsa yazmac kullaniyordur.

Ali

myavuzselim
08/02/2007, 23:50
volatile'in etkisini gormek icin su kodu deneyelim:

test_normal.c:

int test() {
int x = 0;
x += 13;
x += 25;
return x;
}

$ gcc -S -O3 test_normal.c

test_normal.s:

test:
pushl %ebp
movl $38, %eax
movl %esp, %ebp
popl %ebp
ret


test_volatile.c:

int test() {
volatile int x = 0;
x += 13;
x += 25;
return x;
}


$ gcc -S -O3 test_volatile.c

test_volatile.s:

test:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $0, -4(%ebp)
movl -4(%ebp), %eax
addl $13, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
addl $25, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
ret

quasimodo
09/02/2007, 00:08
myavuzselim bunlar 80X86 komutlari olmadigindan bir sey
anladigimdan bahsedemiyecegim.

Ama for(/*...*/; ++i) ornegi icin


1000:2000 | 00 | L 80X86 in yapisina gore yerlestirilmis
1000:2001 | 00 | H i degiskeni ...

mov AX, word ptr[2000]
inc AX
mov word ptr[2000], AX
anladigim kadariyla for dongusu bu sekilde gerceklersiyor.
Ve yine anladigim kadariyla AX, BX, CX, DX bunlar genel
yazmaclar ve islemler aslinda buralarda daha hizli
gerceklesiyor ama goruldugu gibi sinirli sayida ...

quasimodo
10/02/2007, 21:34
char * bir_isaretci;
int bir_sayi;

gibi degiskenleri tanimladigimda derleyici bunlari RAM
de mi ayiriyor yoksa CPU nun icidemi? yani ben

printf("%p\n", bir_isaretci);
printf("%p", &bir_sayi);

dediğide gösterilen adresler RAM in adresimi?

acehreli
10/02/2007, 22:03
Degiskenlerin normalde bellekte (RAM) ayrildiklarini dusunebiliriz.

Eger gosterdigin iki nesne bir islev tanimi gibi bir kod blogunda tanimli iseler, otomatik nesnedirler. Yani onlari biz degil, derleyici otomatik olarak sonlandirir. Butun derleyiciler de boyle otomatik nesneleri program yigitinda (program stack) tutarlar.

Ama yukarida da bahsedildigi gibi, derleyici bazi nesneleri kendi karariyla yazmaclardan birisinde de tutabilir. Hatta bir islev icinde belirli bir sure icin yazmacta tutabilir ve biraz sonraki islemler icin yazmacin artik gerektigini dusundugu icin onu tekrar bellege yazabilir. Bunlar dil standartlarinin deginmedigi konular oldugu icin, aklimiza gelen veya gelmeyen her sey olabilir. :)

Ancaaaak... :) Kuantum teorisindeki belirsizligin bir benzeri olarak, nesnenin adresini almak, onu yazmacta tutulamayacak hale getirir. Cunku yazmaclarin adresleri diye bir kavram yoktur. Yazmac adiyla anilir; adresiyle degil.

Iki printf satirina bakalim:

1) printf("%p\n", bir_isaretci);

bir_isaretci'nin degeri neyse, yani bir_isaretci hangi nesneyi gosteriyorsa, o nesnenin adresi yazilir. Daha once soyle bir satirin isletildigin varsayalim:

bir_isaretci = &bir_sayi;

Adresi alindigi icin, artik bir_sayi yazmacta tutulamaz. Normal bir sekilde bellekte bir yerdedir. Onun icin bir_isaretci'nin bellekte bir adresi tuttugunu soyleyebiliriz.

2) printf("%p", &bir_sayi);

Ayni sekilde, bir_sayi yazmacta bulunamadigi icin bellektedir ve o bellek adresi yazdirilmaktadir.

Ali

quasimodo
10/02/2007, 22:39
Degiskenlerin normalde bellekte
(RAM) ayrildiklarini dusunebiliriz.
Eger gosterdigin iki nesne bir islev tanimi gibi bir kod
blogunda tanimli iseler, otomatik nesnedirler. Yani onlari
biz degil, derleyici otomatik olarak sonlandirir.
Butun derleyiciler de boyle otomatik nesneleri
program yigitinda (program stack) tutarlar.


Peki bu program stack nerede bulunuyor? Sonucta oda RAM
de bulunmuyor mu?

#include <stdio.h>
#include <conio.h>

int main()
{
/*

Komutlar .....

*/
}

Biz busekilde bir program yazdigimizda programımızda
bulunan komutlar nerede saklaniyor ? Bir sonraki komut
CS:IP ciftiyle isaret ediliyor ama bu isaret ettigi yer
neresi ?

acehreli
10/02/2007, 23:34
Evet, program yigiti bellegin bir yerindedir. Yani evet, RAM'dedir. Aslinda islemcinin yigit yazmaci (stack pointer; biz SP diyelim.) nereyi gosteriyorsa, program yigiti oradadir.

Genellikle bellegin yuksek degerli bir adresinden baslar; yer gerektikce degeri azaltilir.

Programimizda bulunan komutlarin derlenmis halleri de bellegin bir yerinde dururlar. Calistigimiz ortamda kodlar nerede duruyorlarsa orada... Ornegin calisma zamaninda printf'in kodunun bulundugu adres 0x1000 ise ve kaynak kodumuzda

printf("merhaba");

yazmissak; derleyicinin olusturmus oldugu kod, su iki isi yapar:

1) "merhaba" sabit dizgisinin adresini yigita yerlestirir
2) IP yazmacina 0x1000 degerini yerlestirir

Boylece printf cagrilmis olur. Yani, IP'ye bir deger yazmak, bir islev cagrilmasini saglar.

Ali

ceeyt
10/02/2007, 23:35
[CODE]printf("%p\n", bir_isaretci);
printf("%p", &bir_sayi);

dediğide gösterilen adresler RAM in adresimi?


Eger bu program windows veya linux gibi bir platformda calisiyorsa ekranda gosterilen deger gercek adres degil.

Yukaridaki gibi isletim sisteleri islemciyi protected mode adi verilen bir durumda calistirirlar ve bu yuzden virtual memory ve physicall memory farkli anlamlara gelir.Daha fazla ayrinti icin korumali mod uzerine biraz arastirma yapabilirsn.

mikroislemciler dersinde gorduklerin temeli olustursa da su an kullandigin isletim sisteminde isleyiste baska bazi ayrintilar daha var.Dedigim gibi protected mode calismayi biraz arastirirsan daha iyi anlayacaksin.


Biz busekilde bir program yazdigimizda programımızda
bulunan komutlar nerede saklaniyor ? Bir sonraki komut
CS:IP ciftiyle isaret ediliyor ama bu isaret ettigi yer
neresi ?

sistem hafizasinda uygun bir yerler

quasimodo
11/02/2007, 03:14
bu yuzden virtual memory ve physicall memory
farkli anlamlara gelir.

Ben windows kullandigima gore gordugum adres hangisi?
virtual mu fiziksel adresmi ... Ikiside degil mi?

acehreli
11/02/2007, 21:53
Gordugun adres, bir nesnenin adresi. Senin programin o nesneyi o adreste goruyor. O adresin nerede oldugu C dilini ilgilendirmiyor. Ornegin o adres Internet uzerinden erisilen baska bir bilgisayarda bile olabilir. Saka yapmiyorum, gercekten oyle olabilir...

Bir isletim sistemi ortaminda belirli bir anda calisan her program kendilerine ait bir nesneyi ayni adreste gorebilirler. Ornegin A programinin a nesnesi 0x1000 adresindeyken B programinin b nesnesi de 0x1000 adresinde olabilir. Kendi acilarindan boyledir.

Tabii isletim sistemi gercek bellegin degisik yerlerini A'ya ve B'ye degisik sekilde gosteriyordur. Ornegin, A'nin 0x1000 dedigi aslinda isletim sisteminin gozunde 0x81000 adresi olabilir ve B'nin 0x1000 dedigi aslinda isletim sisteminin gozunde 0x91000 adresi olabilir. O adresler de isletim sisteminin kullandigi donanimin gozunde tamamen baska olabilirler: 0xB0001000 ve 0xC0001000 gibi...

Pratikte nasil oldugunu yanitliyorsak, gordugun adres virtual adres...

Ali