Bilgisayarlar eşyaları nerede depoladıklarını nasıl hatırlar?


32

Bir bilgisayar bir değişkeni sakladığında, bir program değişkenin değerini alması gerektiğinde, bilgisayar bu değişkenin değeri için bellekte nereye bakacağını nasıl bilir?


17
Öyle değil; "bilgisayar" tamamen habersiz. Tüm adresleri kodlamamız gerekiyor. (Bu biraz basitleştiriyor ama çok fazla değil.)
Raphael

1
@Raphael: Bunu, "temel adresleri sabitlemek zorundayız" olarak genelleştirelim.
phresnel

Ne zaman bir değişken bildirirseniz, kodunuzu çalıştırmaktan sorumlu olan program bir adres tablosunda adresli değişken ismi (aka isim alanı) içerir. "Bilgisayar Programlarının Yapısı ve Uygulanması (SICP) adlı kitabın, bu kadar küçük detaylarla yakından tanışması için
okunmasını tavsiye ederim

Kaynak programınız bir değişken kullanır. Derleyici veya tercüman nasıl uygulanacağına karar verir: bilgisayarın çalışması için talimatlar oluşturur ve bu talimatların önceki talimatların saklandığı yerlerden değerler aldığından emin olmalıdır.
PJTraill

1
@AbhirathMahipal: Bir değişkenin derleme zamanında veya hatta çalışma zamanında bir adresi olması gerekmez; “Ad alanı” bir dil kavramıdır; bir tablo (karma veya başka şekilde) bir uygulama detayıdır; Çalıştırıldığında isim ihtiyacı nod programda devam eder.
PJTraill

Yanıtlar:


31

Derleyici İnşaat'ın harika dünyasına bakmanızı öneririm! Cevap, bunun biraz karmaşık bir süreç olduğudur.

Size bir sezgi vermeye çalışmak için, değişken adlarının yalnızca programcının hatırı için orada olduklarını unutmayın. Bilgisayar sonuçta sonunda her şeyi adrese dönüştürecek.

Yerel değişkenler (genellikle) yığında depolanır: başka bir deyişle, bir işlev çağrısını temsil eden veri yapısının bir parçasıdır. Bir işlevin (belki) kullanacağı değişkenlerin tam listesini o işleve bakarak belirleyebiliriz, böylece derleyici bu işlev için kaç değişkene ihtiyaç duyduğunu ve her değişkenin ne kadar yer kapladığını görebilir.

Stack pointer olarak adlandırılan ve her zaman geçerli yığının başladığı yerin adresini saklayan bir kayıt defteri olan bir miktar sihir var.

Her değişkene, yığında depolandığı "yığın ofseti" verilir. Ardından, program erişimi için bir değişken gerektiğinde x, derleyici cümledeki xileSTACK_POINTER + x_offset bellekte depolanır gerçek fiziksel yer almak.

Unutmayın, bu yüzden kullandığınızda bir işaretçi geri alırsınız mallocveyanew , C veya C ++ . Tam olarak bellekte bir yığın tahsis edilmiş değerin nerede olduğunu belirleyemezsiniz, bu yüzden bir gösterici bulundurmanız gerekir. Bu işaretçi yığının üzerinde olacak, fakat yığına işaret edecek.

İşlev çağrıları ve iadeleri için güncelleme yığınlarının ayrıntıları karmaşıktır, bu yüzden ilgilenirseniz Dragon Kitabını veya Kaplan Kitabını tavsiye ederim .


24

Bir bilgisayar bir değişkeni sakladığında, bir program değişkenin değerini alması gerektiğinde, bilgisayar bu değişkenin değeri için bellekte nereye bakacağını nasıl bilir?

Program anlatıyor. Bilgisayarların yerel olarak “değişkenler” kavramı yoktur - bu tamamen üst düzey bir dildir!

İşte bir C programı:

int main(void)
{
    int a = 1;
    return a + 3;
}

ve işte derleyeceği derleme kodu: (şununla başlayan yorumlar ;)

main:
    ; {
    pushq   %rbp
    movq    %rsp, %rbp

    ; int a = 1
    movl    $1, -4(%rbp)

    ; return a + 3
    movl    -4(%rbp), %eax
    addl    $3, %eax

    ; }
    popq    %rbp
    ret

"İnt a = 1;" CPU, "1 değerini adreste sakla (rbp yazmacının değeri, eksi 4)" talimatını görür. Program bunu söylediği için 1 değerini nereye kaydedeceğini bilir.

Benzer şekilde, bir sonraki talimat "değeri adrese (rbp registerı eksi 4) register eax'e yükle" diyor. Bilgisayarın değişkenler gibi şeyleri bilmesi gerekmez.


