Itu benar-benar tergantung pada sistem, tetapi OS modern dengan memori virtual cenderung memuat gambar proses mereka dan mengalokasikan memori seperti ini:
+---------+
| stack | function-local variables, return addresses, return values, etc.
| | often grows downward, commonly accessed via "push" and "pop" (but can be
| | accessed randomly, as well; disassemble a program to see)
+---------+
| shared | mapped shared libraries (C libraries, math libs, etc.)
| libs |
+---------+
| hole | unused memory allocated between the heap and stack "chunks", spans the
| | difference between your max and min memory, minus the other totals
+---------+
| heap | dynamic, random-access storage, allocated with 'malloc' and the like.
+---------+
| bss | Uninitialized global variables; must be in read-write memory area
+---------+
| data | data segment, for globals and static variables that are initialized
| | (can further be split up into read-only and read-write areas, with
| | read-only areas being stored elsewhere in ROM on some systems)
+---------+
| text | program code, this is the actual executable code that is running.
+---------+
Ini adalah ruang alamat proses umum pada banyak sistem memori virtual umum. "Lubang" adalah ukuran total memori Anda, dikurangi ruang yang digunakan oleh semua area lainnya; ini memberi banyak ruang bagi tumpukan untuk tumbuh. Ini juga "virtual", artinya memetakan ke memori Anda yang sebenarnya melalui tabel terjemahan, dan dapat disimpan di lokasi mana pun di memori yang sebenarnya. Hal ini dilakukan dengan cara ini untuk melindungi satu proses dari mengakses memori proses lain, dan membuat setiap proses berpikir itu berjalan pada sistem yang lengkap.
Perhatikan bahwa posisi, misalnya, tumpukan dan tumpukan mungkin berada dalam urutan berbeda pada beberapa sistem (lihat jawaban Billy O'Neal di bawah ini untuk detail lebih lanjut tentang Win32).
Sistem lain bisa sangat berbeda. DOS, misalnya, berjalan dalam mode nyata , dan alokasi memorinya ketika menjalankan program tampak jauh berbeda:
+-----------+ top of memory
| extended | above the high memory area, and up to your total memory; needed drivers to
| | be able to access it.
+-----------+ 0x110000
| high | just over 1MB->1MB+64KB, used by 286s and above.
+-----------+ 0x100000
| upper | upper memory area, from 640kb->1MB, had mapped memory for video devices, the
| | DOS "transient" area, etc. some was often free, and could be used for drivers
+-----------+ 0xA0000
| USER PROC | user process address space, from the end of DOS up to 640KB
+-----------+
|command.com| DOS command interpreter
+-----------+
| DOS | DOS permanent area, kept as small as possible, provided routines for display,
| kernel | *basic* hardware access, etc.
+-----------+ 0x600
| BIOS data | BIOS data area, contained simple hardware descriptions, etc.
+-----------+ 0x400
| interrupt | the interrupt vector table, starting from 0 and going to 1k, contained
| vector | the addresses of routines called when interrupts occurred. e.g.
| table | interrupt 0x21 checked the address at 0x21*4 and far-jumped to that
| | location to service the interrupt.
+-----------+ 0x0
Anda dapat melihat bahwa DOS memungkinkan akses langsung ke memori sistem operasi, tanpa perlindungan, yang berarti bahwa program ruang pengguna secara umum dapat langsung mengakses atau menimpa apa pun yang mereka sukai.
Namun, dalam ruang alamat proses, program cenderung terlihat serupa, hanya saja mereka digambarkan sebagai segmen kode, segmen data, heap, segmen stack, dll., Dan dipetakan sedikit berbeda. Tetapi sebagian besar area umum masih ada.
Setelah memuat program dan lib bersama yang diperlukan ke dalam memori, dan mendistribusikan bagian-bagian program ke area yang tepat, OS mulai menjalankan proses Anda di mana pun metode utamanya berada, dan program Anda mengambil alih dari sana, membuat panggilan sistem seperlunya saat itu membutuhkan mereka.
Sistem yang berbeda (tertanam, apa pun) mungkin memiliki arsitektur yang sangat berbeda, seperti sistem tanpa tumpukan, sistem arsitektur Harvard (dengan kode dan data disimpan dalam memori fisik terpisah), sistem yang benar-benar menyimpan BSS dalam memori hanya baca (awalnya ditetapkan oleh programmer), dll. Tapi inilah intinya.
Kamu berkata:
Saya juga tahu bahwa program komputer menggunakan dua jenis memori: tumpukan dan tumpukan, yang juga merupakan bagian dari memori utama komputer.
"Stack" dan "heap" hanyalah konsep abstrak, daripada "jenis" memori yang berbeda secara fisik.
Sebuah tumpukan hanyalah struktur data pertama-out terakhir di,. Dalam arsitektur x86, itu sebenarnya dapat diatasi secara acak dengan menggunakan offset dari ujung, tetapi fungsi yang paling umum adalah PUSH dan POP untuk menambah dan menghapus item dari masing-masing. Ini biasanya digunakan untuk variabel fungsi-lokal (disebut "penyimpanan otomatis"), argumen fungsi, alamat pengirim, dll. (Selengkapnya di bawah)
Sebuah "tumpukan" hanya nama panggilan untuk sepotong memori yang dapat dialokasikan pada permintaan, dan ditujukan secara acak (yang berarti, Anda dapat mengakses setiap lokasi di langsung). Ini biasanya digunakan untuk struktur data yang Anda alokasikan saat runtime (dalam C ++, menggunakan new
dan delete
, dan malloc
dan teman-teman di C, dll).
Tumpukan dan tumpukan, pada arsitektur x86, keduanya secara fisik berada di memori sistem Anda (RAM), dan dipetakan melalui alokasi memori virtual ke dalam ruang alamat proses seperti yang dijelaskan di atas.
The register (masih pada x86), secara fisik berada di dalam prosesor (sebagai lawan RAM), dan dimuat oleh prosesor, dari daerah TEXT (dan juga dapat diambil dari tempat lain dalam memori atau tempat lain tergantung pada instruksi CPU yang sebenarnya dieksekusi). Mereka pada dasarnya hanya sangat kecil, lokasi memori on-chip yang sangat cepat yang digunakan untuk sejumlah tujuan berbeda.
Tata letak register sangat tergantung pada arsitektur (pada kenyataannya, register, set instruksi, dan tata letak / desain memori, persis apa yang dimaksud dengan "arsitektur"), jadi saya tidak akan memperluasnya, tetapi menyarankan Anda untuk mengambil kursus bahasa assembly untuk memahami mereka dengan lebih baik.
Pertanyaanmu:
Pada titik apa tumpukan digunakan untuk pelaksanaan instruksi? Instruksi pergi dari RAM, ke tumpukan, ke register?
Tumpukan (dalam sistem / bahasa yang memiliki dan menggunakannya) paling sering digunakan seperti ini:
int mul( int x, int y ) {
return x * y; // this stores the result of MULtiplying the two variables
// from the stack into the return value address previously
// allocated, then issues a RET, which resets the stack frame
// based on the arg list, and returns to the address set by
// the CALLer.
}
int main() {
int x = 2, y = 3; // these variables are stored on the stack
mul( x, y ); // this pushes y onto the stack, then x, then a return address,
// allocates space on the stack for a return value,
// then issues an assembly CALL instruction.
}
Tulis program sederhana seperti ini, dan kemudian kompilasi untuk perakitan ( gcc -S foo.c
jika Anda memiliki akses ke GCC), dan lihatlah. Perakitan ini cukup mudah diikuti. Anda dapat melihat bahwa stack digunakan untuk variabel fungsi lokal, dan untuk memanggil fungsi, menyimpan argumen mereka dan mengembalikan nilai. Ini juga mengapa ketika Anda melakukan sesuatu seperti:
f( g( h( i ) ) );
Semua ini dipanggil pada gilirannya. Ini benar-benar membangun setumpuk pemanggilan fungsi dan argumen mereka, mengeksekusi mereka, dan kemudian memunculkannya saat angin turun kembali (atau naik;). Namun, seperti yang disebutkan di atas, tumpukan (pada x86) sebenarnya berada di ruang memori proses Anda (dalam memori virtual), dan sehingga dapat dimanipulasi secara langsung; itu bukan langkah terpisah selama eksekusi (atau setidaknya orthogonal ke proses).
FYI, di atas adalah konvensi pemanggilan C , juga digunakan oleh C ++. Bahasa / sistem lain dapat mendorong argumen ke tumpukan dalam urutan yang berbeda, dan beberapa bahasa / platform bahkan tidak menggunakan tumpukan, dan melakukannya dengan cara yang berbeda.
Perhatikan juga, ini bukan baris aktual dari eksekusi kode C. Kompiler telah mengubahnya menjadi instruksi bahasa mesin di executable Anda. Mereka kemudian (umumnya) disalin dari area TEXT ke dalam pipeline CPU, kemudian ke register CPU, dan dieksekusi dari sana. [Ini tidak benar. Lihat koreksi Ben Voigt di bawah ini.]