Aracılığıyla paylaş


ARM64EC ABI kurallarına genel bakış

ARM64EC, ARM64 ikili dosyalarının x64 koduyla yerel olarak ve birlikte çalışmasını sağlayan bir uygulama ikili arabirimidir (ABI). Özellikle, ARM64EC ABI çağrı kuralı, yığın kullanımı ve veri hizalama dahil olmak üzere x64 yazılım kurallarını izler ve ARM64EC ve x64 kodunu birlikte çalışabilir hale getirir. İşletim sistemi ikilinin x64 bölümüne öykünmektedir. (ARM64EC içindeki EC, öykünme uyumlu anlamına gelir.)

x64 ve ARM64 ABI'leri hakkında daha fazla bilgi için bkz. x64 ABI kurallarına genel bakış ve ARM64 ABI kurallarına genel bakış.

ARM64EC, x64 ve ARM tabanlı mimariler arasındaki bellek modeli farklarını çözmez. Daha fazla bilgi için bkz . Yaygın Visual C++ ARM geçiş sorunları.

Tanımlar

  • ARM64 - Geleneksel ARM64 kodu içeren ARM64 işlemleri için kod akışı.
  • ARM64EC - x64 koduyla birlikte çalışabilirlik sağlamak için ARM64 yazmaç kümesinin bir alt kümesini kullanan kod akışı.

Eşlemeyi kaydetme

x64 işlemlerinde kod ARM64EC çalışan iş parçacıkları olabilir. Bu nedenle bir x64 yazmaç bağlamı almak her zaman mümkündür ARM64EC 1:1 ile eşlenen ARM64 çekirdek yazmaçlarının bir alt kümesini kullanır. Daha da önemlisi, ARM64EC' den x18İş Parçacığı Ortam Bloğu (TEB) adresini okumak dışında hiçbir zaman bu alt küme dışındaki yazmaçları kullanmaz.

Bazı veya birçok işlev ARM64EC olarak yeniden derlendiğinde yerel ARM64 işlemleri performansta gerilememelidir. ABI, performansı korumak için şu ilkeleri izler:

  • ARM64EC kayıt alt kümesi, ARM64 işlev çağırma kuralının parçası olan tüm yazmaçları içerir.

  • ARM64EC çağırma kuralı, ARM64 çağırma kuralıyla doğrudan eşler.

Özel çağrı kurallarını ve yazmaçları kullanma gibi __chkstk_arm64ec özel yardımcı yordamlar. Bu yazmaçlar, yazmaçların ARM64EC alt kümesine de eklenir.

Tamsayı yazmaçları için kayıt eşlemesi

