Aracılığıyla paylaş


x64 giriş ve bitiş bölümü

Yığın alanı ayıran, diğer işlevleri çağıran, geçici olmayan yazmaçları kaydeden veya özel durum işleme kullanan her işlevin, ilgili işlev tablosu girişiyle ilişkili geri sarma verilerinde adres sınırları açıklanan bir prologu olmalıdır. Daha fazla bilgi için bkz . x64 özel durum işleme. Prolog, gerekirse bağımsız değişken yazmaçlarını giriş adreslerine kaydeder, yığına geçici olmayan yazmaçlar yazar, yığının sabit bölümünü yereller ve geçiciler için ayırır ve isteğe bağlı olarak bir çerçeve işaretçisi oluşturur. İlişkili geri alma verilerinin prolog eylemini tanımlaması ve prolog kodunun etkisini geri almak için gerekli bilgileri sağlaması gerekir.

Yığındaki sabit ayırma birden fazla sayfaysa (yani 4096 bayttan büyükse), yığın ayırma birden fazla sanal bellek sayfasına yayılabilir ve bu nedenle ayırma ayrılmadan önce denetlenmelidir. Prologdan çağrılabilen ve bağımsız değişken kayıtlarından hiçbirini yok içermeyen özel bir yordam bu amaç için sağlanır.

Kalıcı olmayan yazmaçları kaydetmek için tercih edilen yöntem, sabit yığın ayırmadan önce bunları yığına taşımaktır. Sabit yığın ayırma, geçici olmayan yazmaçlar kaydedilmeden önce gerçekleştirilirse, büyük olasılıkla kaydedilen kayıt alanını ele almak için 32 bit yer değiştirme gerekir. (Bildirildiğine göre, yazmaçların gönderimleri taşımalar kadar hızlıdır ve gönderimler arasındaki zımni bağımlılıklara rağmen öngörülebilir gelecek için bu şekilde kalmalıdır.) Geçici olmayan yazmaçlar herhangi bir sırayla kaydedilebilir. Ancak, günlükte geçici olmayan bir kaydın ilk kullanımı kaydı kaydetmek olmalıdır.

Prolog kodu

Tipik bir prolog kodu şu şekilde olabilir:

    mov    [RSP + 8], RCX
    push   R15
    push   R14
    push   R13
    sub    RSP, fixed-allocation-size
    lea    R13, 128[RSP]
    ...

Bu prolog, rcx bağımsız değişkenini giriş konumunda depolar, kalıcı olmayan R13-R15 kayıtlarını kaydeder, yığın çerçevesinin sabit bölümünü ayırır ve sabit ayırma alanına 128 bayt işaret eden bir çerçeve işaretçisi oluşturur. Uzaklık kullanmak, sabit ayırma alanının daha fazlasının tek baytlık uzaklıklarla ele alınmasına olanak tanır.

Sabit ayırma boyutu bir sayfa bellekten büyük veya buna eşitse, RSP'yi değiştirmeden önce bir yardımcı işlev çağrılmalıdır. Bu yardımcı, __chkstkyığının düzgün genişletildiğinden emin olmak için ayrılacak yığın aralığını yoklar. Bu durumda, bunun yerine önceki prolog örneği şöyle olacaktır:

    mov    [RSP + 8], RCX
    push   R15
    push   R14
    push   R13
    mov    RAX,  fixed-allocation-size
    call   __chkstk
    sub    RSP, RAX
    lea    R13, 128[RSP]
    ...

Yardımcı __chkstk , R10, R11 ve koşul kodları dışında hiçbir kaydı değiştirmez. Özellikle, RAX'ı değiştirmeden döndürür ve tüm kalıcı yazmaçları ve bağımsız değişken geçirme yazmaçlarını değiştirilmeden bırakır.

Epilog kodu

Bir işleve yapılan her çıkışta epilog kodu vardır. Normalde yalnızca bir giriş listesi olsa da, birçok epilog olabilir. Epilog kodu yığını sabit ayırma boyutuna (gerekirse) kırpar, sabit yığın ayırmasını serbestleştirir, kayıtlı değerlerini yığından çıkararak kalıcı olmayan kayıtları geri yükler ve döndürür.

Epilog kodu, özel durumlar ve kesmeler aracılığıyla güvenilir bir şekilde geri almak için geri sarma kodunun katı bir kural kümesine uyması gerekir. Bu kurallar, her bir tanımlamayı açıklamak için ek veri gerekmediğinden gereken geri sarma verilerinin miktarını azaltır. Bunun yerine, geri sarma kodu bir epilog tanımlamak için bir kod akışında ileri doğru tarama yaparak bir epilog yürütüldüğünü belirleyebilir.

İşlevde çerçeve işaretçisi kullanılmazsa, epilogun önce yığının sabit bölümünü serbest bırakması gerekir, kalıcı olmayan yazmaçlar açılır ve denetim çağrı işlevine döndürülür. Örneğin,

    add      RSP, fixed-allocation-size
    pop      R13
    pop      R14
    pop      R15
    ret

İşlevde bir çerçeve işaretçisi kullanılıyorsa, yığın, epilog yürütülmadan önce sabit ayırmasına göre kırpılmalıdır. Bu eylem teknik olarak kapsamın bir parçası değildir. Örneğin, daha önce kullanılan prologu geri almak için aşağıdaki kapsam kullanılabilir:

    lea      RSP, -128[R13]
    ; epilogue proper starts here
    add      RSP, fixed-allocation-size
    pop      R13
    pop      R14
    pop      R15
    ret

Uygulamada, bir çerçeve işaretçisi kullanıldığında, RSP'yi iki adımda ayarlamak için iyi bir neden yoktur, bu nedenle bunun yerine aşağıdaki kapsam kullanılır:

    lea      RSP, fixed-allocation-size - 128[R13]
    pop      R13
    pop      R14
    pop      R15
    ret

Bu formlar bir epilog için tek yasal formlardır. Bir veya 'den add RSP,constant ve ardından sıfır veya daha fazla 8 baytlık kayıt pop'larından oluşan bir seriden ve veya return bir jmp'den oluşmalıdır.lea RSP,constant[FPReg] (Epilogda yalnızca bir deyim alt kümesine jmp izin velanabilir. Alt küme yalnızca ModRM mod alanı değerinin jmp 00 olduğu ModRM bellek başvurularına sahip deyim sınıfıdır. ModRM mod alanı değeri 01 veya 10 ile girişteki deyimlerin kullanılması jmp yasaktır. İzin verilebilen ModRM başvuruları hakkında daha fazla bilgi için bkz. AMD x86-64 Mimarisi Programcı El İle Ses 3: Genel Amaçlı ve Sistem Yönergeleri'ndeki Tablo A-15.) Başka hiçbir kod görünemez. Özellikle, bir sonuç değerinin yüklenmesi dahil olmak üzere bir kapsam içinde hiçbir şey zamanlanamaz.

Çerçeve işaretçisi kullanılmadığında, yığının sabit bölümünü serbest bırakmak için epilog kullanılmalıdır add RSP,constant . Bunun yerine kullanamayabilir lea RSP,constant[RSP] . Bu kısıtlama mevcut olduğundan, sarma kodunun epilog ararken tanıyacak daha az deseni vardır.

Bu kuralların takip edilmesi, geri sarma kodunun şu anda bir epilog yürütülmekte olduğunu belirlemesine ve çağrı işlevinin bağlamını yeniden oluşturmasına izin vermek için epilogun geri kalanının yürütülmesini simüle etmesine olanak tanır.

Ayrıca bkz.

x64 Yazılım Kuralları