Mengapa tumpukan biasanya tumbuh ke bawah?

97

Saya tahu bahwa dalam arsitektur yang saya kenal secara pribadi (x86, 6502, dll), tumpukan biasanya tumbuh ke bawah (yaitu setiap item yang didorong ke hasil tumpukan dalam SP yang berkurang, bukan yang bertambah).

Saya bertanya-tanya tentang alasan historis untuk ini. Saya tahu bahwa dalam ruang alamat terpadu, akan lebih mudah untuk memulai tumpukan di ujung segmen data yang berlawanan (katakanlah) jadi hanya ada masalah jika kedua sisi bertabrakan di tengah. Tetapi mengapa tumpukan secara tradisional mendapatkan bagian atas? Terutama mengingat bagaimana ini adalah kebalikan dari model "konseptual"?

(Dan perhatikan bahwa dalam arsitektur 6502, tumpukan juga tumbuh ke bawah, meskipun dibatasi ke satu halaman 256-byte, dan pilihan arah ini tampak sewenang-wenang.)

Ben Zotto
sumber

Jawaban:

52

Mengenai alasan historis, saya tidak bisa mengatakan dengan pasti (karena saya tidak merancangnya). Pemikiran saya tentang masalah ini adalah bahwa CPU awal mendapatkan penghitung program asli mereka disetel ke 0 dan itu adalah keinginan alami untuk memulai tumpukan di ujung lain dan tumbuh ke bawah, karena kode mereka secara alami tumbuh ke atas.

Sebagai tambahan, perhatikan bahwa pengaturan penghitung program ke 0 saat reset tidak berlaku untuk semua CPU awal. Misalnya, Motorola 6809 akan mengambil penghitung program dari alamat 0xfffe/fsehingga Anda dapat mulai berjalan di lokasi yang sewenang-wenang, tergantung pada apa yang disediakan di alamat itu (biasanya, tetapi tidak terbatas pada, ROM).

Salah satu hal pertama yang akan dilakukan beberapa sistem historis adalah memindai memori dari atas hingga menemukan lokasi yang akan membaca kembali nilai yang sama yang tertulis, sehingga ia akan mengetahui RAM aktual yang terpasang (misalnya, z80 dengan ruang alamat 64K belum tentu memiliki 64K atau RAM, sebenarnya 64K akan menjadi besar di hari-hari awal saya). Setelah menemukan alamat aktual teratas, ia akan menyetel penunjuk tumpukan dengan tepat dan kemudian dapat mulai memanggil subrutin. Pemindaian ini umumnya dilakukan oleh kode yang menjalankan CPU di ROM sebagai bagian dari start-up.

Berkenaan dengan pertumbuhan tumpukan, tidak semuanya tumbuh ke bawah, lihat jawaban ini untuk detailnya.

paxdiablo
sumber
1
Saya suka kisah strategi deteksi RAM Z80. Masuk akal bahwa segmen teks ditata tumbuh ke atas - programmer dahulu kala memiliki kontak yang lebih langsung dengan menangani implikasi dari itu daripada tumpukan. Terima kasih paxdiablo. Pointer ke set bentuk alternatif implementasi stack juga sangat menarik.
Ben Zotto
Bukankah memori awal memiliki cara untuk memberi tahu ukurannya dan kita harus menghitungnya secara manual?
phuclv
1
@ LưuVĩnhPhúc, saya harus menganggap Anda satu generasi (atau dua) di belakang saya. Saya masih ingat metode TRS-80 model 3 untuk mendapatkan tanggal dan waktu untuk memintanya kepada pengguna saat boot. Memiliki pemindai memori untuk menetapkan batas atas memori dianggap canggih pada masa itu :-) Dapatkah Anda membayangkan apa yang akan terjadi jika Windows menanyakan waktu, atau berapa banyak memori yang Anda miliki, setiap kali Anda boot?
paxdiablo
1
Memang, dokumentasi Zilog Z80 mengatakan bagian tersebut dimulai dengan mengatur register PC ke 0000h dan menjalankannya. Ini mengatur mode interupsi ke 0, menonaktifkan interupsi, dan mengatur register I dan R ke 0, juga. Setelah itu, mulai dijalankan. Pada 0000h, mulai menjalankan kode. Kode ITU harus menginisialisasi penunjuk tumpukan sebelum dapat memanggil subrutin atau mengaktifkan interupsi. Vendor apa yang menjual Z80 yang berperilaku seperti yang Anda gambarkan?
MikeB
1
Mike, maaf, saya seharusnya lebih jelas. Ketika saya mengatakan memori yang dipindai CPU, saya tidak bermaksud itu adalah fitur dari CPU itu sendiri. Itu sebenarnya dikendalikan dari program di ROM. Saya akan menjelaskan.
paxdiablo
21

Satu penjelasan bagus yang saya dengar adalah bahwa beberapa mesin di masa lalu hanya dapat memiliki offset yang tidak ditandatangani, jadi Anda ingin stack tumbuh ke bawah sehingga Anda dapat mengenai penduduk setempat tanpa harus kehilangan instruksi tambahan untuk memalsukan offset negatif.

anq
sumber
9

Stanley Mazor (arsitek 4004 dan 8080) menjelaskan bagaimana arah pertumbuhan tumpukan dipilih untuk 8080 (dan akhirnya untuk 8086) di "Intel Mikroprosesor: 8008 hingga 8086" :

