Bagikan melalui


Penggunaan tumpukan x64

Semua memori di luar alamat RSP saat ini dianggap volatil: OS, atau debugger, dapat menimpa memori ini selama sesi debug pengguna, atau handler interupsi. Dengan demikian, RSP harus selalu diatur sebelum mencoba membaca atau menulis nilai ke bingkai 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 dirumahkan ke tumpukan; penerima panggilan dijamin 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 nyaman untuk menyimpan argumen register selama eksekusi thunk dan sebagai opsi penelusuran kesalahan (misalnya, membuat argumen mudah ditemukan selama penelusuran kesalahan jika disimpan di alamat rumah 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 wilayah tumpukan ini di seluruh 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 rumah yang berbeda untuk parameter register mereka.

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 of the stack layout for the x64 conversion example.

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

Konstruksi area tumpukan parameter 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 fungsi bingkai. 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 bingkai memiliki kemampuan penuh dari standar panggilan ini dengan pembuangannya.

Jika fungsi bingkai tidak memanggil fungsi lain maka tidak diperlukan untuk menyelaraskan tumpukan (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 ditandatangani saat dijalankan.

perataan malloc

malloc dijamin untuk mengembalikan memori yang cocok diselaraskan untuk menyimpan objek apa pun yang memiliki perataan mendasar dan yang dapat sesuai 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 Visual 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 yang diperluas, yang juga dikenal sebagai jenis yang terlalu selaras. 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. Perataan memori pada batas yang cocok untuk objek yang memerlukan perataan yang diperluas tidak dijamin oleh malloc. Untuk mengalokasikan memori untuk jenis yang terlalu rata, 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 yang kemudian disebut fungsi, seperti yang dibahas dalam Alokasi Tumpukan.

Baca juga

Konvensi perangkat lunak x64
Menyelaraskan
__declspec