2
Bunu jmite'nin cevabına bağlamak %rspiçin CPU'nun yığın göstericisidir. %rbpgeçerli işlev tarafından kullanılan yığının bitini ifade eden bir kayıttır. İki yazmaç kullanmak hata ayıklamayı kolaylaştırır.
MSalters

2

Derleyici veya yorumlayıcı bir değişkenin bildirimi ile karşılaştığında, bu değişkeni saklamak için hangi adresi kullanacağına karar verir ve ardından adresi bir sembol tablosuna kaydeder. Daha sonra bu değişkene yapılan referanslarla karşılaşıldığında, sembol tablosundaki adres değiştirilir.

Sembol tablosuna kaydedilen adres, bir kayıt cihazından (yığın işaretçisi gibi) mahsup olabilir, ancak bu bir uygulama detayıdır.


0

Kesin yöntemler, ne hakkında konuştuğunuza ve ne kadar derine gitmek istediğinize bağlıdır. Örneğin, dosyaları sabit sürücüde saklamak, bir şeyi bellekte saklamak veya bir şeyi veritabanında saklamaktan farklıdır. Her ne kadar kavramlar benzer olsa da. Ve bunu bir programlama seviyesinde nasıl yaptığınız, bilgisayarın I / O seviyesinde nasıl yaptığından farklı bir açıklamadır.

Çoğu sistem, bilgisayarın verileri bulmasına ve erişmesine izin vermek için bir tür dizin / dizin / kayıt mekanizması kullanır. Bu dizin / dizin bir veya daha fazla anahtar içerecek ve verinin gerçekte bulunduğu adres (sabit disk, RAM, veritabanı vb.).

Bilgisayar Programı Örneği

Bir bilgisayar programı, belleğe çeşitli şekillerde erişebilir. Tipik olarak, işletim sistemi programa bir adres alanı verir ve program bu adres alanı ile istediğini yapabilir. Bellek alanı içindeki herhangi bir adrese doğrudan yazabilir ve nasıl istediğini takip edebilir. Bu bazen programlama diline ve işletim sistemine, hatta bir programcının tercih ettiği tekniklere göre değişebilir.

Diğer cevapların bazılarında belirtildiği gibi, kullanılan tam kodlama veya programlama farklıdır, ancak genellikle sahne arkasında bir yığın gibi bir şey kullanır. Geçerli yığının başladığı bellek konumunu depolayan bir kayıt defterine ve daha sonra bu yığında bir işlev veya değişkenin nerede olduğunu bilme yöntemine sahiptir.

Birçok yüksek seviye programlama dilinde, sizin için herşeyi halleder. Tek yapmanız gereken bir değişken bildirmek ve bir değişkeni bu değişkende saklamak ve sizin için perdenin arkasında gerekli yığınları ve dizileri yaratır.

Ancak, ne kadar çok yönlü programlama yapıldığına bakıldığında, gerçekten bir cevap yoktur, çünkü bir programcı, herhangi bir zamanda (kendisine izin veren bir programlama dili kullandığını varsayarsak) tahsis edilen alanı içindeki herhangi bir adrese doğrudan yazmayı seçebilir. Ardından konumunu bir dizide saklayabilir, hatta programa kod yazması bile zor olabilir (yani, "alfa" değişkeni her zaman yığının başında veya her zaman ayrılan belleğin ilk 32 bitinde saklanır).

özet

Dolayısıyla, temel olarak, bilgisayara verilerin depolandığı yeri söyleyen sahnelerin arkasında bir mekanizma bulunmalıdır. En popüler yollardan biri, anahtar (lar) ve hafıza adresini içeren bir tür dizin / dizindir. Bu, her türlü şekilde uygulanır ve genellikle kullanıcıdan kapsüllenir (ve bazen programlayıcıdan kapsüllenir).

Referans: Bilgisayarlar eşyaları nerede depoladıklarını nasıl hatırlıyor?


0

Şablonlar ve formatlar nedeniyle biliyor.

Program / fonksiyon / bilgisayar aslında hiçbir şeyin nerede olduğunu bilmiyor. Sadece belli bir yerde bir şeyin olmasını bekliyor. Bir örnek kullanalım.

class simpleClass{
    public:
        int varA=58;
        int varB=73;
        simpleClass* nextObject=NULL;
};

Yeni sınıfımız 'simpleClass' 3 önemli değişken içerir - bunlara ihtiyacımız olduğunda bazı verileri içerebilen iki tamsayı ve başka bir 'simpleClass nesnesine bir işaretçi. Sadelik uğruna 32 bit bir makinede olduğumuzu varsayalım. 'gcc' veya başka bir 'C' derleyicisi bazı verileri tahsis etmek için çalışmamız için bir şablon hazırlar.

Basit Tipler

