Bagaimana komputer mengingat di mana mereka menyimpan barang?

32

Ketika komputer menyimpan variabel, ketika suatu program perlu mendapatkan nilai variabel, bagaimana komputer tahu di mana harus mencari dalam memori untuk nilai variabel itu?

MCMastery
sumber
17
Tidak; "Komputer" sama sekali tidak disadari. Kami harus meng-hardcode semua alamat. (Yang sedikit menyederhanakan, tetapi tidak terlalu banyak.)
Raphael
1
@ Raphael: Mari kita menggeneralisasikannya ke "kita harus alamat basis hardcode"
phresnel
Setiap kali Anda mendeklarasikan variabel, program yang bertanggung jawab untuk menjalankan kode Anda menyertakan nama variabel dengan alamatnya dalam hashtable (alias namespace). Saya sarankan membaca buku "Struktur dan Implementasi Program Komputer (SICP) agar terbiasa dengan detail-detail kecil seperti itu.
Abhirath Mahipal
Program sumber Anda menggunakan variabel. Compiler atau interpreter memutuskan bagaimana mengimplementasikannya: ia menghasilkan instruksi untuk dieksekusi oleh komputer dan harus memastikan bahwa intruksi tersebut mengambil nilai dari tempat-tempat di mana instruksi sebelumnya menyimpannya.
PJTraill
1
@AbhirathMahipal: variabel tidak perlu memiliki alamat pada waktu kompilasi atau bahkan waktu berjalan; "Namespace" adalah konsep bahasa sementara tabel (hash atau sebaliknya) adalah detail implementasi; nama perlu anggukan tetap ada dalam program ketika dijalankan.
PJTraill

Jawaban:

31

Saya sarankan Anda melihat dunia Konstruksi Kompiler yang indah! Jawabannya adalah ini sedikit proses yang rumit.

Untuk mencoba memberi Anda intuisi, ingatlah bahwa nama variabel murni ada untuk kepentingan programmer. Komputer pada akhirnya akan mengubah segalanya menjadi alamat di bagian akhir.

Variabel lokal (umumnya) disimpan di stack: yaitu, mereka adalah bagian dari struktur data yang mewakili pemanggilan fungsi. Kita dapat menentukan daftar lengkap variabel yang akan digunakan suatu fungsi (mungkin) dengan melihat fungsi itu, sehingga kompiler dapat melihat berapa banyak variabel yang dibutuhkan untuk fungsi ini dan berapa banyak ruang yang dibutuhkan setiap variabel.

Ada sedikit keajaiban yang disebut stack pointer, yang merupakan register yang selalu menyimpan alamat di mana tumpukan saat ini dimulai.

Setiap variabel diberi "tumpukan offset", yang merupakan tempat dalam tumpukan itu disimpan. Kemudian, ketika program perlu mengakses variabel x, kompilator menggantikannya xdengan STACK_POINTER + x_offset, untuk mendapatkan tempat fisik sebenarnya yang disimpan dalam memori.

Perhatikan bahwa, inilah sebabnya Anda mendapatkan pointer kembali ketika Anda menggunakan mallocatau newdalam C atau C ++. Anda tidak dapat menentukan di mana tepatnya dalam memori nilai yang dialokasikan heap, jadi Anda harus menyimpan pointer ke sana. Pointer itu ada di stack, tetapi akan menunjuk ke heap.

Rincian memperbarui tumpukan untuk pemanggilan fungsi dan pengembalian adalah rumit, jadi saya akan merekomendasikan The Dragon Book atau The Tiger Book jika Anda tertarik.

Ya ampun
sumber
24

Ketika komputer menyimpan variabel, ketika suatu program perlu mendapatkan nilai variabel, bagaimana komputer tahu di mana harus mencari dalam memori untuk nilai variabel itu?

Program mengatakannya. Komputer tidak secara alami memiliki konsep "variabel" - itu sepenuhnya hal bahasa tingkat tinggi!

Inilah program C:

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

dan inilah kode perakitan yang dikompilasinya: (komentar dimulai dengan ;)

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

Untuk "int a = 1;" CPU melihat instruksi "menyimpan nilai 1 di alamat (nilai register rbp, minus 4)". Ia tahu di mana menyimpan nilai 1 karena program mengatakannya.

Demikian juga, instruksi selanjutnya mengatakan "memuat nilai di alamat (nilai register rbp, minus 4) ke register eax". Komputer tidak perlu tahu tentang hal-hal seperti variabel.

