Aracılığıyla paylaş


x64 yığın kullanımı

RSP'nin geçerli adresini aşan tüm bellek geçici olarak kabul edilir: İşletim sistemi veya hata ayıklayıcı, kullanıcı hata ayıklama oturumu veya kesme işleyicisi sırasında bu belleğin üzerine yazabilir. Bu nedenle, değerleri bir yığın çerçevesine okumaya veya yazmaya çalışmadan önce RSP her zaman ayarlanmalıdır.

Bu bölümde, yerel değişkenler ve alloca iç için yığın alanı ayırma işlemi ele alınmaktadır.

Yığın ayırma

İşlevin prologu yerel değişkenler, kaydedilmiş yazmaçlar, yığın parametreleri ve yazmaç parametreleri için yığın alanı ayırmadan sorumludur.

Parametre alanı her zaman yığının en altındadır (kullanılsa alloca bile), böylece herhangi bir işlev çağrısı sırasında her zaman dönüş adresine bitişik olur. En az dört girdi içerir, ancak çağrılabilecek herhangi bir işlevin ihtiyaç duyduğu tüm parametreleri tutmak için her zaman yeterli alan içerir. Parametrelerin kendileri hiçbir zaman yığına giriş olmasa bile yazmaç parametreleri için her zaman alan ayrıldığını unutmayın; çağıran, tüm parametreleri için alanın ayrıldığını garanti eder. Giriş adresleri yazmaç bağımsız değişkenleri için gereklidir, dolayısıyla çağrılan işlevin bağımsız değişken listesinin (va_list) veya bağımsız değişkenin adresini alması gerektiğinde bitişik bir alan kullanılabilir. Bu alan ayrıca, thunk yürütme sırasında ve hata ayıklama seçeneği olarak yazmaç bağımsız değişkenlerini kaydetmek için uygun bir yer sağlar (örneğin, giriş adreslerinde giriş kodunda depolanmışlarsa, hata ayıklama sırasında bağımsız değişkenlerin bulunmasını kolaylaştırır). Çağrılan işlevin 4'ten az parametresi olsa bile, bu 4 yığın konumu etkin bir şekilde çağrılan işleve aittir ve parametre kayıt değerlerini kaydetmenin yanı sıra çağrılan işlev tarafından başka amaçlarla kullanılabilir. Bu nedenle çağıran, bir işlev çağrısında bu yığın bölgesine bilgi kaydetmeyebilir.

Bir işlevde alan dinamik olarak ayrılmışsa (alloca), kalıcı olmayan bir yazmaç yığının sabit bölümünün tabanını işaretlemek için çerçeve işaretçisi olarak kullanılmalıdır ve bu kayıt prologa kaydedilip başlatılmalıdır. alloca Kullanıldığında, aynı arayandan gelen çağrıların kayıt parametreleri için farklı giriş adresleri olabileceğini unutmayın.

Yığın her zaman 16 bayt hizalı olarak korunur, ancak giriş listesi içinde (örneğin, dönüş adresi gönderildikten sonra) ve belirli bir çerçeve işlevleri sınıfı için İşlev Türleri'nde belirtilen durumlar dışında.

Aşağıda, A işlevinin yaprak olmayan B işlevini çağırdığı yığın düzeni örneği verilmiştir. A işlevinin prolog'unun yığının alt kısmında B tarafından gerekli olan tüm yazmaç ve yığın parametreleri için zaten alan ayrılmıştır. Çağrı dönüş adresini yönlendirir ve B'nin giriş bölümü yerel değişkenleri, geçici olmayan yazmaçlar ve işlevleri çağırmak için gereken alan için alan ayırır. B kullanıyorsa alloca, alan yerel değişken/kalıcı olmayan yazmaç kaydetme alanı ile parametre yığını alanı arasında ayrılır.

Diagram of the stack layout for the x64 conversion example.

B işlevi başka bir işlevi çağırdığında, dönüş adresi RCX giriş adresinin hemen altına gönderiliyor.

Dinamik parametre yığın alanı yapısı

Bir çerçeve işaretçisi kullanılırsa, parametre yığını alanını dinamik olarak oluşturmak için seçeneği vardır. Bu işlem şu anda x64 derleyicisinde yapılmaz.

İşlev türleri

Temelde iki işlev türü vardır. Yığın çerçevesi gerektiren bir işlev, çerçeve işlevi olarak adlandırılır. Yığın çerçevesi gerektirmeyen bir işleve yaprak işlev adı verilir.

Çerçeve işlevi, yığın alanı ayıran, diğer işlevleri çağıran, kalıcı olmayan kayıtları kaydeden veya özel durum işlemeyi kullanan bir işlevdir. Ayrıca bir işlev tablosu girişi gerektirir. Çerçeve işlevi bir giriş ve bir kapsam gerektirir. Çerçeve işlevi, yığın alanını dinamik olarak ayırabilir ve bir çerçeve işaretçisi kullanabilir. Çerçeve işlevi, bu çağrı standardının tüm özelliklerine sahiptir.

Çerçeve işlevi başka bir işlevi çağırmazsa yığını hizalamak gerekli değildir (Bölüm Yığını Ayırma'da başvurulur).

Yaprak işlev, işlev tablosu girişi gerektirmeyen işlevdir. RSP de dahil olmak üzere geçici olmayan kayıtlarda değişiklik yapamaz; başka bir deyişle herhangi bir işlevi çağıramaz veya yığın alanı ayıramaz. Yürütürken yığını hizalanmamış olarak bırakmasına izin verilir.

malloc hizalaması

malloc'un , temel hizalaması olan ve ayrılan bellek miktarına sığabilecek herhangi bir nesneyi depolamak için uygun şekilde hizalanmış belleği döndürmesi garanti edilir. Temel hizalama, hizalama belirtimi olmadan uygulama tarafından desteklenen en büyük hizalamadan küçük veya buna eşit bir hizalamadır. (Visual C++'da, bir veya 8 bayt için doublegereken hizalama budur. 64 bit platformları hedefleyen kodda 16 bayttır.) Örneğin, dört baytlık ayırma dört baytlık veya daha küçük herhangi bir nesneyi destekleyen bir sınıra hizalanır.

Visual C++, fazla hizalanmış türler olarak da bilinen genişletilmiş hizalamaya sahip türlere izin verir. Örneğin, SSE türleri __m128 ve __m256ile 8'den büyük olan yerlerde n kullanılarak __declspec(align( n )) bildirilen türlerin genişletilmiş hizalaması vardır. Genişletilmiş hizalama gerektiren bir nesne için uygun bir sınırdaki bellek hizalaması tarafından mallocgaranti edilmemektedir. Fazla hizalanmış türler için bellek ayırmak için _aligned_malloc ve ilgili işlevleri kullanın.

alloca

_alloca 16 bayt hizalanmış ve ayrıca çerçeve işaretçisi kullanmak için gereklidir.

Yığın Ayırma'da açıklandığı gibi, ayrılan yığının sonraki işlevlere ait parametreler için ondan sonra alan içermesi gerekir.

Ayrıca bkz.

x64 yazılım kuralları
align
__declspec