ARM64EC kaydetme x64 yazmaç ARM64EC çağırma kuralı ARM64 çağırma kuralı x64 çağırma kuralı
x0 rcx volatile volatile volatile
x1 rdx volatile volatile volatile
x2 r8 volatile volatile volatile
x3 r9 volatile volatile volatile
x4 r10 volatile volatile volatile
x5 r11 volatile volatile volatile
x6 mm1 (düşük 64 bit x87 yazmaç R1 ) volatile volatile volatile
x7 mm2 (düşük 64 bit x87 yazmaç R2 ) volatile volatile volatile
x8 rax volatile volatile volatile
x9 mm3 (düşük 64 bit x87 yazmaç R3 ) volatile volatile volatile
x10 mm4 (düşük 64 bit x87 yazmaç R4 ) volatile volatile volatile
x11 mm5 (düşük 64 bit x87 yazmaç R5 ) volatile volatile volatile
x12 mm6 (düşük 64 bit x87 yazmaç R6 ) volatile volatile volatile
x13 Yok Izin verilme -yen volatile Yok
x14 Yok Izin verilme -yen volatile Yok
x15 mm7 (düşük 64 bit x87 yazmaç R7 ) volatile volatile volatile
x16 x87 R0-R3 yazmaçlarının her birinin yüksek 16 biti volatile(xip0) volatile(xip0) volatile
x17 x87 R4-R7 yazmaçlarının her birinin yüksek 16 biti volatile(xip1) volatile(xip1) volatile
x18 GS.base sabit (TEB) sabit (TEB) sabit (TEB)
x19 r12 geçici olmayan geçici olmayan geçici olmayan
x20 r13 geçici olmayan geçici olmayan geçici olmayan
x21 r14 geçici olmayan geçici olmayan geçici olmayan
x22 r15 geçici olmayan geçici olmayan geçici olmayan
x23 Yok Izin verilme -yen geçici olmayan Yok
x24 Yok Izin verilme -yen geçici olmayan Yok
x25 rsi geçici olmayan geçici olmayan geçici olmayan
x26 rdi geçici olmayan geçici olmayan geçici olmayan
x27 rbx geçici olmayan geçici olmayan geçici olmayan
x28 Yok Izin verilme -yen Izin verilme -yen Yok
fp rbp geçici olmayan geçici olmayan geçici olmayan
lr mm0 (düşük 64 bit x87 yazmaç R0 ) her ikisi her ikisi her ikisi
sp rsp geçici olmayan geçici olmayan geçici olmayan
pc rip yönerge işaretçisi yönerge işaretçisi yönerge işaretçisi
PSTATEalt küme: NZSS/C//V/1, 2 RFLAGS Alt küme -sini: SF/ZF/CF/OF/TF volatile volatile volatile
Yok RFLAGS Alt küme -sini: PF/AF Yok Yok volatile
Yok RFLAGS Alt küme -sini: DF Yok Yok geçici olmayan

1 ve RFLAGSarasında PSTATE eşlemeleri doğrudan okumak, yazmak veya bilgi işlemden kaçının. Bu bitler gelecekte kullanılabilir ve değiştirilebilir.

2 ARM64EC taşıma bayrağı C , çıkarma işlemleri için x64 taşıma bayrağının CF tersidir. Bayrağın geçici olması ve bu nedenle (ARM64EC ve x64) işlevleri arasında geçiş yaparken çöpe atılması nedeniyle özel bir işleme yoktur.

Vektör yazmaçları için kayıt eşlemesi

