ARM64EC

ARM64EC is a new ABI that appeared with Windows 11.

It allows to mix x64 and arm64 code in the same process.

Porting applications to Arm64 using the Arm64EC ABI: https://www.youtube.com/watch?v=HmI6ip4o9as

Understanding Arm64EC ABI and assembly code

Setup

To be able to compile code targeting ARM64EC, you need to install:

To install the SDK, you can install it through VS installer.

Note: If you use Insider Preview Win11 VM, SDK install will fail saying its not compatible with current Windows version. If this, you must install the SDK manually via the link above.

Compile

To compile an arm64ec object, you need flag: /arm64EC (case matters!)

To link if, you need flag: /machine:arm64ec or /machine:arm64x (expose both arm64 and arm64ec interfaces).

There is no way to mix x86 code with any other architecture, it would have no meaning.

Run

This bash script will compile a single binary with two objects:

  • x64.c: compiled in x64

  • main.c: compiled in arm64ec

#!/usr/bin/env bash set -euo pipefail vcvars='C:\"Program Files"\"Microsoft Visual Studio"\2022\Community\VC\Auxiliary\Build\vcvarsall.bat' x64() { cmd.exe /c "call $vcvars x64 & $*" } arm64() { cmd.exe /c "call $vcvars x86_arm64 & $*" } show_arch() { local bin=$1 local arch=$(x64 dumpbin.exe /headers $bin |& grep machine) echo "arch for $bin: $arch" } line() { echo "--------------------" } check_winsdk_available() { # you need windows 11 sdk, else link will fail # LINK : fatal error LNK1104: cannot open file 'softintrin.lib' local found=$(find '/c/Program Files (x86)/' | grep '/softintrin.lib$') if [ "$found" == "" ]; then echo "you need windows 11 sdk (22000) installed" exit 1 fi } cat > main.c << EOF #include <stdio.h> extern char* secret_from_x64(int* res); int main() { int secret = 0; char* msg = secret_from_x64(&secret); printf("%s: %d\n", msg, secret); } EOF cat > x64.c << EOF char* secret_from_x64(int* res) { *res = 42; return "sent from x64"; } EOF check_winsdk_available arm64 cl.exe main.c /c /arm64EC # this flag enables this new ABI line x64 cl.exe x64.c /c # link # machine:arm64x expose both arm64 and arm64ec abi # machine:arm64ec expose only arm64ec abi line arm64 link.exe main.obj x64.obj /machine:arm64ec line show_arch main.obj show_arch x64.obj show_arch main.exe line ./main.exe

Output

-------------------- arch for main.obj: A641 machine (ARM64EC) arch for x64.obj: 8664 machine (x64) arch for main.exe: 8664 machine (x64) (ARM64X) -------------------- sent from x64: 42