Aracılığıyla paylaş


x64 ABI kurallarına genel bakış

Bu konu, x86 mimarisinin 64 bit uzantısı olan x64 için temel uygulama ikili arabirimini (ABI) açıklar. Çağrı kuralı, tür düzeni, yığın ve kayıt kullanımı gibi konuları ve daha fazlasını kapsar.

x64 çağrı kuralları

x86 ile x64 arasındaki iki önemli fark şunlardır:

  • 64 bit adresleme özelliği
  • Genel kullanım için on altı 64 bit yazmaç.

Genişletilmiş yazmaç kümesi göz önünde bulundurulduğunda x64, __fastcall çağırma kuralını ve RISC tabanlı özel durum işleme modelini kullanır.

Kural, __fastcall ilk dört bağımsız değişken için yazmaçları ve daha fazla bağımsız değişken geçirmek için yığın çerçevesini kullanır. Kayıt kullanımı, yığın parametreleri, dönüş değerleri ve yığın geri sarma gibi x64 çağrı kuralıyla ilgili ayrıntılar için bkz . x64 çağırma kuralı.

Çağırma kuralı hakkında __vectorcall daha fazla bilgi için bkz __vectorcall. .

x64 derleyici iyileştirmesini etkinleştirme

Aşağıdaki derleyici seçeneği uygulamanızı x64 için iyileştirmenize yardımcı olur:

x64 türü ve depolama düzeni

Bu bölümde x64 mimarisi için veri türlerinin depolanması açıklanmaktadır.

Skaler türler

Herhangi bir hizalamayla verilere erişmek mümkün olsa da, performans kaybını önlemek için verileri doğal sınırına veya doğal sınırının bir katına hizalayın. Numaralandırmalar sabit tamsayılardır ve 32 bit tamsayılar olarak değerlendirilir. Aşağıdaki tabloda, aşağıdaki hizalama değerlerini kullanarak hizalamayla ilgili olarak tür tanımı ve veriler için önerilen depolama açıklanmaktadır:

  • Bayt - 8 bit
  • Word - 16 bit
  • Çift kelime - 32 bit
  • Dörtlü - 64 bit
  • Octaword - 128 bit
Skaler tür C veri türü Depolama boyutu (bayt cinsinden) Önerilen hizalama
INT8 char 1 Bayt
UINT8 unsigned char 1 Bayt
INT16 short 2 Word
UINT16 unsigned short 2 Word
INT32 int, long 4 Çift kelime
UINT32 unsigned int, unsigned long 4 Çift kelime
INT64 __int64 8 Dörtlü
UINT64 unsigned __int64 8 Dörtlü
FP32 (tek duyarlıklı) float 4 Çift kelime
FP64 (çift duyarlık) double 8 Dörtlü
POINTER * 8 Dörtlü
__m64 struct __m64 8 Dörtlü
__m128 struct __m128 16 Octaword

x64 toplama ve birleşim düzeni

Diziler, yapılar ve birleşimler gibi diğer türlerin tutarlı toplama ve birleşim depolama ve veri alımını sağlayan daha katı hizalama gereksinimleri vardır. Dizi, yapı ve birleşim tanımları şunlardır:

  • Dizi

    Bitişik veri nesnelerinden oluşan sıralı bir grup içerir. Her nesne bir öğe olarak adlandırılır. Dizideki tüm öğeler aynı boyuta ve veri türüne sahiptir.

  • Yapı

    Sıralı bir veri nesnesi grubu içerir. Bir dizinin öğelerinden farklı olarak, bir yapının üyeleri farklı veri türlerine ve boyutlarına sahip olabilir.

  • Birleşim

    Adlandırılmış üye kümesinden herhangi birini tutan nesne. Adlandırılmış kümenin üyeleri herhangi bir türde olabilir. Birleşim için ayrılan depolama, bu birleşimin en büyük üyesi için gereken depolama alanına ve hizalama için gereken doldurmaya eşittir.

Aşağıdaki tabloda, birleşimlerin ve yapıların skaler üyeleri için kesinlikle önerilen hizalama gösterilmektedir.

Skaler Tür C Veri Türü Gerekli Hizalama
INT8 char Bayt
UINT8 unsigned char Bayt
INT16 short Word
UINT16 unsigned short Word
INT32 int, long Çift kelime
UINT32 unsigned int, unsigned long Çift kelime
INT64 __int64 Dörtlü
UINT64 unsigned __int64 Dörtlü
FP32 (tek duyarlıklı) float Çift kelime
FP64 (çift duyarlık) double Dörtlü
POINTER * Dörtlü
__m64 struct __m64 Dörtlü
__m128 struct __m128 Octaword

