Saat mengkompilasi kode C dan melihat perakitan, semuanya memiliki tumpukan yang tumbuh mundur seperti ini:
_main:
pushq %rbp
movl $5, -4(%rbp)
popq %rbp
ret
-4(%rbp)
- apakah ini berarti pointer dasar atau stack pointer sebenarnya bergerak ke bawah alamat memori daripada naik? Mengapa demikian?
Aku berubah $5, -4(%rbp)
untuk $5, +4(%rbp)
, disusun dan berlari kode dan tidak ada kesalahan. Jadi mengapa kita harus tetap mundur di tumpukan memori?
-4(%rbp)
sekali tidak memindahkan pointer dasar dan itu+4(%rbp)
tidak mungkin bekerja.malloc
menumbuhkan tumpukanmain
mengacaukan RBP-nya. Itu tentu saja mungkin. (Dan ya, tulisan4(%rbp)
akan menginjak nilai RBP yang disimpan). Err sebenarnya, main ini tidak pernahmov %rsp, %rbp
, jadi akses memori relatif terhadap RBP pemanggil , jika itu yang benar-benar diuji oleh OP !!! Jika ini benar-benar disalin dari keluaran kompiler, beberapa instruksi ditinggalkan!Jawaban:
Ya,
push
instruksi mengurangi penunjuk tumpukan dan menulis ke tumpukan, sementarapop
melakukan sebaliknya, membaca dari tumpukan dan menambah penunjuk tumpukan.Ini agak historis karena untuk mesin dengan memori terbatas, tumpukan ditempatkan tinggi dan tumbuh ke bawah, sedangkan tumpukan ditempatkan rendah dan tumbuh ke atas. Hanya ada satu celah "memori bebas" - antara tumpukan & tumpukan, dan celah ini dibagi, salah satu dapat tumbuh ke dalam celah sesuai kebutuhan secara individual. Dengan demikian, program ini hanya kehabisan memori ketika tumpukan dan tumpukan bertabrakan tanpa meninggalkan memori bebas.
Jika tumpukan dan tumpukan keduanya tumbuh ke arah yang sama, maka ada dua celah, dan tumpukan tidak dapat benar-benar tumbuh ke celah tumpukan (sebaliknya juga bermasalah).
Awalnya, prosesor tidak memiliki instruksi penanganan tumpukan khusus. Namun, ketika dukungan tumpukan ditambahkan ke perangkat keras, ia mengambil pola ini tumbuh ke bawah, dan prosesor masih mengikuti pola ini sampai sekarang.
Orang dapat berargumen bahwa pada mesin 64-bit ada ruang alamat yang cukup untuk memungkinkan banyak celah - dan sebagai bukti, banyak celah harus terjadi ketika suatu proses memiliki banyak utas. Meskipun ini bukan motivasi yang cukup untuk mengubah keadaan, karena dengan sistem kesenjangan ganda, arah pertumbuhan bisa dibilang sewenang-wenang, sehingga tradisi / kompatibilitas cocok dengan skala.
Anda harus mengubah petunjuk CPU tumpukan penanganan untuk mengubah arah tumpukan, atau menyerah pada penggunaan didedikasikan mendorong & bermunculan petunjuk (misalnya
push
,pop
,call
,ret
, orang lain).Perhatikan bahwa arsitektur set instruksi MIPS tidak memiliki
push
& khususpop
, sehingga praktis untuk menumbuhkan tumpukan di kedua arah - Anda mungkin masih menginginkan tata letak memori satu celah untuk proses satu utas, tetapi dapat menumbuhkan tumpukan ke atas dan tumpukan ke bawah. Namun, jika Anda melakukan itu, beberapa kode varargs mungkin memerlukan penyesuaian dalam sumber atau lewat parameter di bawah kap.(Faktanya, karena tidak ada penanganan stack khusus pada MIPS, kami dapat menggunakan kenaikan sebelum atau sesudah atau sebelum atau sesudah penurunan untuk mendorong ke tumpukan selama kami menggunakan pembalikan yang tepat untuk memunculkan tumpukan, dan juga dengan asumsi bahwa sistem operasi menghormati model penggunaan tumpukan yang dipilih. Memang, dalam beberapa sistem tertanam dan beberapa sistem pendidikan, tumpukan MIPS ditanam ke atas.)
sumber
push
danpop
pada kebanyakan arsitektur, tetapi juga jauh lebih penting interupsi-penanganan,call
,ret
, dan apa pun yang telah dipanggang-dalam interaksi dengan stack.gets()
, atau apakahstrcpy()
itu tidak mendapatkan inline, maka pengembalian fungsi - fungsi pustaka tersebut akan menggunakan alamat pengirim yang ditimpa. Saat ini dengan tumpukan yang tumbuh ke bawah, saat penelepon mereka kembali.strcpy
), pada sebuah lengkungan di mana alamat pengirim disimpan dalam register kecuali perlu tumpah, tidak ada akses ke clobber pengembalian alamat.Dalam sistem spesifik Anda tumpukan mulai dari alamat memori tinggi dan "tumbuh" ke bawah ke alamat memori rendah. (kasing simetris dari rendah ke tinggi juga ada)
Dan karena Anda berubah dari -4 dan +4 dan itu berlari bukan berarti itu benar. Tata letak memori dari program yang sedang berjalan lebih kompleks dan tergantung pada banyak faktor lain yang dapat berkontribusi pada fakta bahwa Anda tidak langsung terhempas pada program yang sangat sederhana ini.
sumber
Pointer stack menunjuk pada batas antara memori stack yang dialokasikan dan yang tidak dialokasikan. Menumbuhkannya ke bawah berarti menunjuk pada awal struktur pertama dalam ruang stack yang dialokasikan, dengan item yang dialokasikan lainnya mengikuti pada alamat yang lebih besar. Memiliki pointer menunjuk ke awal struktur yang dialokasikan jauh lebih umum daripada sebaliknya.
Sekarang pada banyak sistem saat ini, ada register terpisah untuk stack frame yang bisa agak andal dibatalkan untuk mengetahui rantai panggilan, dengan penyimpanan variabel lokal diselingi. Cara register tumpukan bingkai ini diatur pada beberapa arsitektur berarti ia akhirnya menunjuk di belakang penyimpanan variabel lokal sebagai lawan dari penunjuk tumpukan sebelum itu. Jadi menggunakan register tumpukan bingkai ini kemudian membutuhkan pengindeksan negatif.
Perhatikan bahwa stack frames dan pengindeksannya adalah aspek sisi dari bahasa komputer yang dikompilasi sehingga pembuat kode kompilerlah yang harus berurusan dengan "tidak wajar" daripada programmer bahasa assembly yang buruk.
Jadi, sementara ada alasan historis yang baik untuk memilih tumpukan untuk tumbuh ke bawah (dan beberapa dari mereka dipertahankan jika Anda memprogram dalam bahasa assembly dan tidak repot-repot mengatur bingkai tumpukan yang tepat), mereka menjadi kurang terlihat.
sumber