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 |
PSTATE alt küme: N Z SS /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 RFLAGS
arası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 FPSR
eş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 adresx10 : Çıkış thunk adresix11 : Hızlı ileriye doğru sıra adresiDışarıya: x9 : Hedef işlev saptırıldıysa, ileri sarma dizisinin adresini içerirx10 : Çıkış thunk adresix11 : İş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_call derleme 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 adresx10 : Çıkış thunk adresix11 : Hızlı ileriye doğru sıra adresiDışarıya: x9 : Hedef işlev saptırıldıysa, ileri sarma dizisinin adresini içerirx10 : Çıkış thunk adresix11 : İş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 adresix11 : Hedef işlevin adresiDışarıya: x9 : Hedef x64 ise işlevin adresidir. Aksi takdirde, tanımsızx10 : Çıkış thunk'un adresix11 : Hedef x64 ise çıkış thunk adresini içerir. Aksi takdirde işlevin adresiKorunan 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ı hedefleTü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. parametrex5 = yığından 6. parametrex6 = yığından 7. parametrex7 = yığından 8. parametreParametre 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:
- Yığın ayırmalarını geri alır
__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 __vectorcall
kullanı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 call
dahil 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:
- Yığın ayırmayı geri alır
- ARM64EC
lr
kaydını açar - 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
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin