Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
ARM64EC är ett program binärt gränssnitt (ABI) som gör att ARM64-binärfiler kan köras internt och driftskompatibelt med x64-kod. Mer specifikt följer ARM64EC ABI x64-programvarukonventioner, inklusive anropskonventioner, stackanvändning och datajustering, vilket gör ARM64EC och x64-kod kompatibla. Operativsystemet emulerar x64-delen av binärfilen. (EG i ARM64EC står för emuleringskompatibel.)
Mer information om x64- och ARM64-API:er finns i Översikt över x64 ABI-konventioner och Översikt över ARM64 ABI-konventioner.
ARM64EC löser inte skillnader i minnesmodell mellan x64- och ARM-baserade arkitekturer. Mer information finns i Vanliga problem med Migrering av Microsoft C++ ARM.
Definitioner
- ARM64 – kodströmmen för ARM64-processer som innehåller traditionell ARM64-kod.
- ARM64EC – Kodströmmen som använder en delmängd av ARM64-registret för att tillhandahålla samverkan med x64-kod.
Registrera mappning
x64-processer kan ha trådar som kör ARM64EC kod. Så det är alltid möjligt att hämta en x64-registerkontext, ARM64EC använder en delmängd av ARM64-kärnregister som mappar 1:1 till emulerade x64-register. Viktigt är att ARM64EC aldrig använder register utanför den här delmängden, förutom att läsa TEB-adressen (Thread Environment Block) från x18.
Inbyggda ARM64-processer bör inte gå tillbaka i prestanda när vissa eller många funktioner omkompileras som ARM64EC. För att upprätthålla prestanda följer ABI dessa principer:
ARM64EC-registerunderuppsättningen innehåller alla register som ingår i ARM64-funktionsanropskonventionen.
ARM64EC-anropskonventionen mappar direkt till ARM64-anropskonventionen.
Särskilda hjälpmetoder som __chkstk_arm64ec använder anpassade samtalskonventioner och register. Dessa register ingår också i ARM64EC delmängd av register.
Kartläggning av heltalsregister
| ARM64EC-register | x64-register | ARM64EC samtalskonvention | ARM64-samtalskonvention | x64-samtalskonvention |
|---|---|---|---|---|
x0 |
rcx |
flyktig | flyktig | flyktig |
x1 |
rdx |
flyktig | flyktig | flyktig |
x2 |
r8 |
flyktig | flyktig | flyktig |
x3 |
r9 |
flyktig | flyktig | flyktig |
x4 |
r10 |
flyktig | flyktig | flyktig |
x5 |
r11 |
flyktig | flyktig | flyktig |
x6 |
mm1 (låga 64 bitar av x87-register R1) |
flyktig | flyktig | flyktig |
x7 |
mm2 (låga 64 bitar av x87-register R2) |
flyktig | flyktig | flyktig |
x8 |
rax |
flyktig | flyktig | flyktig |
x9 |
mm3 (låga 64 bitar av x87-register R3) |
flyktig | flyktig | flyktig |
x10 |
mm4 (låga 64 bitar av x87-register R4) |
flyktig | flyktig | flyktig |
x11 |
mm5 (låga 64 bitar av x87-register R5) |
flyktig | flyktig | flyktig |
x12 |
mm6 (låga 64 bitar av x87-register R6) |
flyktig | flyktig | flyktig |
x13 |
Inte tillgänglig | Otillåtet | flyktig | Inte tillgänglig |
x14 |
Inte tillgänglig | Otillåten | flyktig | Inte tillgänglig |
x15 |
mm7 (låga 64 bitar av x87-register R7) |
flyktig | flyktig | flyktig |
x16 |
De övre 16 bitarna av varje x87-register R0-R3 |
flyktig(xip0) |
flyktig(xip0) |
flyktig |
x17 |
De övre 16 bitarna av varje x87-register R4-R7 |
flyktig(xip1) |
flyktig(xip1) |
flyktig |
x18 |
GS.base | fixed(TEB) | fixed(TEB) | fixed(TEB) |
x19 |
r12 |
icke-flyktig | icke-flyktig | icke-flyktig |
x20 |
r13 |
icke-flyktig | icke-flyktig | icke-flyktig |
x21 |
r14 |
icke-flyktig | icke-flyktig | icke-flyktig |
x22 |
r15 |
icke-flyktig | icke-flyktig | icke-flyktig |
x23 |
Inte tillgänglig | Otillåten | icke-flyktig | Inte tillgänglig |
x24 |
Inte tillgänglig | Otillåten | icke-flyktig | Inte tillgänglig |
x25 |
rsi |
icke-flyktig | icke-flyktig | icke-flyktig |
x26 |
rdi |
icke-flyktig | icke-flyktig | icke-flyktig |
x27 |
rbx |
icke-flyktig | icke-flyktig | icke-flyktig |
x28 |
Inte tillgänglig | Förbjuden | Otillåten | Inte tillgänglig |
fp |
rbp |
icke-flyktig | icke-flyktig | icke-flyktig |
lr |
mm0 (låga 64 bitar av x87-register R0) |
båda | båda | båda |
sp |
rsp |
icke-flyktig | icke-flyktig | icke-flyktig |
pc |
rip |
instruktionspekare | instruktionspekare | instruktionspekare |
PSTATEdelmängd: N/Z/C/V/SS1, 2 |
RFLAGS delmängd: SF/ZF/CF/OF/TF |
flyktig | flyktig | flyktig |
| Inte tillgänglig |
RFLAGS delmängd: PF/AF |
Inte tillgänglig | Inte tillgänglig | flyktig |
| Inte tillgänglig |
RFLAGS delmängd: DF |
Inte tillgänglig | Inte tillgänglig | icke-flyktig |
1 Undvik att läsa, skriva eller beräkna mappningar direkt mellan PSTATE och RFLAGS. Dessa bitar kan användas i framtiden och kan komma att ändras.
2 Den ARM64EC-känneteckenflaggan C är den omvända av x64-känneteckenflaggan CF för subtraktionsoperationer. Det finns ingen särskild hantering eftersom flaggan är flyktig och därför förstörs när du övergår mellan (ARM64EC och x64) funktioner.
Registrera mappning för vektorregister
| ARM64EC-register | x64-register | ARM64EC samtalskonvention | ARM64-samtalskonvention | x64-samtalskonvention |
|---|---|---|---|---|
v0-v5 |
xmm0-xmm5 |
flyktig | flyktig | flyktig |
v6-v7 |
xmm6-xmm7 |
flyktig | flyktig | icke-flyktig |
v8-v15 |
xmm8-xmm15 |
instabil 1 | instabil 1 | icke-flyktig |
v16-v31 |
xmm16-xmm31 |
Otillåtet | flyktig | otillåten (x64-emulatorn stöder inte AVX-512) |
FPCR
2 |
MXCSR[15:6] |
icke-flyktig | icke-flyktig | icke-flyktig |
FPSR
2 |
MXCSR[5:0] |
flyktig | flyktig | flyktig |
1 Dessa ARM64-register är speciella eftersom de lägre 64 bitarna är icke-flyktiga men de övre 64 bitarna är flyktiga. När det gäller en x64-uppringare är de i praktiken instabila eftersom den anropade personen skulle förstöra data.
2 Undvik direkt läsning, skrivning eller databehandling av FPCR och FPSR. Dessa bitar kan användas i framtiden och kan komma att ändras.
Strukturpackning
ARM64EC följer samma struct-förpackningsregler som används för x64 för att säkerställa samverkan mellan ARM64EC kod och x64-kod. Mer information och exempel på x64-struct-packning finns i Översikt över x64 ABI-konventioner.
Flyttalsundantag
För att avgöra om en ARM-processor stöder undantag skriver du ett värde som aktiverar undantag till FPCR-registret och läser sedan tillbaka det. Om processorn stöder flyttalsundantag förblir de bitar som motsvarar undantag som stöds inställda, medan processorn återställer bitarna för undantag som inte stöds.
På ARM64EC hanterar Windows processorns flyttalsundantag och inaktiverar dem i FPCR-registret. Detta säkerställer konsekvent beteende för olika processorvarianter.
ABI-rutiner för emuleringshjälp
ARM64EC kod och thunks använder emuleringshjälprutiner för att övergå mellan x64- och ARM64EC-funktioner.
I följande tabell beskrivs varje särskild ABI-rutin och de register som ABI använder. Rutinerna ändrar inte de angivna bevarade registeren under ABI-kolumnen. Inga antaganden bör göras om olistade register. På disken är ABI-rutinpekarna null. Vid inläsningen uppdaterar inläsaren pekarna så att de pekar på x64-emulatorns rutiner.
| Namn | Beskrivning | ABI |
|---|---|---|
__os_arm64x_dispatch_call_no_redirect |
Anropas av en exit-thunk för att anropa ett x64-mål (antingen en x64-funktion eller en x64-snabbframåtsekvens). Rutinen skickar ARM64EC returadress (i LR registret) följt av adressen till instruktionen som lyckas med en blr x16 instruktion som anropar x64-emulatorn. Sedan körs instruktionen blr x16 |
returvärde i x8 (rax) |
__os_arm64x_dispatch_ret |
Anropas av en inträdesfunktion för att återgå till sin x64-uppringare. Den visar x64-returadressen från stacken och anropar x64-emulatorn för att hoppa till den | Inte tillgänglig |
__os_arm64x_check_call |
Anropas av ARM64EC kod med en pekare till en slut-thunk och den indirekta ARM64EC måladress som ska köras. ARM64EC-målet anses vara korrigeringsbart och programkörningen återgår alltid till anroparen, antingen med samma data som det kallades med, eller med modifierad data. | Argumenten:x9: Måladressenx10: Adressen för utgångs-thunkenx11: Sekvensadressen för snabbsnabb framåtUt: x9: Om målfunktionen har omdirigerats innehåller den adressen till snabbspolning framåt-sekvensenx10: Adressen för utgångs-thunkenx11: Om funktionen har omletts innehåller den adressen för exit-thunk. Annars hoppade måladressen över tillBevarade register: x0-x8, x15 (chkstk). och q0-q7 |
__os_arm64x_check_icall |
Anropas av ARM64EC kod, med en pekare till en exit thunk, för att hantera ett hopp till en måladress som är antingen x64 eller ARM64EC. Om målet är x64 och x64-koden inte har korrigerats anger rutinen måladressregistret. Den pekar på den ARM64EC versionen av funktionen om det finns någon. I annat fall ställer den in registret så att det pekar på den avslutande tröskeln som övergår till x64-målplattformen. Sedan återgår den till den anropande ARM64EC-koden, som sedan hoppar till adressen i registret. Den här rutinen är en icke-optimerad version av __os_arm64x_check_call, där måladressen inte är känd vid kompileringstillfälletAnvänds på en anropsplats för ett indirekt anrop |
Argumenten:x9: Måladressenx10: Adressen för utgångs-thunkenx11: Sekvensadressen för snabbsnabb framåtUt: x9: Om målfunktionen har omdirigerats innehåller den adressen till snabbspolning framåt-sekvensenx10: Adressen för utgångs-thunkenx11: Om funktionen har omletts innehåller den adressen för exit-thunk. Annars hoppade måladressen över tillBevarade register: x0-x8, x15 (chkstk) och q0-q7 |
__os_arm64x_check_icall_cfg |
Samma som __os_arm64x_check_icall men kontrollerar också att den angivna adressen är ett giltigt kontrollflödesdiagrams indirekta anropsmål |
Argumenten:x10: Adressen till exit-thunkx11: Målfunktionens adressUt: x9: Om målet är x64, adressen till funktionen. I annat fall, odefinieradx10: Adressen till exit-thunkx11: Om målet är x64 innehåller det adressen till exit-funktionen. Annars är det funktionens adress...Bevarade register: x0-x8, x15 (chkstk) och q0-q7 |
__os_arm64x_get_x64_information |
Hämtar den begärda delen av live x64-registerkontexten | _Function_class_(ARM64X_GET_X64_INFORMATION) NTSTATUS LdrpGetX64Information(_In_ ULONG Type, _Out_ PVOID Output, _In_ PVOID ExtraInfo) |
__os_arm64x_set_x64_information |
Anger den begärda delen av live x64-registerkontexten | _Function_class_(ARM64X_SET_X64_INFORMATION) NTSTATUS LdrpSetX64Information(_In_ ULONG Type,_In_ PVOID Input, _In_ PVOID ExtraInfo) |
__os_arm64x_x64_jump |
Används i anpassare utan signatur och andra thunks som direkt vidarebefordrar (jmp) ett anrop till en annan funktion som kan ha vilken signatur som helst, och därmed skjuter upp den potentiella tillämpningen av rätt thunk till det verkliga målet. |
Argumenten:x9: mål att hoppa tillAlla parameterregister bevarade (vidarebefordrade) |
Thunk
Thunks är de lågnivåmekanismer som stöder ARM64EC- och x64-funktioner som anropar varandra. Det finns två typer: entry-thunks för att komma in i ARM64EC-funktioner och exit-thunks för att anropa x64-funktioner.
Inmatningstrick och inbyggda inmatnings thunks: x64 till ARM64EC funktionsanrop
För att stödja x64-anropare när en C/C++-funktion kompileras som ARM64EC, genererar verktygskedjan en ingångspunkt som består av ARM64EC maskinkod. Intrinsics har en egen inträdes-thunk. Alla andra funktioner delar en inmatningsfunktion med alla funktioner med samma anropskonvention, parametrar och returtyp. Innehållet i thunk beror på anropskonventionen för C/C++-funktionen.
Förutom att hantera parametrar och returadressen överbryggar thunk skillnaderna i volatilitet mellan ARM64EC- och x64-vektorregister som orsakas av ARM64EC mappning av vektorregister:
| ARM64EC-register | x64-register | ARM64EC samtalskonvention | ARM64-samtalskonvention | x64-samtalskonvention |
|---|---|---|---|---|
v6-v15 |
xmm6-xmm15 |
volatil, men sparad/återställd i inmatningsstubben (x64 till ARM64EC) | flyktiga eller delvis flyktiga övre 64 bitar | icke-flyktig |
Inmatningstunk utför följande åtgärder:
| Parameternummer | Stackanvändning |
|---|---|
| 0-4 | Lagrar ARM64EC v6 och v7 i uppringarens allokerade hemutrymmeEftersom anroparen är ARM64EC, som inte har begreppet hemutrymme, klonas inte de lagrade värdena. Allokerar ytterligare 128 byte på stacken och lagrar ARM64EC v8 via v15. |
| 5-8 |
x4 = 5:e parametern från stackenx5 = 6:e parametern från stackenx6 = 7:e parametern från stackenx7 = 8:e parametern från stackenOm parametern är SIMD används registren v4-v7 i stället |
| 9+ | Allokerar AlignUp(NumParams - 8 , 2) * 8 byte på stacken. *Kopierar de 9:e och återstående parametrarna till det här området |
* Om värdet justeras till ett jämnt tal garanteras att stacken förblir justerad till 16 byte
Om funktionen accepterar en 32-bitars heltalsparameter är det tillåtet för thunken att endast pusha 32 bitar i stället för hela 64 bitar av registret.
Därefter använder thunk en ARM64-instruktion bl för att anropa funktionen ARM64EC. När funktionen har returnerat, kommer thunken att aktiveras:
- Ångrar eventuella stackallokeringar
-
__os_arm64x_dispatch_retAnropar emulatorhjälpare för att poppa x64-returadressen och återuppta x64-emulering.
Avsluta thunk: ARM64EC till x64-funktionsanrop
För varje anrop som en ARM64EC C/C++-funktion gör till potentiell x64-kod genererar MSVC-verktygskedjan en avslutningsknapp. Innehållet i thunk beror på parametrarna för x64-funktionen och om funktionen använder standardanropskonventionen eller __vectorcall. Kompilatorn hämtar den här informationen från en funktionsdeklaration för anroparen.
Först pushar Thunk returadressen som finns i ARM64EC-registret lr och ett fiktivt värde på 8 byte för att säkerställa att stacken är justerad till 16 byte. För det andra hanterar "thunk" parametrarna:
| Parameternummer | Stackanvändning |
|---|---|
| 0-4 | Allokerar 32 bytes av hemutrymme på stacken |
| 5-8 | Allokerar AlignUp(NumParams - 4, 2) * 8 fler byte högre upp på stacken. * Kopierar den 5:e och eventuella efterföljande parametrar från ARM64EC:s x4-x7 till det här extra utrymmet |
| 9+ | Kopierar de 9:e och återstående parametrarna till det extra utrymmet |
* Om du justerar värdet till ett jämnt tal garanteras att stacken förblir justerad till 16 byte.
För det tredje anropar __os_arm64x_dispatch_call_no_redirect thunk emulatorhjälpen för att anropa x64-emulatorn för att köra x64-funktionen. Anropet måste vara en blr x16 instruktion (praktiskt nog är x16 ett flyktigt register). En blr x16 instruktion krävs eftersom x64-emulatorn parsar den här instruktionen som ett tips.
Funktionen x64 försöker vanligtvis återgå till emulatorhjälpen med hjälp av en x64-instruktion ret . Nu identifierar x64-emulatorn att den finns i ARM64EC kod. Den läser sedan föregående 4-byte-ledtråd som råkar vara ARM64-instruktionen blr x16. Eftersom detta tips anger att returadressen finns i den här hjälparen, hoppar emulatorn direkt till den adressen.
Funktionen x64 tillåts återgå till emulatorhjälpfunktionen med hjälp av vilken greninstruktion som helst, inklusive x64 jmp och call. Emulatorn hanterar även dessa scenarier.
När hjälpen sedan återgår till thunken, tonk:
- Ångrar allokering av staplar
- Poppar ARM64EC
lr-registret - Verkställer en ARM64-instruktion
ret lr.
ARM64EC funktionsnamnsdekoration
Ett ARM64EC funktionsnamn har en sekundär dekoration tillämpad efter valfri språkspecifik dekoration. För funktioner med C-länkning (oavsett om de kompileras som C eller med hjälp av extern "C"), läggs ett # till i namnet. För C++-dekorerade funktioner infogas en $$h tagg i namnet.
foo => #foo
?foo@@YAHXZ => ?foo@@$$hYAHXZ
__vectorcall
Verktygskedjan ARM64EC stöder __vectorcallför närvarande inte . Kompilatorn genererar ett fel när den identifierar __vectorcall användning med ARM64EC.
Se även
Förstå ARM64EC ABI och sammansättningskod
Vanliga problem med Migrering av Microsoft C++ ARM
Dekorerade namn