Apa tujuan dari zona merah?

12

Zona merah adalah area ukuran tetap di memori di luar penunjuk tumpukan yang belum "dialokasikan". Compiler menghasilkan rakitan untuk mengakses area itu dalam fungsi daun sederhana.

Tapi saya tidak bisa melihat keuntungan nyata untuk zona merah. Mengakses memori di luar stack pointer sangat berbahaya dan dapat dengan mudah menyebabkan kerusakan data . Mengapa bahkan melakukan ini? Menyimpan 2 instruksi prosesor (push ebp; mov ebp esp) tidak akan memberikan kecepatan nyata.

Alexander Dzyoba
sumber

Jawaban:

16

Zona merah, murni dan sederhana, merupakan optimasi yang dapat menyimpan instruksi. Ini berarti bahwa tidak lagi diperlukan kode yang dipancarkan untuk setiap fungsi untuk mengurangi dari stack pointer untuk membuat penyimpanan lokal seperti itu

sub XXX, %rsp 

di awal setiap panggilan fungsi, bahkan jika mereka bukan fungsi daun. Sering kali kode yang dipancarkan dari kompiler dapat menggunakan ruang sementara di zona merah di bawah penunjuk tumpukan tanpa perlu menyimpannya dan sebelum memanggil fungsi lainnya. Ini adalah optimasi yang berguna untuk tersedia.

Jika Anda tidak lagi harus sub dari penunjuk tumpukan, kode yang dipancarkan dapat menggunakan rsp sebagai basis penunjuk, pekerjaan yang biasanya disediakan untuk rbp, dan kode yang dipancarkan dapat menggunakan rbp sebagai register tujuan umum lainnya.

Ini pada akhirnya berarti prolog dan epilog dari setiap pemanggilan fungsi dapat menyimpan dua instruksi yang akan menyimpan dan mengembalikan rbp:

(gnu assembler)

pushq %rbp       # prologue [ two instructions not necessary ]
movq %rsp,%rbp

.... [code]

movq %rbp,%rsp   # epilogue [ two instructions not necessary ]
popq %rbp        

Perhatikan bahwa dalam gcc Anda dapat melewati flag -mno-red-zone jika Anda tidak menginginkannya (tetapi ABI x86-64 mensyaratkannya). Kernel Linux tidak harus sesuai dengan ABI dan dengan demikian semua kode kernel dikompilasi dengan -mno-red-zone.

Lebih jauh, mengakses memori di luar penunjuk tumpukan tidak berbahaya jika itu adalah mode operasi yang diharapkan. Ini hanya berbahaya dan dapat menyebabkan korupsi ketika tidak direncanakan, dan tidak terduga. Ketika kode yang dipancarkan melakukannya, ia tahu apa yang dilakukannya.

Brian Onn
sumber
Ya saya mengerti ini. Tetapi apakah menyimpan 1 instruksi (sub dari esp) benar-benar optimasi? Maksud saya menghemat beberapa byte dan 1 siklus prosesor untuk harga kemungkinan nyata data yang rusak terlihat aneh. Mungkin ada alasan lain untuk melakukan itu?
Alexander Dzyoba
3
Sebenarnya bukan sub dari esp yang merupakan optimasi, tetapi karena Anda tidak lagi harus sub dari esp, Anda dapat menggunakan esp sebagai basis pointer (biasanya dilakukan oleh ebp) dan menggunakan ebp untuk sesuatu yang lain dalam kode fungsi. Akhirnya, karena esp sekarang adalah pointer dasar, kode dapat menghindari menyimpan dan mengembalikan ebp dalam prolog / epilog. Saya akan mengklarifikasi jawabannya dengan informasi tambahan ini
Brian Onn
sunting dan ubah menjadi rbp / rsp daripada ebp / esp karena zona merah hanya merupakan bagian dari ABI x86-64 (walaupun tidak ada yang mencegah seseorang menggunakan teknik yang sama dengan register 32 bit; tetapi tidak ada kompiler yang melakukannya hari ini)
Brian Onn
1
Penghilangan frame pointer sama sekali tidak berhubungan dengan zona merah - kompiler dapat mengindeks stack menggunakan %rspsebagai pointer basis.
alecov