Penunjuk tumpukan dipilih untuk menjalankan "menurun" (dengan tumpukan maju ke memori yang lebih rendah) untuk menyederhanakan pengindeksan ke dalam tumpukan dari program pengguna (pengindeksan positif) dan untuk menyederhanakan tampilan konten tumpukan dari panel depan.

roolebo
sumber
6

Salah satu kemungkinan alasannya mungkin karena ini menyederhanakan penyelarasan. Jika Anda menempatkan variabel lokal pada tumpukan yang harus ditempatkan pada batas 4-byte, Anda cukup mengurangi ukuran objek dari penunjuk tumpukan, dan kemudian mengosongkan dua bit yang lebih rendah untuk mendapatkan alamat yang selaras dengan benar. Jika tumpukan tumbuh ke atas, memastikan penyelarasan menjadi sedikit lebih rumit.

jalf
sumber
1
Komputer tidak mengurangi; mereka menambahkan pujian 2. Apa pun yang dilakukan dengan mengurangi benar-benar dilakukan dengan menjumlahkan. Pertimbangkan, komputer memiliki penjumlah, bukan pengurang.
jww
1
@jww - itu perbedaan tanpa perbedaan. Saya mungkin juga mengklaim komputer tidak menambahkan mereka hanya mengurangi! Untuk keperluan jawaban ini, itu tidak terlalu penting - tetapi kebanyakan ALU akan menggunakan sirkuit yang mendukung penjumlahan dan pengurangan dengan kinerja yang sama. Artinya, meskipun A - Bsecara konseptual dapat diimplementasikan sebagai A + (-B)(yaitu, langkah negasi terpisah untuk B), ini tidak dalam praktiknya.
BeeOnRope
@jww Masalahmu salah untuk komputer awal - butuh beberapa waktu untuk melengkapi dua untuk menang, dan sampai itu terjadi, ada komputer yang menggunakan pelengkap dan tanda-dan-besaran dan mungkin hal-hal lain sebagai gantinya. Dengan penerapan tersebut, mungkin ada keuntungan untuk menambah versus mengurangi. Jadi dengan tidak adanya informasi tambahan, salah untuk mengesampingkan ini sebagai faktor yang mungkin mempengaruhi pilihan skema pengalamatan seperti arah tumpukan.
mtraceur
4

IIRC tumpukan tumbuh ke bawah karena tumpukan tumbuh ke atas. Bisa jadi sebaliknya.

Christian V
sumber
5
Heap yang tumbuh ke atas memungkinkan realokasi yang efisien dalam beberapa kasus, tetapi heap yang tumbuh ke bawah tidak pernah berhasil.
Peter Cordes
@PeterCordes kenapa?
Yashas
3
@Yashas: karena realloc(3)membutuhkan lebih banyak ruang setelah objek untuk hanya memperpanjang pemetaan tanpa menyalin. Realokasi berulang dari objek yang sama dimungkinkan jika diikuti oleh ruang tak terpakai yang jumlahnya berubah-ubah.
Peter Cordes
2

Saya percaya ini murni keputusan desain. Tidak semuanya tumbuh ke bawah - lihat utas SO ini untuk diskusi yang baik tentang arah pertumbuhan tumpukan pada arsitektur yang berbeda.

Kaleb Brasee
sumber
1

Saya yakin konvensi tersebut dimulai dengan IBM 704 dan "register pengurangan" yang terkenal itu. Pidato modern akan menyebutnya bidang offset instruksi, tetapi intinya adalah mereka turun , bukan naik .

luser droog
sumber
1

Hanya 2c lagi:

Di luar semua alasan historis yang disebutkan, saya cukup yakin tidak ada alasan yang valid dalam prosesor modern. Semua prosesor dapat mengambil offset yang ditandatangani, dan memaksimalkan jarak heap / stack agak diperdebatkan sejak kami mulai berurusan dengan banyak utas.

Saya pribadi menganggap ini sebagai cacat desain keamanan. Jika, katakanlah, perancang arsitektur x64 akan membalikkan arah pertumbuhan tumpukan, sebagian besar buffer overflow tumpukan akan dihilangkan - yang merupakan masalah besar. (karena senar tumbuh ke atas).

Ofek Shilon
sumber
0

Saya tidak yakin tetapi saya melakukan beberapa pemrograman untuk VAX / VMS di masa lalu. Sepertinya saya ingat satu bagian dari memori (tumpukan ??) naik dan tumpukan turun. Saat keduanya bertemu, maka Anda kehabisan memori.

Martin
sumber
1
Ini benar, tapi mengapa heap tumbuh ke atas dan bukan sebaliknya?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
0

Salah satu keuntungan dari pertumbuhan tumpukan yang menurun dalam sistem tersemat minimal adalah bahwa satu bagian RAM dapat dipetakan secara berlebihan ke dalam halaman O dan halaman 1, memungkinkan variabel halaman nol untuk ditetapkan mulai dari 0x000 dan tumpukan tumbuh ke bawah dari 0x1FF, memaksimalkan jumlah yang harus ditingkatkan sebelum menimpa variabel.

Salah satu tujuan desain asli 6502 adalah dapat dikombinasikan dengan, misalnya, 6530, menghasilkan sistem mikrokontroler dua chip dengan ROM program 1 KB, timer, I / O, dan 64 byte RAM bersama. antara variabel tumpukan dan halaman nol. Sebagai perbandingan, sistem tertanam minimal pada waktu itu berdasarkan 8080 atau 6800 adalah empat atau lima chip.

Milan
sumber