Устройства на базе Arm становятся все более популярными благодаря своему экономичному характеру, более длительному времени автономной работы и повышенной производительности. Это обусловило постепенный рост количества устройств на Windows, которые работают на платформе ARM64.
Для создания приложений на ассеммблере под Windows ARM64 прежде всего необходимо установить среду разработки Visual Studio. Visual Studio доступна в ряде редакций. Мы будем использовать выпуск Visual Studio Community. Причем стоит отметить, что Visual Studio имеет полноценную поддержку ARM64.
Итак, для установки среды загрузим установщик со страницы https://visualstudio.microsoft.com/ru/vs/community/. После запуска программы установщика выберем пункт Разработка классических приложений на C++:
Стоит отметить, что хотя сама Visual Studio и имеет поддержку ARM64, но ее установщик не является нативным приложением ARM64 и представляет общее приложение для разных архитектур, поэтому на ARM он может работать чуть медленее. Однако при установке он установщик определит платформу системы и загрузит и установит именно те файлы, которые подходят для данной системы, то есть для x86-64 устанавливается одна версия Visual Studio, а для ARM64 - другая.
После установки в панели Пуск среди установленных программ мы сможем найти кроме собственно Visual Studio также ряд установленных сопутствующих консольных утилит
Здесь нас будет интресовать прежде всего утилита ARM64 Native Tools Command Prompt for VS 2022. Эта утилита позволяет напрямую обращаться к ассемблеру armasm64, который представляет своего рода версию MASM для платформы ARM64. Например, запустим данную утилиту и введем название ассемблера "armasm64", и нам отобразится его версия и опции:
********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.6.5 ** Copyright (c) 2022 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'arm64' C:\Program Files\Microsoft Visual Studio\2022\Community>armasm64 Microsoft (R) ARM Macro Assembler Version 14.36.32537.0 for 64 bits Copyright (C) Microsoft Corporation. All rights reserved. error A2033: missing input source file Usage: armasm [<options>] sourcefile objectfile armasm [<options>] -o objectfile sourcefile armasm -h for help C:\Program Files\Microsoft Visual Studio\2022\Community>
Теперь создадим простейшую программу для Windows. В целом armasm64 применяет тот же синтаксис, те же инструкции, что и ассемблер GAS, однако есть и различия. Поэтому в дальнейшем я буду акцентировать внимание именно на различиях.
Итак, определим для хранения файлов с исходным кодом какой-нибудь каталог. Например, в моем случае это будет папка С:\arm64
. В этой папке
создадим файл hello.asm и определим в нем следующий код:
area main, CODE ; определение раздела main, который имеет тип CODE global __main ; делаем видимой извне функцию __main __main ; определение функции __main mov x0, #2 ; помещаем в регистр Х0 число 2 mov x1, #3 ; помещаем в регистр Х1 число 3 add x0, x0, x1 ; складываем числа - Х0 = Х0 + Х1 ret ; завершение функции __main end ; завершение программы
Определение программы начинается с директивы AREA, которая определяет раздел.
area main, CODE
Директиве передается название раздела - произвольный идентификатор,
который указывает на имя разделя. В данном случае раздел называется main
. Затем указывается тип раздела. Здесь это
CODE. Данный тип указывает, что раздел представляет собой секцию с инструкциями программы. То есть это аналогично применению
в ряде ассемблеров директивы .code
или .text
Далее идет директива GLOBAL, которая позволяет сделать видимым, доступным из вне некоторый идентификатор.
global __main
В нашем случае делаем
доступной извне процедуру __main
, которая будет выступать в качестве точки входа в программу. Это необходимо компоновщику, чтобы он определил
точку входа.
Затем располагает собственно определение процедуры/функции __main
. Оно начинаяется с имени функции, за которым идет набор составляющих ее инструкций.
Обратите внимание на отступы и что у названия функции отступа нет.
В самой функции __main для простоты с помощью инструкции MOV помещаем в регистры Х0 и Х1 числа 2 и 3 и с помощью инструкции ADD складываем эти числа и результат помещаем в регистр Х0
mov x0, #2 mov x1, #3 add x0, x0, x1
Функция __main завершается вызовом инструкции ret, а сама программа завершается инструкцией end
Теперь скомпилируем программу. Для этого запустим утилиту ARM64 Native Tools Command Prompt for VS 2022 и с помощью команды cd перейдем в ней к папке, где располагается наш файл hello.asm. Затем для компиляции выполним следующую команду
armasm64 hello.asm -o hello.obj
Эта команда передает ассемблеру armasm64 исходный файл "hello.asm".
С помощью опции -o
указывается название файла, в который будет производиться компиляция.
То есть в данном случае файл hello.asm будет компилироваться в файл hello.obj.
Итак, после выполнения этой команды в папке с исходным кодом у нас появится скомпилированный объектный файл hello.obj. Теперь его надо скомпоновать в исполняемый файл, чтобы его можно было запускать как обычное приложение. Для этого выполним команду
cl hello.obj /link /entry:__main /subsystem:console
Команда cl представляет вызов компилятора языка C++, который устанавливается вместе с Visual Studio. Этому компилятору передается файл
hello.obj. А с помощью опции /link
передатся настройки для компоновщика. В частности, опция /entry
устанавливает точку входа в программу.
В нашем случае это функция __main
, которую в коде программы мы экспортировали во вне с помощью директивы GLOBAL. Если
наша точка входа имеет другое имя, то соответственно также меняется значение этого параметра. Кроме того, опция /subsystem:console
указывает, что мы компилируем консольное приложение.
Стоит отметить, что вместо компилятора cl мы могли бы просто вызвать программу компоновщика/линкера в виде утилиты link и передать ей те же параметры:
link hello.obj /entry:__main /subsystem:console
После выполнения этой команды с папке с исходным кодом появится собственно файл программы - hello.exe. И мы можем запустить его, вызвав команду
hello.exe
Однако поскольку программа ничего не выводит на консоль, то и консоль при вызове этой программы ничего не отобразит. Тем не менее в программе изменяется значение регистра Х0. Данный регистр обычно используется при завершении программы как числовой код завершения программы (в нашем случае в регистре Х0 располгается число 5). И чтобы получить этот числовой код, после выполнения скомпилированной программы надо выполнить команду
echo %ERRORLEVEL%
Полный вывод консоли ARM64 Native Tools Command Prompt for VS 2022:
********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.6.5 ** Copyright (c) 2022 Microsoft Corporation ********************************************************************** [vcvarsall.bat] Environment initialized for: 'arm64' C:\Program Files\Microsoft Visual Studio\2022\Community>cd c:\arm64 c:\arm64>armasm64 hello.asm -o hello.obj Microsoft (R) ARM Macro Assembler Version 14.36.32537.0 for 64 bits Copyright (C) Microsoft Corporation. All rights reserved. c:\arm64>cl hello.obj /link /entry:__main /subsystem:console Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32537 for ARM64 Copyright (C) Microsoft Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 14.36.32537.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:hello.exe /entry:__main /subsystem:console hello.obj c:\arm64>hello.exe c:\arm64>echo %ERRORLEVEL% 5 c:\arm64>