Bagikan melalui


Penggunaan stack x64

Semua memori di luar alamat RSP saat ini dianggap tak stabil: OS, atau debugger, dapat menimpa memori ini selama sesi debug pengguna, atau penangan interupsi. Dengan demikian, RSP harus selalu diatur sebelum mencoba membaca atau menulis nilai ke frame tumpukan.

Bagian ini membahas alokasi ruang tumpukan untuk variabel lokal dan intrinsik alloca .

Alokasi tumpukan

Prolog fungsi bertanggung jawab untuk mengalokasikan ruang tumpukan untuk variabel lokal, register tersimpan, parameter tumpukan, dan parameter register.

Area parameter selalu berada di bagian bawah tumpukan (bahkan jika alloca digunakan), sehingga akan selalu berdekatan dengan alamat pengembalian selama panggilan fungsi apa pun. Ini berisi setidaknya empat entri, tetapi selalu cukup ruang untuk menyimpan semua parameter yang diperlukan oleh fungsi apa pun yang mungkin dipanggil. Perhatikan bahwa ruang selalu dialokasikan untuk parameter register, bahkan jika parameter itu sendiri tidak pernah disimpan di tumpukan; penerima dipastikan bahwa ruang telah dialokasikan untuk semua parameternya. Alamat rumah diperlukan untuk argumen register sehingga area yang berdampingan tersedia jika fungsi yang disebut perlu mengambil alamat daftar argumen (va_list) atau argumen individual. Area ini juga menyediakan tempat yang praktis untuk menyimpan argumen register selama eksekusi thunk dan sebagai opsi pemecahan masalah (misalnya, membuat argumen mudah ditemukan selama debugging jika disimpan di lokasi memori asal mereka dalam kode prolog). Bahkan jika fungsi yang disebut memiliki kurang dari 4 parameter, 4 lokasi tumpukan ini secara efektif dimiliki oleh fungsi yang disebut, dan dapat digunakan oleh fungsi yang disebut untuk tujuan lain selain menyimpan nilai register parameter. Dengan demikian, pemanggil mungkin tidak menyimpan informasi di bagian stack ini ketika menjalankan panggilan fungsi.

Jika ruang dialokasikan secara dinamis (alloca) dalam fungsi, maka register nonvolatile harus digunakan sebagai penunjuk bingkai untuk menandai dasar bagian tetap dari tumpukan dan register tersebut harus disimpan dan diinisialisasi dalam prolog. Perhatikan bahwa ketika alloca digunakan, panggilan ke penerima panggilan yang sama dari pemanggil yang sama mungkin memiliki alamat yang berbeda untuk parameter register-nya.

Tumpukan akan selalu dipertahankan sejajar 16 byte, kecuali dalam prolog (misalnya, setelah alamat pengembalian didorong), dan kecuali jika ditunjukkan dalam Jenis Fungsi untuk kelas fungsi bingkai tertentu.

Berikut ini adalah contoh tata letak tumpukan di mana fungsi A memanggil fungsi non-daun B. Prolog Fungsi A telah mengalokasikan ruang untuk semua parameter register dan stack yang diperlukan oleh B di bagian bawah tumpukan. Panggilan mendorong alamat pengembalian dan prolog B mengalokasikan ruang untuk variabel lokalnya, register nonvolatile, dan ruang yang diperlukan untuk memanggil fungsi. Jika B menggunakan alloca, ruang dialokasikan antara area penyimpanan register variabel/nonvolatile lokal dan area tumpukan parameter.

Diagram tata letak tumpukan untuk contoh konversi x64.

Ketika fungsi B memanggil fungsi lain, alamat pengembalian didorong tepat di bawah alamat rumah untuk RCX.

Pembangunan area tumpukan parameter yang dinamis

Jika penunjuk bingkai digunakan, opsi ada untuk membuat area tumpukan parameter secara dinamis. Ini saat ini tidak dilakukan di pengkompilasi x64.

Jenis fungsi

Pada dasarnya ada dua jenis fungsi. Fungsi yang memerlukan bingkai tumpukan disebut frame function. Fungsi yang tidak memerlukan bingkai tumpukan disebut fungsi daun.

Fungsi bingkai adalah fungsi yang mengalokasikan ruang tumpukan, memanggil fungsi lain, menyimpan register nonvolatile, atau menggunakan penanganan pengecualian. Ini juga memerlukan entri tabel fungsi. Fungsi bingkai memerlukan prolog dan epilog. Fungsi bingkai dapat secara dinamis mengalokasikan ruang tumpukan dan dapat menggunakan penunjuk bingkai. Fungsi frame memiliki kemampuan penuh dari standar panggilan ini yang dapat digunakan.

Jika fungsi bingkai tidak memanggil fungsi lain, maka tidak diperlukan untuk menyelaraskan stack (dirujuk dalam Alokasi Tumpukan Bagian).

Fungsi daun adalah fungsi yang tidak memerlukan entri tabel fungsi. Ini tidak dapat membuat perubahan pada register nonvolatile apa pun, termasuk RSP, yang berarti tidak dapat memanggil fungsi apa pun atau mengalokasikan ruang tumpukan. Diperbolehkan untuk membiarkan tumpukan tidak selaras saat dieksekusi.

perataan malloc

malloc dijamin mengembalikan memori yang diselaraskan dengan baik untuk menyimpan objek apa pun yang memiliki penyelarasan dasar dan yang dapat muat dalam jumlah memori yang dialokasikan. Perataan mendasar adalah perataan yang kurang dari atau sama dengan perataan terbesar yang didukung oleh implementasi tanpa spesifikasi penyelarasan. (Di Microsoft C++, ini adalah perataan yang diperlukan untuk double, atau 8 byte. Dalam kode yang menargetkan platform 64-bit, itu adalah 16 byte.) Misalnya, alokasi empat byte akan diselaraskan pada batas yang mendukung objek empat byte atau lebih kecil.

Visual C++ mengizinkan jenis yang memiliki perataan diperluas, yang juga dikenal sebagai jenis over-aligned. Misalnya, jenis SSE __m128 dan __m256, dan jenis yang dideklarasikan dengan menggunakan __declspec(align( n )) di mana n lebih besar dari 8, memiliki perataan yang diperluas. Tidak ada jaminan bahwa perataan memori pada batas yang sesuai untuk objek yang memerlukan perataan tambahan dijamin oleh malloc. Untuk mengalokasikan memori untuk jenis yang memerlukan penyelarasan lebih tinggi, gunakan _aligned_malloc dan fungsi terkait.

alloca

_alloca harus selaras 16 byte dan juga diperlukan untuk menggunakan penunjuk bingkai.

Tumpukan yang dialokasikan perlu menyertakan ruang setelahnya untuk parameter dari fungsi-fungsi yang dipanggil berikutnya, seperti yang dibahas dalam Alokasi Tumpukan.

Lihat juga

Konvensi perangkat lunak x64
Menyelaraskan
__declspec