#windows #arm #64-bit #arm64 #abi
#Windows #arm #64-разрядный #arm64 #abi
Вопрос:
В настоящее время я пытаюсь понять, как работает Windows на ARM. У меня возникли проблемы с пониманием того, как ARM64EC ABI может работать на чипе ARM. Microsoft заявляет, что ARM64EC основан на AArch64 с некоторыми изменениями, чтобы сделать его совместимым с x64, включая соглашения о вызовах, использование стека и выравнивание данных [1]. На мой взгляд, это означало бы, что он может быть выполнен на чипе x64, и я не могу найти причину, по которой это заставило бы его работать на чипе ARM, если он соответствует соглашениям x64.
Также они говорят, что эмулируется код x64 (я предполагаю, используя расширенную версию эмулятора x86 для ARM), но затем ARM64EC запускается изначально. Но почему мы должны различать, если они оба совместимы? Затем ОС изменяет все внутри, чтобы соответствовать AArch64?
Есть ли что-то, чего мне не хватает? Я наткнулся на ISA, но не смог найти ничего о том, какие ABI будут совместимы с A64 ISA. Но у меня также есть некоторые проблемы с пониманием взаимосвязи ISA и ABI?
Я извиняюсь, если это глупый вопрос, но я думаю, что я просто не понимаю или не понимаю ничего, а Microsoft довольно скудна в деталях.
Ответ №1:
На мой взгляд, это означало бы, что он может быть выполнен на чипе x64 […].
Вы путаете ABI с набором инструкций. ARM64EC по-прежнему использует набор команд A64 (который процессор x64 не способен выполнить), но он использует регистры и стек таким образом, который концептуально легко сопоставить с регистрами x64.
Я не смог найти фактическую спецификацию для ARM64EC, но я полагаю, что одна вещь может быть обратным адресом.
В обычном коде ARM64 вызывается функция with bl func_name
, которая вводит адрес возврата в x30
, а затем вызываемый объект использует ret
, который будет переходить к адресу in x30
. Сравните это с x64, где call
помещает адрес возврата в стек и ret
извлекает его оттуда.
Опять же, я не знаю, действительно ли ARM64EC делает это, но если бы я его проектировал, то одна вещь, которую я бы сделал, — сделать вызовы функций похожими на это:
// call site
adr x30, 1f
str x30, [sp, -8]!
b func_name
1:
// ...
func_name:
// ...
ldr x30, [sp], 8
ret
Если бы вы этого не сделали, то переведенный код x64 ожидал бы, что вещи будут находиться в разных местах, чем были введены машинным кодом, и наоборот.
Комментарии:
1. Спасибо. Чтобы я правильно понял, ARM64EC представляет в приложениях соглашения x64, затем внутренне перемещает все из мест, которые приложение предоставило ему, в места, которые нужны A64, а затем использует обычные вызовы A64 для выполнения того, что он должен? Который в некоторых случаях должен использовать (я полагаю) некоторые переменные регистры для хранения значений между перемещениями, если, например, x64 хранит значение A в r1 и значение B в r2, но A64 ожидает A в r2 и B в r1.
2. Нет. код x64 переводится во время выполнения и, по-видимому, не может быть совместим с arm64 ABI там. Теперь, когда у вас есть C или C или любой другой код, который вы компилируете, вы можете либо скомпилировать его с arm64 ABI, что сделает его несовместимым с переведенным кодом x64, либо с arm64ec ABI, что сделает его совместимым с переведенным x64, но несовместимым с arm64 ABI.
Ответ №2:
MSFT недавно опубликовала некоторые подробности о ARM64EC и о том, как он работает: https://docs.microsoft.com/en-us/windows/uwp/porting/arm64ec-abi
Подводя итог, двоичный файл ARM64EC — это в основном код ARM64, но использование регистров таким образом, чтобы отображать состояние 1: 1 на x64, и все функции, которые экспортируются или помечаются соответствующим образом, получат короткую оболочку x64, называемую FFS, это позволяет подключать эти функции с помощью х64-хуков, несмотря на большинствокод должен быть ARM64. И гарантирует, что при импорте библиотеки не имеет значения, будет ли она x64 или arm64ec, если ваше приложение, являющееся x64 или arm64ec, сможет беспрепятственно ее использовать.