İlk olarak, bir 'int' gibi basit bir tür için bir anahtar kelime kullanıldığında, derleyici tarafından çalıştırılabilir dosyanın '.data' veya '.bss' bölümünde bir not alınır, böylece işletim sistemi tarafından çalıştırıldığında, veriler program için kullanılabilir. 'İnt' anahtar sözcüğü 4 bayt (32 bit), 'long int' 8 bayt (64 bit) tahsis eder.

Bazen, hücre bazında bir değişken, onu belleğe yüklemesi gereken komuttan hemen sonra gelebilir, bu yüzden sözde-montajda şöyle görünür:

...
clear register EAX
clear register EBX
load the immediate (next) value into EAX
5
copy the value in register EAX to register EBX
...

Bu, EAX'in yanı sıra EBX'teki '5' değeriyle bitecekti.

Program yürütülürken, derhal yüklendiğinden beri '5' hariç her komut çalıştırılır. referans verdiğinden ve CPU'nun atlamasını sağladığından .

Bu yöntemin dezavantajı, yalnızca sabitler için gerçekten pratik olmasıdır, çünkü dizilerin / tamponların / dizelerin kodunuzun ortasında tutulması pratik değildir. Genelde çoğu değişken program başlıklarında tutulur.

Biri bu dinamik değişkenlerden birine erişmesi gerekiyorsa, o zaman ani değere bir işaretçi gibi davranabilir:

...
clear register EAX
clear register EBX
load the immediate value into EAX
0x0AF2CE66 (Let's say this is the address of a cell containing '5')
load the value pointed to by EAX into EBX
...

Bu, EAX sicilindeki '0x0AF2CE66' değeri ve EBX sicilindeki '5' değeri ile bitecekti. Biri, kayıtlara birlikte değerler ekleyebilir, bu nedenle bu yöntemi kullanarak bir dizinin veya dizenin öğelerini bulabiliriz.

Bir başka önemli nokta, adresleri benzer bir şekilde kullanırken değerleri saklayabilmesi, böylece bu hücrelerde bulunan değerlere başvurabilmesidir.

Karmaşık Tipler

Bu sınıfın iki nesnesini yaparsak:

simpleClass newObjA;
simpleClass newObjB;

sonra ikinci nesneye, ilk nesnede bunun için mevcut alana işaretçi atayabiliriz:

newObjA.nextObject=&newObjB;

Şimdi program, birinci nesnenin işaretçi alanı içindeki ikinci nesnenin adresini bulmayı bekleyebilir. Hafızada, bu gibi bir şey olurdu:

newObjA:    58
            73
            &newObjB
            ...
newObjB:    58
            73
            NULL

Burada dikkat edilmesi gereken çok önemli bir gerçek şu ki, 'newObjA' ve 'newObjB' derlendiklerinde isimlerinin olmamasıdır. Onlar sadece bazı verilerin gelmesini beklediğimiz yerler. Dolayısıyla, & newObjA'ya 2 hücre eklersek, o zaman 'nextObject' olarak işlev gören hücreyi buluruz. Bu nedenle, 'newObjA' adresini ve 'nextObject' hücresinin buna göre nerede olduğunu biliyorsak, 'newObjB' adresini biliyoruz:

...
load the immediate value into EAX
&newObjA
add the immediate value to EAX
2
load the value in EAX into EBX

Bu, 'EAX' da '2 + & newObjA' ve 'EBX' de '& newObjB' ile bitecekti.

Şablonları / Biçimleri

Derleyici sınıf tanımını derlerken, gerçekten bir format yapmanın, forma yazmanın ve bir formattan okuma yapmanın bir yolunu derler.

Yukarıda verilen örnek, iki 'int' değişkenine sahip tek başına bağlı bir liste için bir şablondur. Bu tür yapılar, ikili ve n-ary ağaçlarıyla birlikte dinamik bellek ayırma için çok önemlidir. Bulutlu ağaçların pratik uygulamaları, dosyalara, dizinlere veya sürücüler / işletim sistemi tarafından tanınan diğer örneklere işaret eden dizinlerden oluşan dosya sistemleri olacaktır.

Tüm elemanlara erişmek için, yapının içinde ve üstünde bir inç çalışan solucanı düşünün. Bu şekilde, program / fonksiyon / bilgisayar hiçbir şey bilmez, sadece verileri dolaşmak için talimatlar uygular.


Burada kullanılan "şablon" ve "biçim" sözcükleri, şimdiye kadar gördüğüm hiçbir derleyici veya derleyici ders kitabında görünmüyor ve aynı olmayan şey için her iki sözcüğü kullanmak için hiçbir neden görünmüyor. Değişkenlerin adresleri ve / veya ofsetleri vardır, tek bilmeniz gereken şey budur.
user207421

Kelimeleri veri düzenleme için soyutlamalar yaptıkları için kullanıyorum, tıpkı sayılar, dosyalar, diziler ve değişkenler de soyutlamalar gibi.
Bay Minty Fresh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.