Aşağıdaki toplama hizalama kuralları geçerlidir:

  • Dizinin hizalaması, dizinin öğelerinden birinin hizalaması ile aynıdır.

  • Bir yapının veya birleşimin başlangıcının hizalaması, herhangi bir üyenin en yüksek hizalamasıdır. Yapı veya birleşim içindeki her üye, önceki tabloda tanımlandığı gibi uygun hizalamaya yerleştirilmelidir. Bu, önceki üyeye bağlı olarak örtük iç doldurma gerektirebilir.

  • Yapı boyutu, hizalamasının tam sayı katı olmalıdır ve bu da son üyeden sonra doldurma gerektirebilir. Yapılar ve birleşimler diziler halinde gruplandırılabildiğinden, bir yapı veya birleşimin her dizi öğesi daha önce belirlenen uygun hizalamada başlamalıdır ve bitmelidir.

  • Önceki kurallar korunduktan sonra verileri hizalama gereksinimlerinden daha büyük olacak şekilde hizalamak mümkündür.

  • Tek bir derleyici, boyut nedenleriyle bir yapının ambalajını ayarlayabilir. Örneğin, /Zp (Yapı Üyesi Hizalaması), yapıların ambalajının ayarlanmasını sağlar.

x64 yapı hizalama örnekleri

Aşağıdaki dört örnekte her biri hizalanmış bir yapı veya birleşim bildirilir ve buna karşılık gelen şekiller bu yapının veya birleşimin bellekteki düzenini gösterir. Şekildeki her sütun bir bellek baytını temsil eder ve sütundaki sayı bu bayt yer değiştirmesini gösterir. Her şeklin ikinci satırındaki ad, bildirimdeki bir değişkenin adına karşılık gelir. Gölgeli sütunlar, belirtilen hizalamayı elde etmek için gereken doldurmayı gösterir.

Örnek 1

// Total size = 2 bytes, alignment = 2 bytes (word).

_declspec(align(2)) struct {
    short a;      // +0; size = 2 bytes
}

Örnek 1 yapı düzenini gösteren diyagram.

Örnek 2

// Total size = 24 bytes, alignment = 8 bytes (quadword).

_declspec(align(8)) struct {
    int a;       // +0; size = 4 bytes
    double b;    // +8; size = 8 bytes
    short c;     // +16; size = 2 bytes
}

Örnek 2 yapı düzenini gösteren diyagram.

Örnek 3

// Total size = 12 bytes, alignment = 4 bytes (doubleword).

_declspec(align(4)) struct {
    char a;       // +0; size = 1 byte
    short b;      // +2; size = 2 bytes
    char c;       // +4; size = 1 byte
    int d;        // +8; size = 4 bytes
}

Örnek 3 yapı düzenini gösteren diyagram.

Örnek 4

// Total size = 8 bytes, alignment = 8 bytes (quadword).

_declspec(align(8)) union {
    char *p;      // +0; size = 8 bytes
    short s;      // +0; size = 2 bytes
    long l;       // +0; size = 4 bytes
}

Örnek 4 birleşim düzenini gösteren diyagram.

Bit Alanları

Yapı biti alanları 64 bit ile sınırlıdır ve imzalanmamış int, unsigned int, int64 veya unsigned int64 türünde olabilir. Tür sınırını geçen bit alanları, bit alanını bir sonraki tür hizalamasına hizalamak için bitleri atlar. Örneğin, tamsayı bit alanları 32 bit sınırı geçmeyebilir.

x86 derleyicisiyle çakışmalar

4 bayttan büyük veri türleri, bir uygulamayı derlemek için x86 derleyicisini kullandığınızda yığına otomatik olarak hizalanmamıştır. x86 derleyicisinin mimarisi 4 bayt hizalanmış bir yığın olduğundan, 4 bayttan büyük olan her şey (örneğin, 64 bitlik bir tamsayı) otomatik olarak 8 baytlık bir adrese hizalanamaz.

Hizalanmamış verilerle çalışmanın iki etkisi vardır.

  • Hizalanmamış konumlara erişmek, hizalanmış konumlara erişmek için gerekenden daha uzun sürebilir.

  • Hizalanmamış konumlar birbirine kenetlenmiş işlemlerde kullanılamaz.

Daha katı bir hizalamaya ihtiyacınız varsa değişken bildirimlerinizde kullanın __declspec(align(N)) . Bu, derleyicinin yığını belirtimlerinize uyacak şekilde dinamik olarak hizalamasına neden olur. Ancak, yığının çalışma zamanında dinamik olarak ayarlanması uygulamanızın daha yavaş yürütülmesine neden olabilir.

x64 yazmaç kullanımı

x64 mimarisi, 16 genel amaçlı yazmaç (bundan sonra tamsayı yazmaçları olarak adlandırılır) ve kayan nokta kullanımı için 16 XMM/YMM yazmacı sağlar. Geçici yazmaçlar, arayan tarafından bir aramada yok edildiği varsayılan karalama yazmaçlarıdır. Geçici olmayan yazmaçlar, bir işlev çağrısında değerlerini korumak için gereklidir ve kullanılırsa çağıran tarafından kaydedilmelidir.