ARM64EC kaydetme x64 yazmaç ARM64EC çağırma kuralı ARM64 çağırma kuralı x64 çağırma kuralı
v0-v5 xmm0-xmm5 volatile volatile volatile
v6-v7 xmm6-xmm7 volatile volatile geçici olmayan
v8-v15 xmm8-xmm15 geçici 1 geçici 1 geçici olmayan
v16-v31 xmm16-xmm31 Izin verilme -yen volatile izin verilmeyen (x64 öykünücüsü AVX-512'i desteklemez)
FPCR 2 MXCSR[15:6] geçici olmayan geçici olmayan geçici olmayan
FPSR 2 MXCSR[5:0] volatile volatile volatile

1 Bu ARM64 yazmaçları, alt 64 bitlerin geçici olmayan ancak üst 64 bitlerin geçici olması için özeldir. Bir x64 çağıranı açısından bakıldığında, arayan kişi verileri çöpe atacağından etkili bir şekilde geçicidir.

2 ve FPSReşlemelerini doğrudan okumak, yazmak veya bilgi işlemden FPCR kaçının. Bu bitler gelecekte kullanılabilir ve değiştirilebilir.

Yapı paketleme

ARM64EC, ARM64EC kod ile x64 kodu arasında birlikte çalışabilirlik sağlamak için x64 için kullanılan aynı yapı paketleme kurallarını izler. x64 yapı paketleme hakkında daha fazla bilgi ve örnek için bkz . x64 ABI kurallarına genel bakış.

Öykünme yardımcı ABI yordamları

ARM64EC kod ve thunks , x64 ve ARM64EC işlevleri arasında geçiş yapmak için öykünme yardımcı yordamlarını kullanır.

Aşağıdaki tabloda her özel ABI yordamı ve ABI'nin kullandığı yazmaçlar açıklanmaktadır. Yordamlar, ABI sütunu altında listelenen korunan yazmaçları değiştirmez. Listelenmemiş yazmaçlar hakkında hiçbir varsayımda bulunulmamalıdır. Diskte, ABI yordamı işaretçileri null olur. Yükleme zamanında yükleyici, işaretçileri x64 öykünücü yordamlarına işaret eden şekilde güncelleştirir.

Veri Akışı Adı Açıklama ABI
__os_arm64x_dispatch_call_no_redirect Bir x64 hedefini çağırmak için çıkış thunk tarafından çağrılır (x64 işlevi veya x64 hızlı ileri dizisi). Yordam, ARM64EC dönüş adresini (kayıtta LR ) ve ardından x64 öykünücüsünü çağıran bir blr x16 yönergenin başarılı olduğu yönergenin adresini yönlendirir. Ardından yönergeyi blr x16 çalıştırır (rax) içinde x8 dönüş değeri
__os_arm64x_dispatch_ret x64 çağıranı geri dönmek için bir giriş thunk tarafından çağrılır. Yığından x64 dönüş adresini açar ve atlamak için x64 öykünücüsünü çağırır Yok
__os_arm64x_check_call Çıkış thunk işaretçisi ve yürütülecek dolaylı ARM64EC hedef adresi ile ARM64EC kod tarafından çağrılır. ARM64EC hedefi düzeltme eki uygulanabilir olarak kabul edilir ve yürütme her zaman çağrılan verilerle veya değiştirilmiş verilerle çağırana geri döner Bağımsız Değişkenler:
x9: Hedef adres
x10: Çıkış thunk adresi
x11: Hızlı ileriye doğru sıra adresi

Dışarıya:
x9: Hedef işlev saptırıldıysa, ileri sarma dizisinin adresini içerir
x10: Çıkış thunk adresi
x11: İşlev saptırıldıysa çıkış thunk adresini içerir. Aksi takdirde hedef adres atlandı

Korunan yazmaçlar: x0-x8, x15 (chkstk). ve q0-q7
__os_arm64x_check_icall x64 veya ARM64EC hedef adrese atlamayı işlemek için çıkış thunk işaretçisiyle ARM64EC kodu tarafından çağrılır. Hedef x64 ise ve x64 koduna düzeltme eki uygulamadıysa, yordam hedef adres kaydını ayarlar. Varsa işlevin ARM64EC sürümüne işaret eder. Aksi takdirde, kayıt defteri x64 hedefine geçiş çıkış thunk işaret etmek için ayarlar. Ardından çağrı ARM64EC koduna döner ve ardından kayıttaki adrese atlar. Bu yordam, hedef adresin __os_arm64x_check_callderleme zamanında bilinmediği iyileştirilmiş olmayan bir sürümüdür.

Dolaylı çağrının arama sitesinde kullanılır
Bağımsız Değişkenler:
x9: Hedef adres
x10: Çıkış thunk adresi
x11: Hızlı ileriye doğru sıra adresi

Dışarıya:
x9: Hedef işlev saptırıldıysa, ileri sarma dizisinin adresini içerir
x10: Çıkış thunk adresi
x11: İşlev saptırıldıysa çıkış thunk adresini içerir. Aksi takdirde hedef adres atlandı

Korunan yazmaçlar: x0-x8, x15 (chkstk) ve q0-q7
__os_arm64x_check_icall_cfg __os_arm64x_check_icall Aynı ama aynı zamanda belirtilen adresin geçerli bir Denetim Akışı Grafı dolaylı çağrı hedefi olup olmadığını denetler Bağımsız Değişkenler:
x10: Çıkış thunk'un adresi
x11: Hedef işlevin adresi

Dışarıya:
x9: Hedef x64 ise işlevin adresidir. Aksi takdirde, tanımsız
x10: Çıkış thunk'un adresi
x11: Hedef x64 ise çıkış thunk adresini içerir. Aksi takdirde işlevin adresi

Korunan yazmaçlar: x0-x8, x15 (chkstk) ve q0-q7
__os_arm64x_get_x64_information Canlı x64 yazmaç bağlamının istenen bölümünü alır _Function_class_(ARM64X_GET_X64_INFORMATION) NTSTATUS LdrpGetX64Information(_In_ ULONG Type, _Out_ PVOID Output, _In_ PVOID ExtraInfo)
__os_arm64x_set_x64_information Canlı x64 yazmaç bağlamının istenen bölümünü ayarlar _Function_class_(ARM64X_SET_X64_INFORMATION) NTSTATUS LdrpSetX64Information(_In_ ULONG Type,_In_ PVOID Input, _In_ PVOID ExtraInfo)
__os_arm64x_x64_jump İmzasız ayarlayıcıda ve herhangi bir imzaya sahip olabilecek başka bir işleve çağrıyı doğrudan iletan (jmp) diğer thunk'larda kullanılır ve doğru thunk'un olası uygulamasını gerçek hedefe erteler Bağımsız Değişkenler:
x9: atlamayı hedefle

Tüm parametre yazmaçları korunur (iletilir)

Dönüştürücü

Thunks, birbirini çağıran ARM64EC ve x64 işlevlerini destekleyen alt düzey mekanizmalardır. İki tür vardır: ARM64EC işlevleri girmek için giriş thunks ve x64 işlevlerini çağırmak için thunk'lardan çıkın.

Giriş thunk ve iç giriş thunks: ARM64EC işlev çağrısına x64

Bir C/C++ işlevi ARM64EC olarak derlendiğinde x64 çağıranlarını desteklemek için, araç zinciri ARM64EC makine kodundan oluşan tek bir giriş thunk oluşturur. İçsellerin kendi giriş thunk'ları vardır. Diğer tüm işlevler eşleşen bir çağrı kuralına, parametrelerine ve dönüş türüne sahip tüm işlevlerle bir giriş thunk'unu paylaşır. Thunk'un içeriği C/C++ işlevinin çağırma kuralına bağlıdır.

Thunk, parametreleri ve dönüş adresini işlemeye ek olarak, ARM64EC vektör yazmaç eşlemesinin neden olduğu ARM64EC ve x64 vektör yazmaçları arasındaki volatilite farklarını da bir araya getirmektedir:

ARM64EC kaydetme x64 yazmaç ARM64EC çağırma kuralı ARM64 çağırma kuralı x64 çağırma kuralı
v6-v15 xmm6-xmm15 geçici, ancak giriş thunk içinde kaydedilmiş/geri yüklenen (x64 to ARM64EC) geçici veya kısmen geçici üst 64 bit geçici olmayan

Giriş thunk aşağıdaki eylemleri gerçekleştirir:

Parametre numarası Yığın kullanımı
0-4 ARM64EC v6 ve v7 çağıran tarafından ayrılan giriş alanında depolar

Çağrılan ARM64EC olduğundan ve ev alanı olarak belirtilmemiş olduğundan, depolanan değerler tıkanmaz.

Yığında fazladan 128 bayt ayırır ve aracılığıyla ARM64EC v8 depolar v15.
5-8 x4 = yığından 5. parametre
x5 = yığından 6. parametre
x6 = yığından 7. parametre
x7 = yığından 8. parametre

Parametre SIMD ise, v4-v7 bunun yerine yazmaçlar kullanılır
9+ Yığında bayt ayırır AlignUp(NumParams - 8 , 2) * 8 . *

9. ve kalan parametreleri bu alana kopyalar

* Değeri çift bir sayıya hizalamak, yığının 16 bayta hizalı kalmasını garanti eder

İşlev 32 bitlik bir tamsayı parametresi kabul ederse, thunk'un üst kaydın tam 64 biti yerine yalnızca 32 bit göndermesine izin verilir.

Ardından thunk, ARM64EC işlevini çağırmak için bir ARM64 bl yönergesi kullanır. İşlev döndürdüğünde thunk:

  1. Yığın ayırmalarını geri alır
  2. __os_arm64x_dispatch_ret x64 dönüş adresini açmak ve x64 öykünmesini sürdürmek için öykünücü yardımcısını çağırır.

Çıkış thunk: x64 işlev çağrısına ARM64EC

Bir ARM64EC C/C++ işlevinin olası x64 koduna yaptığı her çağrı için MSVC araç zinciri bir çıkış thunk oluşturur. thunk'un içeriği, x64 çağıranın parametrelerine ve çağıranın standart çağırma kuralını veya __vectorcallkullanıp kullanmadığına bağlıdır. Derleyici bu bilgileri çağıranın işlev bildiriminden alır.

İlk olarak, thunk, yığının 16 baytla hizalandığından emin olmak için ARM64EC lr yazmaçtaki dönüş adresini ve 8 baytlık sahte bir değeri iletir. İkinci olarak, thunk parametreleri işler:

Parametre numarası Yığın kullanımı
0-4 Yığında 32 bayt ev alanı ayırır
5-8 Yığında daha yüksek baytlar AlignUp(NumParams - 4, 2) * 8 ayırır. *

5. ve sonraki parametreleri ARM64EC x4-x7 bu ek alana kopyalar
9+ 9. ve kalan parametreleri ek alana kopyalar

* Değeri çift bir sayıya hizalamak, yığının 16 bayta hizalı kalmasını garanti eder.

Üçüncüsü, thunk x64 işlevini çalıştırmak için x64 öykünücüsünü çağırmak için öykünücü yardımcısını çağırır __os_arm64x_dispatch_call_no_redirect . Çağrı bir blr x16 yönerge olmalıdır (rahatça, x16 geçici bir kayıttır). blr x16 x64 öykünücüsü bu yönergeyi ipucu olarak ayrıştırdığından bir yönerge gereklidir.

x64 işlevi genellikle bir x64 ret yönergesi kullanarak öykünücü yardımcısına geri dönmeye çalışır. Bu noktada, x64 öykünücüsü ARM64EC kodda olduğunu algılar. Ardından ARM64 yönergesi olan önceki 4 blr x16 baytlık ipucunu okur. Bu ipucu dönüş adresinin bu yardımcıda olduğunu gösterdiğinden, öykünücü doğrudan bu adrese atlar.

x64 işlevinin, x64 jmp ve calldahil olmak üzere herhangi bir dal yönergesini kullanarak öykünücü yardımcısına dönmesine izin verilir. Öykünücü bu senaryoları da işler.

Yardımcı thunk'a döndüğünde, thunk:

  1. Yığın ayırmayı geri alır
  2. ARM64EC lr kaydını açar
  3. ARM64 ret lr yönergesi yürütür.

ARM64EC işlev adı dekorasyonu

ARM64EC işlev adı, dile özgü herhangi bir dekorasyondan sonra uygulanan ikincil bir dekorasyona sahiptir. C bağlantısı olan işlevler için (C olarak derlenmiş veya kullanılarak extern "C"), # ada bir eklenir. C++ ile dekore edilmiş işlevler için ada bir $$h etiket eklenir.

foo         => #foo
?foo@@YAHXZ => ?foo@@$$hYAHXZ

__vectorcall

ARM64EC araç zinciri şu anda desteklemez __vectorcall. Derleyici, ARM64EC ile kullanımı algıladığında __vectorcall bir hata yayar.

Ayrıca bkz.

ARM64EC ABI ve derleme kodunu anlama
Yaygın Visual C++ ARM geçiş sorunları
Süslü adlar