Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
ARM64EC egy alkalmazás bináris felülete (ABI), amely lehetővé teszi, hogy az ARM64 bináris fájljai natívan és együttműködve fussanak x64-kóddal. Az ARM64EC ABI az x64-szoftverkonvenciákat követi, beleértve a hívási konvenciók, a veremhasználat és az adatok igazítását, így a ARM64EC és az x64-kód interoperábilissá válik. Az operációs rendszer emulálja a bináris x64 részét. (Az EC az ARM64EC-ben az emuláció kompatibilis.)
Az x64- és ARM64 ABI-konvenciókról további információt az x64 ABI-konvenciók áttekintése és az ARM64 ABI-konvenciók áttekintése című témakörben talál.
ARM64EC nem oldja meg az x64 és ARM-alapú architektúrák közötti memóriamodell-különbségeket. További információ: Gyakori Microsoft C++ ARM-migrálási problémák.
Meghatározások
- ARM64 – A hagyományos ARM64-kódot tartalmazó ARM64-folyamatok kódstreamje.
- ARM64EC – Az ARM64-regiszterkészlet egy részhalmazát használó kódstream, amely az x64-kód együttműködési képességét biztosítja.
Regiszter leképezése
Az x64-folyamatok ARM64EC kódot futtató szálakat tartalmazhatnak. Így mindig lekérhető egy x64-regiszterkörnyezet, ARM64EC az ARM64 magregisztrálók egy részhalmazát használja, amely az 1:1-et megfelelteti az x64-regiszterek emulálásához. Fontos, hogy ARM64EC soha nem használja az alhalmazon kívüli regisztereket, kivéve, amikor beolvassa a Szálkörnyezeti blokk (TEB) címét x18-ból.
A natív ARM64-folyamatok teljesítményének nem szabad romlania, amikor néhány vagy sok függvényt újrafordítanak ARM64EC-ként. A teljesítmény fenntartása érdekében az ABI az alábbi alapelveket követi:
A ARM64EC regisztrációs részhalmaz tartalmazza az ARM64 függvényhívási konvenció részét képező összes regisztert.
A ARM64EC hívási konvenció közvetlenül az ARM64 hívási konvencióhoz igazodik.
Speciális segítő rutinok, mint például a __chkstk_arm64ec, egyéni hívási konvenciókat és regisztereket használnak. Ezek a regiszterek a nyilvántartások ARM64EC részhalmazában is szerepelnek.
Egész számregiszterek leképezése
| ARM64EC regisztráció | x64-regisztráció | ARM64EC hívási konvenció | ARM64-hívási konvenció | x64-hívási konvenció |
|---|---|---|---|---|
x0 |
rcx |
illékony | illékony | illékony |
x1 |
rdx |
illékony | illékony | illékony |
x2 |
r8 |
illékony | illékony | illékony |
x3 |
r9 |
illékony | illékony | illékony |
x4 |
r10 |
illékony | illékony | illékony |
x5 |
r11 |
illékony | illékony | illékony |
x6 |
mm1 (az x87 R1 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x7 |
mm2 (az x87 R2 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x8 |
rax |
illékony | illékony | illékony |
x9 |
mm3 (az x87 R3 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x10 |
mm4 (az x87 R4 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x11 |
mm5 (az x87 R5 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x12 |
mm6 (az x87 R6 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x13 |
Nincs adat. | nem engedélyezett | illékony | Nincs adat. |
x14 |
Nincs adat. | nem engedélyezett | illékony | Nincs adat. |
x15 |
mm7 (az x87 R7 regiszter alacsony 64 bitje) |
illékony | illékony | illékony |
x16 |
Az egyes x87 R0-R3 regiszterek felső 16 bitje |
illékony(xip0) |
illékony(xip0) |
illékony |
x17 |
Az egyes x87 R4-R7 regiszterek felső 16 bitje |
illékony(xip1) |
illékony(xip1) |
illékony |
x18 |
GS.base | rögzített (TEB) | rögzített (TEB) | rögzített (TEB) |
x19 |
r12 |
nem változékony | nem változékony | nem változékony |
x20 |
r13 |
nem változékony | nem változékony | nem változékony |
x21 |
r14 |
nem változékony | nem változékony | nem változékony |
x22 |
r15 |
nem változékony | nem változékony | nem változékony |
x23 |
Nincs adat. | nem engedélyezett | nem változékony | Nincs adat. |
x24 |
Nincs adat. | nem engedélyezett | nem változékony | Nincs adat. |
x25 |
rsi |
nem változékony | nem változékony | nem változékony |
x26 |
rdi |
nem változékony | nem változékony | nem változékony |
x27 |
rbx |
nem változékony | nem változékony | nem változékony |
x28 |
Nincs adat. | nem engedélyezett | nem engedélyezett | Nincs adat. |
fp |
rbp |
nem változékony | nem változékony | nem változékony |
lr |
mm0 (az x87 R0 regiszter alacsony 64 bitje) |
mindkettő | mindkettő | mindkettő |
sp |
rsp |
nem változékony | nem változékony | nem változékony |
pc |
rip |
utasításmutató | utasításmutató | utasításmutató |
PSTATErészhalmaz: N/Z/C/V/SS1, 2 |
RFLAGS részhalmaz: SF/ZF/CF/OF/TF |
illékony | illékony | illékony |
| Nincs adat. |
RFLAGS részhalmaz: PF/AF |
Nincs adat. | Nincs adat. | illékony |
| Nincs adat. |
RFLAGS részhalmaz: DF |
Nincs adat. | Nincs adat. | nem változékony |
1 Kerülje a közvetlen olvasást, írást vagy számítást az PSTATE és RFLAGS közötti leképezésekre. Ezek a bitek a jövőben használhatók, és változhatnak.
2 Az ARM64EC jelzőbit C az x64 jelzőbit inverze a kivonási műveletekhez. Nincs speciális kezelés, mert a jelző nem stabil, ezért a (ARM64EC és x64) függvények közötti váltáskor elveszik.
Vektorregiszterek leképezése
| ARM64EC regisztráció | x64-regisztráció | ARM64EC hívási konvenció | ARM64-hívási konvenció | x64-hívási konvenció |
|---|---|---|---|---|
v0-v5 |
xmm0-xmm5 |
illékony | illékony | illékony |
v6-v7 |
xmm6-xmm7 |
illékony | illékony | nem változékony |
v8-v15 |
xmm8-xmm15 |
illékony 1 | illékony 1 | nem változékony |
v16-v31 |
xmm16-xmm31 |
nem engedélyezett | illékony | letiltva (az x64 emulátor nem támogatja az AVX-512-t) |
FPCR
2 |
MXCSR[15:6] |
nem változékony | nem változékony | nem változékony |
FPSR
2 |
MXCSR[5:0] |
illékony | illékony | illékony |
1 Ezek az ARM64-regiszterek abban különlegesek, hogy az alsó 64 bit nem változékony, a felső 64 bit azonban változékony. Az x64-hívók szempontjából gyakorlatilag változékonyak, mert a hívott felülírná az adatokat.
2 Kerülje a közvetlen olvasását, írását vagy a leképezések számítását FPCR és FPSR esetén. Ezek a bitek a jövőben használhatók, és változhatnak.
Strukturált csomagolás
ARM64EC ugyanazokat a szerkezetcsomagolási szabályokat követi, amelyeket az x64-hez használ a ARM64EC kód és az x64 kód közötti együttműködés biztosítása érdekében. További információ és példák az x64-alapú szerkezetek csomagolására: X64 ABI-konvenciók áttekintése.
Lebegőpontos kivételek
Annak megállapításához, hogy egy ARM CPU támogatja-e a kivételeket, írjon egy értéket, amely engedélyezi az FPCR-regisztráció kivételét, majd olvassa vissza. Ha a PROCESSZOR támogatja a lebegőpontos kivételeket, a támogatott kivételeknek megfelelő bitek továbbra is be lesznek állítva, míg a processzor alaphelyzetbe állítja a biteket a nem támogatott kivételek esetében.
Az ARM64EC alatt a Windows elkapja a processzor lebegőpontos kivételeit, és letiltja őket az FPCR-regiszterben. Ez biztosítja a különböző processzorvariánsok konzisztens viselkedését.
Emulációs segéd ABI-rutinok
ARM64EC kód és csonkok emulációs segédprogramokat használnak az x64 és ARM64EC függvények közötti váltáshoz.
Az alábbi táblázat az egyes speciális ABI-rutinokat és az ABI által használt nyilvántartásokat ismerteti. A rutinok nem módosítják az ABI oszlopban lévő felsorolt tartósított regisztereket. Nem szabad feltételezni a nem regisztrált nyilvántartásokat. A lemezen az ABI rutinmutatói null értékűek. Betöltési időben a betöltő frissíti a mutatókat, hogy az x64 emulátor rutinjaira mutasson.
| Név | Leírás | ABI |
|---|---|---|
__os_arm64x_dispatch_call_no_redirect |
Az exit thunk hív egy x64 célt (akár egy x64 függvényt, akár egy x64 gyorselőre sorozatot). A rutin leküldi az ARM64EC visszatérési címet (a LR regiszterben), majd az x64 emulátort meghívó blr x16 utasítást követő utasítás címét. Ezután futtatja az utasítást blr x16 |
visszatérési érték (x8rax) |
__os_arm64x_dispatch_ret |
Egy belépési mechanizmus hívást eszközöl, hogy visszatérjen az x64-es hívójához. Ekkor megjelenik az x64 visszatérési cím a veremből, és meghívja az x64 emulátort, hogy ugorjon rá | Nincs adat. |
__os_arm64x_check_call |
ARM64EC kód hívja meg, amely egy kilépési csonkra mutató mutatóval és a végrehajtáshoz szükséges közvetett ARM64EC célcímmel rendelkezik. A ARM64EC cél javíthatónak minősül, és a végrehajtás mindig ugyanazokkal az adatokkal tér vissza a hívóhoz, mint amellyel meghívták, vagy módosított adatokkal. | Érvek:x9: A célcímx10: A kilépési thunk címx11: A gyors továbbítási szekvencia címeKint van: x9: Ha a célfüggvényt eltérítették, az tartalmazza a gyors előrelépési sorozat címét.x10: A kilépési thunk címx11: Ha a függvényt eltérítették, az tartalmazza a kilépési "thunk" címet. Ellenkező esetben a célcím a következőre ugrott:Megőrzött regiszterek: x0-x8, x15 ().chkstk és q0-q7 |
__os_arm64x_check_icall |
A ARM64EC kód hívható meg egy kilépési csonkra mutató mutatóval egy x64 vagy ARM64EC nevű célcímre való ugrás kezeléséhez. Ha a cél x64, és az x64-kód nem lett javítva, a rutin beállítja a célcím-nyilvántartást. Ha létezik ilyen, a függvény ARM64EC verziójára mutat. Ellenkező esetben a regisztert úgy állítja be, hogy az x64-es célhoz való átmenetet kezelő kilépő pontra mutasson. Ezután visszatér a hívási ARM64EC kódhoz, amely ezután a regisztrációs címre ugrik. Ez a rutin a __os_arm64x_check_call nevű rutin nem optimalizált verziója, ahol a célcím a fordítás idején nem ismert.Közvetett hívás helyén használatos |
Érvek:x9: A célcímx10: A kilépési thunk címx11: A gyors továbbítási szekvencia címeKint van: x9: Ha a célfüggvényt eltérítették, az tartalmazza a gyors előrelépési sorozat címét.x10: A kilépési thunk címx11: Ha a függvényt eltérítették, az tartalmazza a kilépési "thunk" címet. Ellenkező esetben a célcím a következőre ugrott:Tartósított nyilvántartások: x0-x8, x15 (chkstk) és q0-q7 |
__os_arm64x_check_icall_cfg |
Ugyanaz, mint __os_arm64x_check_icall, de azt is ellenőrzi, hogy a megadott cím egy érvényes Control Flow Graph közvetett hívási cél-e. |
Érvek:x10: A kilépési thunk címex11: A célzott függvény címeKint van: x9: Ha a cél x64, a függvény címe. Ellenkező esetben nem definiáltx10: A kilépési thunk címex11: Ha a cél x64, az tartalmazza a kilépési thunk címét. Ellenkező esetben a függvény címeTartósított nyilvántartások: x0-x8, x15 (chkstk) és q0-q7 |
__os_arm64x_get_x64_information |
Lekéri az élő x64-regisztrációs környezet kért részét | _Function_class_(ARM64X_GET_X64_INFORMATION) NTSTATUS LdrpGetX64Information(_In_ ULONG Type, _Out_ PVOID Output, _In_ PVOID ExtraInfo) |
__os_arm64x_set_x64_information |
Az élő x64-regisztrációs környezet kért részének beállítása | _Function_class_(ARM64X_SET_X64_INFORMATION) NTSTATUS LdrpSetX64Information(_In_ ULONG Type,_In_ PVOID Input, _In_ PVOID ExtraInfo) |
__os_arm64x_x64_jump |
Aláírás nélküli beállítóban és más olyan csonkokban használatos, amelyek közvetlenül továbbítják (jmp) a hívást egy másik függvénynek, amely bármilyen aláírással rendelkezhet, és halasztja a jobb oldali thunk lehetséges alkalmazását a valódi célhoz |
Érvek:x9: cél, amelyhez ugrikMinden paraméterregisztrátor megőrzve (továbbítva) |
Csonkok
A thunkok olyan alacsony szintű mechanizmusok, amelyek támogatják az ARM64EC és x64 függvények egymás közti hívását. Két típus létezik: a ARM64EC függvények beírására szolgáló beviteli thunkok és az x64-függvények meghívására szolgáló kilépési thunkok .
Bejegyzés hívásának technikája és belső technikai bejegyzés: x64-ről ARM64EC-re történő függvényhívás
Az ARM64EC fordítású C/C++ függvények x64-hívók általi támogatása érdekében az eszközlánc egyetlen bejegyzésáthidalót hoz létre, amely ARM64EC gépi kódot tartalmaz. Az intrinsicsnek saját belépési útja van. Minden más függvény egy belépési hidat oszt meg az összes olyan függvénnyel, amely egyező hívási konvencióval, paraméterekkel és visszatérési típussal rendelkezik. A thunk tartalma a C/C++ függvény hívási konvenciójától függ.
A paraméterek és a visszatérési cím kezelése mellett a thunk áthidalja az ARM64EC és az x64 vektorregiszterek volatilitásbeli különbségeit, melyeket az ARM64EC vektorregiszter térképezés okoz.
| ARM64EC regisztráció | x64-regisztráció | ARM64EC hívási konvenció | ARM64-hívási konvenció | x64-hívási konvenció |
|---|---|---|---|---|
v6-v15 |
xmm6-xmm15 |
illékony, de mentett/visszaállított az entry thunkban (x64-ről ARM64EC-re) | illékony vagy részben illékony felső 64 bit | nem változékony |
A bejegyzési thunk a következő műveleteket hajtja végre:
| Paraméterszám | Veremhasználat |
|---|---|
| 0-4 | Az ARM64EC-t v6 és v7 a hívó által lefoglalt memóriaterületre tárolja.Mivel a hívott ARM64EC, amely nem rendelkezik a "home space" fogalmával, a tárolt értékek nem lesznek felülírva. További 128 bájtot foglal le a veremben, és az ARM64EC v8-tól v15-ig tárolja. |
| 5-8 |
x4 = 5. paraméter a verembőlx5 = a hatodik paraméter a verembőlx6 = a verem 7. paraméterex7 = 8. paraméter a verembőlHa a paraméter SIMD, a rendszer inkább a v4-v7 regisztereket használja |
| 9+ | Bájtokat AlignUp(NumParams - 8 , 2) * 8 foglal le a veremen. *Másolja a 9. és a fennmaradó paramétereket erre a területre. |
* Az érték páros számhoz igazítása garantálja, hogy a verem 16 bájthoz igazodik
Ha a függvény egy 32 bites egész szám paramétert fogad el, a thunk csak 32 bitet küldhet le a szülőregisztrálás teljes 64 bitje helyett.
Ezután a thunk egy ARM64 bl utasítással hívja meg a ARM64EC függvényt. A függvény visszatérése után a thunk következik:
- A veremfoglalások visszavonása
- Meghívja az
__os_arm64x_dispatch_retemulátor segédprogramot az x64 visszatérési címének kipattintására és az x64 emuláció folytatására.
Kilépési hiba: ARM64EC x64-es függvényhíváshoz
Minden olyan hívásnál, amelyet egy ARM64EC C/C++ függvény a lehetséges x64-kódhoz hoz létre, az MSVC eszközlánc létrehoz egy kilépési hibát. A thunk tartalma az x64 helyettesítési rutin paramétereitől függ, és hogy a helyettesítési rutin a szabványos hívási konvenciót vagy egy nem szabványos konvenciót, például a __vectorcall használ-e. A fordító ezt az információt a hívó függvénydeklarációjából szerzi be.
Először a thunk leküldi a ARM64EC lr regiszterben lévő visszatérési címet, és egy 8 bájtos hamis értéket, hogy a verem 16 bájthoz legyen igazítva. Másodszor, a thunk kezeli a paramétereket:
| Paraméterszám | Veremhasználat |
|---|---|
| 0-4 | 32 bájtnyi helyet foglal le a stacken |
| 5-8 | A AlignUp(NumParams - 4, 2) * 8 több bájtot magasabban foglalja le a veremen. * Másolja az 5. és az azt követő paramétereket a ARM64EC-ból x4-x7 ebbe a plusz helyre |
| 9+ | A 9. és az utána következő paraméterek másolása a szabad helyre |
* Az érték páros számhoz igazítása garantálja, hogy a verem 16 bájthoz igazodik.
Harmadszor, a thunk meghívja az __os_arm64x_dispatch_call_no_redirect emulátor segédet, hogy meghívja az x64 emulátort az x64 függvény futtatásához. A hívásnak blr x16 utasításnak kell lennie (kényelmesen, x16 egy volatilis regiszter). Utasításra blr x16 van szükség, mert az x64 emulátor tippként értelmezi ezt az utasítást.
Az x64 függvény általában x64 ret utasítással próbál visszatérni az emulátor segédhöz. Ezen a ponton az x64 emulátor észleli, hogy ARM64EC kódban van. Ezután felolvassa az előző 4 bájtos tippet, amely történetesen az ARM64 blr x16 utasítás. Mivel ez a tipp azt jelzi, hogy a visszatérési cím ebben a segédben található, az emulátor közvetlenül erre a címre ugrik.
Az x64 függvény bármilyen águtasítással visszatérhet az emulátort segítő funkcióhoz, beleértve az x64 jmp és call utasításokat is. Az emulátor ezeket a forgatókönyveket is kezeli.
Amikor a segítő visszatér a csonkhoz, a thunk:
- Feloldja bármely veremfoglalást
- A ARM64EC
lrregisztrációjának előugró ablaka - ARM64
ret lrutasítást hajt végre.
ARM64EC függvénynév díszítése
ARM64EC függvénynév egy másodlagos jelölést kap, amelyet a nyelvspecifikus jelölés alkalmazása után adnak hozzá. C kapcsolattal rendelkező függvények esetében (akár C-ként fordítva, akár extern "C" használatával), a # kerül a név elé. A C++ által dekorált függvények esetében a rendszer egy címkét $$h szúr be a névbe.
foo => #foo
?foo@@YAHXZ => ?foo@@$$hYAHXZ
__vectorcall
A ARM64EC eszközlánc jelenleg nem támogatott __vectorcall. A fordító hibát ad ki, amikor észleli a __vectorcall használatot ARM64EC-vel.
Lásd még
Az ARM64EC ABI és a szerelvénykód ismertetése
A Microsoft C++ ARM áttelepítésének gyakori problémái
Kitüntetett nevek