pengguna253751
sumber
2
Untuk menghubungkan ini ke jawaban jmite, %rspadalah penunjuk tumpukan CPU. %rbpadalah register yang mengacu pada sedikit tumpukan yang digunakan oleh fungsi saat ini. Menggunakan dua register menyederhanakan debugging.
MSalters
2

Ketika kompiler atau interpreter menemukan deklarasi variabel, ia memutuskan alamat apa yang akan digunakan untuk menyimpan variabel itu, dan kemudian mencatat alamat dalam tabel simbol. Ketika referensi selanjutnya untuk variabel itu ditemukan, alamat dari tabel simbol diganti.

Alamat yang direkam dalam tabel simbol mungkin merupakan offset dari register (seperti stack pointer) tapi itu detail implementasi.

Scott Cooper
sumber
0

Metode yang tepat tergantung pada apa yang Anda bicarakan dan seberapa dalam Anda ingin melangkah. Misalnya, menyimpan file pada hard drive berbeda dari menyimpan sesuatu di memori atau menyimpan sesuatu di database. Meski konsepnya mirip. Dan bagaimana Anda melakukannya pada level pemrograman adalah penjelasan yang berbeda dari bagaimana komputer melakukannya pada level I / O.

Sebagian besar sistem menggunakan semacam mekanisme direktori / indeks / registri untuk memungkinkan komputer menemukan dan mengakses data. Indeks / direktori ini akan berisi satu atau lebih kunci, dan alamat data sebenarnya terletak di (apakah itu hard drive, RAM, database, dll.).

Contoh Program Komputer

Program komputer dapat mengakses memori dengan berbagai cara. Biasanya sistem operasi memberi ruang alamat pada program, dan program dapat melakukan apa yang diinginkannya dengan ruang alamat tersebut. Ia dapat menulis secara langsung ke alamat apa pun di dalam ruang memorinya, dan ia dapat melacaknya seperti yang diinginkannya. Ini kadang-kadang akan berbeda menurut bahasa pemrograman dan sistem operasi, atau bahkan menurut teknik yang disukai programmer.

Seperti disebutkan dalam beberapa jawaban lain, pengkodean atau pemrograman yang digunakan berbeda, tetapi biasanya di balik layar ia menggunakan sesuatu seperti tumpukan. Ini memiliki register yang menyimpan lokasi memori di mana tumpukan saat ini dimulai, dan kemudian metode untuk mengetahui di mana di tumpukan itu fungsi atau variabel.

Dalam banyak bahasa pemrograman tingkat yang lebih tinggi, ini akan menangani semua itu untuk Anda. Yang harus Anda lakukan adalah mendeklarasikan variabel, dan menyimpan sesuatu di variabel itu, dan itu menciptakan tumpukan dan array yang diperlukan di belakang layar untuk Anda.

Tetapi mengingat betapa serbagunanya pemrograman, sebenarnya tidak ada satu jawaban, karena seorang programmer dapat memilih untuk menulis secara langsung ke alamat mana saja di dalam ruang yang dialokasikan kapan saja (dengan asumsi ia menggunakan bahasa pemrograman yang memungkinkan hal itu). Kemudian ia dapat menyimpan lokasinya dalam sebuah array, atau bahkan hanya kode keras ke dalam program (yaitu variabel "alpha" selalu disimpan di awal tumpukan atau selalu disimpan dalam 32 bit pertama memori yang dialokasikan).

Ringkasan

Jadi pada dasarnya, harus ada beberapa mekanisme di belakang layar yang memberitahu komputer di mana data disimpan. Salah satu cara yang paling populer adalah semacam indeks / direktori yang berisi kunci dan alamat memori. Ini diimplementasikan dalam segala macam cara dan biasanya dienkapsulasi dari pengguna (dan kadang-kadang bahkan dienkapsulasi dari programmer).

Referensi: Bagaimana komputer mengingat di mana mereka menyimpan barang?

Scott M. Stolz
sumber
0

Itu tahu karena template dan format.

Program / fungsi / komputer tidak benar-benar tahu di mana ada sesuatu. Itu hanya mengharapkan sesuatu berada di tempat tertentu. Mari kita gunakan sebuah contoh.

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

Kelas baru kami 'simpleClass' berisi 3 variabel penting - dua integer yang dapat berisi beberapa data saat kami membutuhkannya, dan sebuah penunjuk ke 'objek simpleClass' lainnya. Mari kita asumsikan bahwa kita menggunakan mesin 32-bit demi kesederhanaan. 'gcc' atau kompiler 'C' yang lain akan membuat templat yang dapat kita gunakan untuk mengalokasikan beberapa data.

Tipe Sederhana

Pertama, ketika seseorang menggunakan kata kunci untuk tipe sederhana seperti 'int', sebuah catatan dibuat oleh kompiler di bagian file yang dapat dieksekusi yaitu '.data' atau '.bss' sehingga ketika dijalankan oleh sistem operasi, datanya adalah tersedia untuk program ini. Kata kunci 'int' akan mengalokasikan 4 byte (32 bit), sedangkan 'int panjang' akan mengalokasikan 8 byte (64 bit).

Kadang-kadang, dengan cara sel demi sel, suatu variabel dapat muncul tepat setelah instruksi yang seharusnya memuatnya ke dalam memori, jadi itu akan terlihat seperti ini dalam pseudo-assembly:

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

Ini akan berakhir dengan nilai '5' di EAX dan juga EBX.

Ketika program dijalankan, setiap instruksi dijalankan kecuali untuk '5' karena memuat langsung referensi itu dan membuat CPU melewatinya.

Kelemahan dari metode ini adalah hanya benar-benar praktis untuk konstanta, karena tidak praktis untuk menyimpan array / buffer / string di tengah-tengah kode Anda. Jadi, secara umum, sebagian besar variabel disimpan di header program.

Jika seseorang perlu mengakses salah satu variabel dinamis ini, maka seseorang dapat memperlakukan nilai langsung seolah-olah itu adalah pointer:

...
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
...

Ini akan diakhiri dengan nilai '0x0AF2CE66' di register EAX dan nilai '5' di register EBX. Kita juga bisa menambahkan nilai dalam register bersama, jadi kita bisa menemukan elemen array atau string menggunakan metode ini.

Poin penting lainnya adalah bahwa seseorang dapat menyimpan nilai saat menggunakan alamat dengan cara yang sama, sehingga orang dapat merujuk nilai pada sel tersebut nanti.

Jenis yang kompleks

Jika kita membuat dua objek dari kelas ini:

simpleClass newObjA;
simpleClass newObjB;

lalu kita bisa menetapkan pointer ke objek kedua ke bidang yang tersedia untuknya di objek pertama:

newObjA.nextObject=&newObjB;

Sekarang program dapat berharap untuk menemukan alamat objek kedua dalam bidang pointer objek pertama. Dalam memori, ini akan terlihat seperti:

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

Satu fakta yang sangat penting untuk dicatat di sini adalah bahwa 'newObjA' dan 'newObjB' tidak memiliki nama saat dikompilasi. Itu hanya tempat di mana kami mengharapkan beberapa data berada. Jadi, jika kita menambahkan 2 sel ke & newObjA maka kita menemukan sel yang bertindak sebagai 'nextObject'. Oleh karena itu, jika kita mengetahui alamat 'newObjA' dan di mana sel 'nextObject' relatif terhadapnya, maka kita dapat mengetahui alamat 'newObjB':

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

Ini akan berakhir dengan '2 + & newObjA' di 'EAX' dan '& newObjB' di 'EBX'.

Templat / Format

Ketika kompiler mengkompilasi definisi kelas, itu benar-benar mengkompilasi cara untuk membuat format, cara menulis ke format, dan cara membaca dari format.

Contoh yang diberikan di atas adalah templat untuk daftar yang terhubung sendiri dengan dua variabel 'int'. Jenis konstruksi ini sangat penting untuk alokasi memori dinamis, bersama dengan pohon biner dan n-ary. Aplikasi praktis dari n-ary tree adalah sistem file yang terdiri dari direktori yang menunjuk ke file, direktori, atau instance lain yang dikenali oleh driver / sistem operasi.

Untuk mengakses semua elemen, pikirkan tentang inchworm yang bekerja dengan cara naik turun struktur. Dengan cara ini, program / fungsi / komputer tidak tahu apa-apa, itu hanya menjalankan instruksi untuk memindahkan data.

Tn. Minty Fresh
sumber
Kata-kata 'templat' dan 'format' seperti yang digunakan di sini tidak muncul dalam kompiler atau buku teks kompiler yang pernah saya lihat, dan sepertinya tidak ada alasan untuk menggunakan kedua kata itu untuk hal yang sama yang tidak ada. Variabel memiliki alamat dan / atau offset, hanya itu yang perlu Anda ketahui.
user207421
Saya menggunakan kata-kata karena mereka abstraksi untuk pengaturan data, seperti halnya angka, file, array, dan variabel adalah abstraksi.
Tn. Minty Fresh