Volatilite ve korumayı kaydetme

Aşağıdaki tabloda, her yazmaç işlevinin işlev çağrıları arasında nasıl kullanıldığı açıklanmaktadır:

Kaydol Durum Kullanma
RAX Uçucu Dönüş değeri yazmaç
RCX Uçucu İlk tamsayı bağımsız değişkeni
RDX Uçucu İkinci tamsayı bağımsız değişkeni
R8 Uçucu Üçüncü tamsayı bağımsız değişkeni
R9 Uçucu Dördüncü tamsayı bağımsız değişkeni
R10:R11 Uçucu Arayan tarafından gerektiği gibi korunmalıdır; syscall/sysret yönergelerinde kullanılır
R12:R15 Kalıcı Çağıran tarafından korunmalıdır
RDI Kalıcı Çağıran tarafından korunmalıdır
RSI Kalıcı Çağıran tarafından korunmalıdır
RBX Kalıcı Çağıran tarafından korunmalıdır
RBP Kalıcı Çerçeve işaretçisi olarak kullanılabilir; callee tarafından korunmalıdır
RSP Kalıcı Yığın işaretçisi
XMM0, YMM0 Uçucu İlk FP bağımsız değişkeni; kullanıldığında ilk vektör türü bağımsız değişkeni __vectorcall
XMM1, YMM1 Uçucu İkinci FP bağımsız değişkeni; kullanıldığında ikinci vektör türü bağımsız değişkeni __vectorcall
XMM2, YMM2 Uçucu Üçüncü FP bağımsız değişkeni; kullanıldığında üçüncü vektör türü bağımsız değişkeni __vectorcall
XMM3, YMM3 Uçucu Dördüncü FP bağımsız değişkeni; kullanıldığında dördüncü vektör türü bağımsız değişkeni __vectorcall
XMM4, YMM4 Uçucu Arayan tarafından gerektiği gibi korunmalıdır; kullanıldığında beşinci vektör türü bağımsız değişkeni __vectorcall
XMM5, YMM5 Uçucu Arayan tarafından gerektiği gibi korunmalıdır; kullanıldığında altıncı vektör türü bağımsız değişkeni __vectorcall
XMM6:XMM15, YMM6:YMM15 Geçici Olmayan (XMM), Geçici (YMM'nin üst yarısı) Callee tarafından korunmalıdır. YMM kayıtları arayan tarafından gerektiği gibi korunmalıdır.

İşlev çıkışında ve C Çalışma Zamanı Kitaplığı çağrılarına ve Windows sistem çağrılarına işlev girişinde, CPU bayrakları yazmaçlarındaki yön bayrağının temizlenmesi beklenir.

Yığın kullanımı

x64'te yığın ayırma, hizalama, işlev türleri ve yığın çerçeveleri hakkında ayrıntılı bilgi için bkz . x64 yığın kullanımı.

Prolog ve epilog

Yığın alanı ayıran, diğer işlevleri çağıran, geçici olmayan yazmaçları kaydeden veya özel durum işlemeyi kullanan her işlevin, adres sınırları ilgili işlev tablosu girişiyle ilişkili geri sarma verilerinde açıklanan bir prologu ve bir işleve yapılan her çıkışta kapsamları olmalıdır. x64'te gerekli giriş ve kapsam koduyla ilgili ayrıntılar için bkz . x64 giriş ve bitiş.

x64 özel durum işleme

x64 üzerinde yapılandırılmış özel durum işleme ve C++ özel durum işleme davranışını uygulamak için kullanılan kurallar ve veri yapıları hakkında bilgi için bkz . x64 özel durum işleme.

İç ve satır içi bütünleştirilmiş kod

x64 derleyicisinin kısıtlamalarından biri satır içi derleyici desteği değildir. Bu, C veya C++ dilinde yazılamayacak işlevlerin alt yordam olarak veya derleyici tarafından desteklenen iç işlevler olarak yazılması gerekeceği anlamına gelir. Bazı işlevler performansa duyarlıyken diğerleri duyarlı değildir. Performansa duyarlı işlevler iç işlevler olarak uygulanmalıdır.

Derleyici tarafından desteklenen iç öğeler Derleyici iç bilgileri bölümünde açıklanmıştır.

x64 resim biçimi

x64 yürütülebilir görüntü biçimi PE32+. Yürütülebilir görüntüler (hem DLL'ler hem de EXE'ler) en fazla 2 gigabayt boyutuyla sınırlıdır, bu nedenle statik görüntü verilerini ele almak için 32 bit yer değiştirme ile göreli adresleme kullanılabilir. Bu veriler içeri aktarma adresi tablosunu, dize sabitlerini, statik genel verileri vb. içerir.

Ayrıca bkz.

Çağırma Kuralları