Di Windows, tumpukan tumbuh dari alamat besar ke kecil. Kadang-kadang ditentukan secara arsitektur, dan kadang-kadang itu hanya kesepakatan yang diterima. Nilai penunjuk tumpukan (register prosesor) adalah penunjuk ke nilai di bagian atas tumpukan. Dan nilai yang terletak lebih dalam di stack, masing-masing, terletak di alamat besar. Tetapi apa yang terjadi pada data yang terletak di alamat yang lebih kecil dari stack pointer?

Konvensi untuk beberapa (tetapi tidak semua) arsitektur menentukan zona merah, yang merupakan area memori di bawah penunjuk tumpukan, tetapi yang masih berlaku untuk digunakan oleh aplikasi.

Untuk Windows, ukuran zona merah bervariasi tergantung pada arsitektur perangkat keras dan seringkali nol.
Arsitektur | Ukuran Zona Merah |
---|
x86 | 0 byte |
x64 | 0 byte |
Itanium | 16 byte * |
Alpha AXP | 0 byte |
MIPS32 | 0 byte |
PowerPC | 232 byte ** |
ARM32 | 8 byte |
ARM64 | 16 byte |
* Platform Itanium patut diperhatikan fitur: ada zona merah terletak di atas penunjuk tumpukan , dan tidak di bawahnya.
** Dalam hal PowerPC, zona merah adalah efek samping dari perjanjian panggilan .
Memori apa pun di belakang zona merah (di bawah tumpukan) dianggap tidak stabil dan dapat diubah oleh sistem operasi kapan saja.
Tapi serius, mengapa sistem operasi peduli dengan apa yang saya lakukan dengan stack saya? Maksudku, ini tumpukanku! Sistem operasi tidak memberi tahu saya apa yang harus saya lakukan dengan memori yang saya alokasikan melalui VirtualAlloc
. Apa yang membuat tumpukan berbeda dari memori lain?
Pertimbangkan kode berikut untuk platform x86 :
MOV [esp-4], eax ; eax MOV ecx, [esp-4] ; ecx CMP ecx, eax ; ? JNZ panic ; N: -
Penjelasan komentar untuk instruksi JNZKebaktian pengkodean perakitan mengatakan bahwa komentar untuk instruksi cabang harus menjelaskan hasilnya jika cabang selesai. Dalam contoh di atas, instruksi CMP menanyakan pertanyaan "Apakah mereka sama?". Dan instruksi JNZ melompat jika mereka tidak sama. Dengan demikian, komentar dimulai dengan "N:", yang berarti bahwa transisi akan selesai jika jawaban untuk pertanyaan sebelumnya adalah "Tidak", dan sisa komentar menggambarkan situasi ketika transisi dilakukan.
Konvensi coding assembler?Ya, kami memiliki konvensi pengkodean untuk assembler.
Apakah mungkin transisi bersyarat akan dilaksanakan?
Karena tidak ada zona merah pada x86, memori dengan offset negatif relatif terhadap stack pointer dapat ditimpa kapan saja. Oleh karena itu, untuk kode di atas, transisi ke label panic
dimungkinkan.
Debugger dapat menggunakan memori di belakang zona merah sebagai tempat yang nyaman untuk menyimpan datanya. Misalnya, jika Anda menggunakan perintah .call , debugger akan membuat panggilan bersarang pada tumpukan yang sama dan mungkin akan menggunakan bagian dari ruang tumpukan ini untuk menyimpan register sehingga mereka dapat dikembalikan setelah kembali dari fungsi yang dipanggil. Karena itu, setiap data yang disimpan di luar zona merah akan dimusnahkan.
Bahkan selama operasi normal, sistem operasi dapat kapan saja menimpa data di luar zona merah. Di sini, misalnya, bagaimana ini bisa terjadi:
Misalkan utas Anda menjalankan slot waktunya tepat setelah menyimpan data di belakang zona merah. Ketika utas Anda sedang menunggu untuk melanjutkan eksekusi, manajer memori sementara mengambil halaman fisik dari kode Anda. Pada akhirnya, utas Anda mendapatkan kendali lagi dan manajer memori mencoba untuk menukar halaman kode kembali (halaman masuk). Oh tidak, kesalahan I / O terjadi selama paging! Sistem operasi mendorong bingkai pengecualian untuk STATUS_IN_PAGE_ERROR
pada tumpukan, yang mengarah pada korupsi data yang Anda simpan di belakang zona merah.
Sistem operasi mengirimkan pengecualian ini. Ini mengakses penangan pengecualian vektor ( VEH ), yang merupakan bagian lain dari program Anda. Pawang diinstal secara khusus untuk menangani situasi luar biasa yang muncul dari kemungkinan peluncuran program Anda langsung dari CD-ROM atau FS jaringan yang tidak dapat diandalkan. Program menampilkan permintaan yang meminta pengguna memasukkan CD lagi dan menawarkan untuk mencoba lagi. Jika pengguna mengatakan apa yang perlu diulangi, penangan pengecualian vektor mengembalikan EXCEPTION_CONTINUE_EXECUTION
, dan sistem operasi akan memulai kembali instruksi di mana pengecualian terjadi.
Kali ini, restart berhasil karena CD-ROM hadir (dan membaca) dan kode dapat berhasil dipompa ke memori. Pernyataan berikut dijalankan, yang memuat nilai di luar zona merah ke dalam ecx
. Tapi ini bukan nilai yang sama yang disimpan oleh pernyataan sebelumnya, karena pengecualian STATUS_IN_PAGE_ERROR
menimpa itu. Perbandingan mengatakan bahwa datanya berbeda, dan kami pergi ke label panic
.
Jika Anda ingin menyimpan data di stack, letakkan di sana dengan benar: pertama-tama kurangi pointer stack, dan kemudian simpan nilainya di bagian stack yang valid. Jangan sembunyikan data di belakang zona merah, memori ini dapat diubah kapan saja tanpa sepengetahuan Anda.