Как программировать на ассемблере под windows 10

В данной статье я хочу рассмотреть вопросы, которые могут возникнуть у человека, приступившего к изучению ассемблера, связанные с установкой различных транслятор...

В данной статье я хочу рассмотреть вопросы, которые могут возникнуть у человека, приступившего к изучению ассемблера, связанные с установкой различных трансляторов и трансляцией программ под Windows и Linux, а также указать ссылки на ресурсы и книги, посвященные изучению данной темы.

MASM

Используется для создания драйверов под Windows.

По ссылке переходим на сайт и скачиваем пакет (masm32v11r.zip). После инсталляции программы на диске создается папка с нашим пакетом C:masm32. Создадим программу prog11.asm, которая ничего не делает.

.586P
.model flat, stdcall 
_data segment 
_data ends
_text segment
start:
ret   
_text ends
end start

Произведём ассемблирование (трансляцию) файла prog11.asm, используя ассемблер с сайта masm32.

image
Ключ /coff используется здесь для трансляции 32-битных программ.
Линковка производится командой link /subsystem:windows prog11.obj (link /subsystem:console prog11.obj)

Как сказано в Википедии

MASM — один из немногих инструментов разработки Microsoft, для которых не было отдельных 16- и 32-битных версий.

Также ассемблер версии 6. можно взять на сайте Кипа Ирвина kipirvine.com/asm, автора книги «Язык ассемблера для процессоров Intel».

Кстати, вот ссылка на личный сайт Владислава Пирогова, автора книги “Ассемблер для Windows”.

MASM с сайта Microsoft

Далее скачаем MASM (версия 8.0) с сайта Microsoft по ссылке. Загруженный файл носит название «MASMsetup.exe». При запуске этого файла получаем сообщение -«Microsoft Visual C++ Express Edition 2005 required».

Открываем этот файл архиватором (например 7zip). Внутри видим файл setup.exe, извлекаем его, открываем архиватором. Внутри видим два файла vc_masm.msi,vc_masm1.cab. Извлекаем файл vc_masm1.cab, открываем архиватором. Внутри видим файл FL_ml_exe_____X86.3643236F_FC70_11D3_A536_0090278A1BB8. Переименовываем его в файл fl_ml.exe, далее, произведём ассемблирование файла prog11.asm, используя ассемблер fl_ml.exe.

image

MASM в Visual Studio

Также MASM можно найти в папке с Visual Studio (у меня VS 10) вот здесь: C:Program FilesMicrosoft Visual Studio 10.0VCbinml.exe.

image

Для того, чтобы запустить на 32- или 64-разрядной системе и создавать программы, работающие как под 32-, так и под 64-разрядной Windows, подходит MASM32 (ml.exe, fl_ml.exe). Для того, чтобы работать на 32- и 64-разрядных системах и создавать программы, работающие под 64-разрядной Windows, но неработающие под 32-разрядной нужен ассемблер ml64.exe. Лежит в папке C:Program FilesMicrosoft Visual Studio 10.0VCbinamd64 и вот здесь — C:Program FilesMicrosoft Visual Studio 10.0VCbinx86_amd64.

TASM

Программный пакет компании Borland, предназначенный для разработки программ на языке ассемблера для архитектуры x86. В настоящее время Borland прекратила распространение своего ассемблера.

Скачать можно, например, здесь. Инсталлятора нет, просто извлекаем программу. Вот исходник из книги Питера Абеля (рис. 3.2) «Язык Ассемблера для IBM PC и программирования».

stacksg segment para stack 'stack'
    db 12 dup ('stackseg')
stacksg ends
codesg segment para 'code'
begin proc far
 assume ss:stacksg,cs:codesg,ds:nothing
 push ds
 sub ax,ax
 push ax
 mov ax, 0123h
 add ax, 0025h
 mov bx,ax
 add bx,ax
 mov cx,bx
 sub cx,ax
 sub ax,ax
 nop
 ret
begin endp
codesg ends
 end begin

Выполним ассемблирование (трансляцию) файла abel32.asm.

image

Корректность работы программы можно проверить, произведя линковку (tlink.exe) объектного файла и запустив полученный файл в отладчике.

Как было сказано выше, MASM можно использовать для работы с 16-битными программами. Выполним ассемблирование (трансляцию) программы abel32.asm с помощью ассемблера MASM:

image

Ключ /coff здесь не используется.
Линковка производится файлом link16.exe

Вот здесь приводится порядок действий, которые необходимо выполнить для запуска TASM в DOSbox. Для линковки понадобится файл DPMI16BI.OVL

FASM

В статье Криса Касперски «Сравнение ассемблерных трансляторов» написано, что «FASM — неординарный и весьма самобытный, но увы, игрушечный ассемблер. Пригоден для мелких задач типа „hello, world“, вирусов, демок и прочих произведений хакерского творчества.»

Скачаем FASM с официального сайта. Инсталлятора нет, просто извлекаем программу. Откроем fasm editor — C:fasmfasmw.exe. В папке C:fasmEXAMPLESHELLO есть файл HELLO.asm.

include 'win32ax.inc' 
.code
  start:
 invoke    MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
    invoke    ExitProcess,0
.end start

Откроем файл HELLO.asm из fasmw.exe. Изменим строку include ‘win32ax.inc’ на строку include ‘c:fasmINCLUDEWIN32AX.INC’. Запускаем из меню Run → Run.

image

Вот ссылки на ресурсы, посвященные FASM:

→ FASM на Cyberforum’е
→ FASM на asmworld .com программы под Dos
→ Цикл статей «Ассемблер под Windows для чайников»
→ Сайт на narod’е

FASM в Linux

Для того, использовать FASM в Linux (у меня Ubuntu), скачаем соответствующий дистрибутив (fasm-1.71.60.tgz), распакуем его, в папке у нас будет бинарный файл fasm, копируем этот файл в /usr/local/bin для того, чтобы можно было запускать его из консоли, как любую другую команду.Выполним ассемблирование программы hello.asm из папки fasm/examples/elfexe/hello.asm.

image

Корректность работы программы можно проверить в отладчике.

Nasm

Nasm успешно конкурирует со стандартным в Linux- и многих других UNIX-системах ассемблером Gas.

Nasm в Linux можно установить с помощью менеджера пакетов или из командной строки: в дистрибутиве Debian (Ubuntu) командой apt-get install nasm, в дистрибутивах Fedora, CentOS, RedHat командой yum install nasm.

Создадим программу, которая 5 раз выводит сообщение “Hello”. Пример взят из книги Андрея Викторовича Столярова “Программирование на языке ассемблера NASM для ОС UNIX”. Учебник, а также библиотека “stud_io.inc” есть на личном сайте автора.

%include "stud_io.inc"
global _start
section .text
_start: mov eax, 0
again:  PRINT "Hello"
PUTCHAR 10
inc eax
cmp eax, 5
jl again
FINISH

Выполним ассемблирование и линковку и запустим файл hello.asm.

$ nasm -f elf hello.asm
$ ld hello.o -o hello
$ ./hello

Для 64bit необходимо использовать команду nasm -f elf64 hello.asm

NASM для Windows

NASM для Windows можно установить, скачав соответствующий дистрибутив с соответствующего сайта.

Ассемблирование:
nasm -f bin имя_файла.asm -o имя_файла.com

Ссылки на ресурсы, посвященные Nasm:

→ Сайт А.В. Столярова
→ Сайт, на котором лежит электронный учебник (в архиве)
→ То же самое

AS

Стандартный ассемблер практически во всех разновидностях UNIX, в том числе Linux и BSD. Свободная версия этого ассемблера называется GAS (GNU assembler). Позволяет транслировать программы с помощью компилятора GCC.

Из учебников удалось найти только книгу на английском «Programming from the ground up». На русском удалось найти только одну главу из книги С. Зубкова «Assembler для DOS, Windows и UNIX».

Возьмем пример программы, которая ничего не делает, с сайта. Создадим программу gas.s

.section .text
   .globl _start
   _start:
      movl  $1, %eax
      movl  $2, %ebx
      int   $0x80

Выполним ассемблирование (трансляцию), линковку и запуск программы:

$ as -o gas.o gas.s
$ ld -o gas gas.o
$ ./gas

Если в данной программе изменить _start на main, то можно выполнить ассемблирование (трансляцию) и линковку компилятором gcc.

.section .text
   .globl main
   main:
      movl  $1, %eax
      movl  $2, %ebx
      int   $0x80

Выполним ассемблирование (трансляцию), линковку и запуск программы:

$ gcc gas.s -o gas
$ ./gas

Выводы: если вы изучаете программирование под Windows, то вы можете остановить свой выбор на Masm; Tasm больше не поддерживается, но для обучения по старым классическим учебникам подойдёт.
Под Linux Gas подойдет тем, кто использует GCC, а тем, кому не нравится синтаксис Gas, подойдёт Nasm.

P.S. Про обработку строк в ассемблере на примере создания транслятора простого «эзотерического» языка можно прочитать здесь.
P.P.S. Упрощенный ограниченный набор ассемблерных инструкций используется в учебной модели компьютера Little Man Computer, которому у меня также посвящено несколько статей ссылка.

На сегодняшний день существует огромное количество языков программирования высокого уровня. На их фоне программирование на низкоуровневом языке — ассемблере — может на первый взгляд показаться чем-то устаревшим и нерациональным. Однако это только кажется. Следует признать, что ассемблер фактически является языком процессора, а значит, без него не обойтись, пока существуют процессоры. Основными достоинствами программирования на ассемблере являются максимальное быстродействие и минимальный размер получаемых программ.

Недостатки зачастую обусловлены лишь склонностью современного рынка к предпочтению количества качеству. Современные компьютеры способны легко справиться с нагромождением команд высокоуровневых функций, а если нелегко — будьте добры обновите аппаратную часть вашей машины! Таков закон коммерческого программирования. Если же речь идет о программировании для души, то компактная и шустрая программа, написанная на ассемблере, оставит намного более приятное впечатление, нежели высокоуровневая громадина, обремененная кучей лишних операций. Бытует мнение, что программировать на ассемблере могут только избранные. Это неправда. Конечно, талантливых программистов-ассемблерщиков можно пересчитать по пальцам, но ведь так обстоит дело практически в любой сфере человеческой деятельности. Не так уж много найдется водителей-асов, но научиться управлять автомобилем сумеет каждый — было бы желание. Ознакомившись с данным циклом статей, вы не станете крутым хакером. Однако вы получите общие сведения и научитесь простым способам программирования на ассемблере для Windows, используя ее встроенные функции и макроинструкции компилятора. Естественно, для того, чтобы освоить программирование для Windows, вам необходимо иметь навыки и опыт работы в Windows. Сначала вам будет многое непонятно, но не расстраивайтесь из- за этого и читайте дальше: со временем все встанет на свои места.

Итак, для того, чтобы начать программировать, нам как минимум понадобится компилятор. Компилятор — это программа, которая переводит исходный текст, написанный программистом, в исполняемый процессором машинный код. Основная масса учебников по ассемблеру делает упор на использование пакета MASM32 (Microsoft Macro Assembler). Но я в виде разнообразия и по ряду других причин буду знакомить вас с молодым стремительно набирающим популярность компилятором FASM (Flat Assembler). Этот компилятор достаточно прост в установке и использовании, отличается компактностью и быстротой работы, имеет богатый и емкий макросинтаксис, позволяющий автоматизировать множество рутинных задач. Его последнюю версию вы можете скачать по адресу: сайт выбрав flat assembler for Windows. Чтобы установить FASM, создайте папку, например, «D:FASM» и в нее распакуйте содержимое скачанного zip-архива. Запустите FASMW.EXE и закройте, ничего не изменяя. Кстати, если вы пользуетесь стандартным проводником, и у вас не отображается расширение файла (например, .EXE), рекомендую выполнить Сервис -> Свойства папки -> Вид и снять птичку с пункта Скрывать расширения для зарегистрированных типов файлов. После первого запуска компилятора в нашей папке должен появиться файл конфигурации — FASMW.INI. Откройте его при помощи стандартного блокнота и допишите в самом низу 3 строчки:
[Environment]
Fasminc=D:FASMINCLUDE
Include=D:FASMINCLUDE

Если вы распаковали FASM в другое место — замените «D:FASM» на свой путь. Сохраните и закройте FASMW.INI. Забегая вперед, вкратце объясню, как мы будем пользоваться компилятором:
1. Пишем текст программы, или открываем ранее написанный текст, сохраненный в файле .asm, или вставляем текст программы из буфера обмена комбинацией.
2. Жмем F9, чтобы скомпилировать и запустить программу, или Ctrl+F9, чтобы только скомпилировать. Если текст программы еще не сохранен — компилятор попросит сохранить его перед компиляцией.
3. Если программа запустилась, тестируем ее на правильность работы, если нет — ищем ошибки, на самые грубые из которых компилятор нам укажет или тонко намекнет.
Ну, а теперь мы можем приступить к долгожданной практике. Запускаем наш FASMW.EXE и набираем в нем код нашей первой программы:

include ‘%fasminc%/win32ax.inc’

.data
Caption db ‘Моя первая программа.’,0
Text db ‘Всем привет!’,0

.code
start:
invoke MessageBox,0,Text,Caption,MB_OK
invoke ExitProcess,0

.end start

Жмем Run -> Run, или F9 на клавиатуре. В окне сохранения указываем имя файла и папку для сохранения. Желательно привыкнуть сохранять каждую программу в отдельную папку, чтобы не путаться в будущем, когда при каждой программе может оказаться куча файлов: картинки, иконки, музыка и прочее. Если компилятор выдал ошибку, внимательно перепроверьте указанную им строку — может, запятую пропустили или пробел. Также необходимо знать, что компилятор чувствителен к регистру, поэтому .data и .Data воспринимаются как две разные инструкции. Если же вы все правильно сделали, то результатом будет простейший MessageBox (рис. 1). Теперь давайте разбираться, что же мы написали в тексте программы. В первой строке директивой include мы включили в нашу программу большой текст из нескольких файлов. Помните, при установке мы прописывали в фасмовский ини-файл 3 строчки? Теперь %fasminc% в тексте программы означает D:FASMINCLUDE или тот путь, который указали вы. Директива include как бы вставляет в указанное место текст из другого файла. Откройте файл WIN32AX.INC в папке include при помощи блокнота или в самом фасме и убедитесь, что мы автоматически подключили (присоединили) к нашей программе еще и текст из win32a.inc, macro/if.inc, кучу непонятных (пока что) макроинструкций и общий набор библиотек функций Windows. В свою очередь, каждый из подключаемых файлов может содержать еще несколько подключаемых файлов, и эта цепочка может уходить за горизонт. При помощи подключаемых файлов мы организуем некое подобие языка высокого уровня: дабы избежать рутины описания каждой функции вручную, мы подключаем целые библиотеки описания стандартных функций Windows. Неужели все это необходимо такой маленькой программе? Нет, это — что-то вроде «джентльменского набора на все случаи жизни». Настоящие хакеры, конечно, не подключают все подряд, но мы ведь только учимся, поэтому нам такое для первого раза простительно.

Далее у нас обозначена секция данных — .data. В этой секции мы объявляем две переменные — Caption и Text. Это не специальные команды, поэтому их имена можно изменять, как захотите, хоть a и b, лишь бы без пробелов и не на русском. Ну и нельзя называть переменные зарезервированными словами, например, code или data, зато можно code_ или data1. Команда db означает «определить байт» (define byte). Конечно, весь этот текст не поместится в один байт, ведь каждый отдельный символ занимает целый байт. Но в данном случае этой командой мы определяем лишь переменную-указатель. Она будет содержать адрес, в котором хранится первый символ строки. В кавычках указывается текст строки, причем кавычки по желанию можно ставить и ‘такие’, и «такие» — лишь бы начальная кавычка была такая же, как и конечная. Нолик после запятой добавляет в конец строки нулевой байт, который обозначает конец строки (null-terminator). Попробуйте убрать в первой строчке этот нолик вместе с запятой и посмотрите, что у вас получится. Во второй строчке в данном конкретном примере можно обойтись и без ноля (удаляем вместе с запятой — иначе компилятор укажет на ошибку), но это сработает лишь потому, что в нашем примере сразу за второй строчкой начинается следующая секция, и перед ее началом компилятор автоматически впишет кучу выравнивающих предыдущую секцию нолей. В общих случаях ноли в конце текстовых строк обязательны! Следующая секция — секция исполняемого кода программы — .code. В начале секции стоит метка start:. Она означает, что именно с этого места начнет исполняться наша программа. Первая команда — это макроинструкция invoke. Она вызывает встроенную в Windows API-функцию MessageBox. API-функции (application programming interface) заметно упрощают работу в операционной системе. Мы как бы просим операционную систему выполнить какое-то стандартное действие, а она выполняет и по окончании возвращает нам результат проделанной работы. После имени функции через запятую следуют ее параметры. У функции MessageBox параметры такие:

1-й параметр должен содержать хэндл окна-владельца. Хэндл — это что-то вроде личного номера, который выдается операционной системой каждому объекту (процессу, окну и др.). 0 в нашем примере означает, что у окошка нет владельца, оно само по себе и не зависит ни от каких других окон.
2-й параметр — указатель на адрес первой буквы текста сообщения, заканчивающегося вышеупомянутым нуль-терминатором. Чтобы наглядно понять, что это всего лишь адрес, сместим этот адрес на 2 байта прямо в вызове функции: invoke MessageBox,0,Text+2,Caption,MB_OK и убедимся, что теперь текст будет выводиться без первых двух букв.
3-й — указатель адреса первой буквы заголовка сообщения.
4-й — стиль сообщения. Со списком этих стилей вы можете ознакомиться, например, в INCLUDEEQUATES USER32.INC. Для этого вам лучше будет воспользоваться поиском в Блокноте, чтобы быстро найти MB_OK и остальные. Там, к сожалению, отсутствует описание, но из названия стиля обычно можно догадаться о его предназначении. Кстати, все эти стили можно заменить числом, означающим тот, иной, стиль или их совокупность, например: MB_OK + MB_ICONEXCLAMATION. В USER32.INC указаны шестнадцатеричные значения. Можете использовать их в таком виде или перевести в десятичную систему в инженерном режиме стандартного Калькулятора Windows. Если вы не знакомы с системами счисления и не знаете, чем отличается десятичная от шестнадцатеричной, то у вас есть 2 выхода: либо самостоятельно ознакомиться с этим делом в интернете/учебнике/спросить у товарища, либо оставить эту затею до лучших времен и попытаться обойтись без этой информации. Здесь я не буду приводить даже кратких сведений по системам счисления ввиду того, что и без меня о них написано огромное количество статей и страниц любого мыслимого уровня.

Вернемся к нашим баранам. Некоторые стили не могут использоваться одновременно — например, MB_OKCANCEL и MB_YESNO. Причина в том, что сумма их числовых значений (1+4=5) будет соответствовать значению другого стиля — MB_RETRYCANCEL. Теперь поэкспериментируйте с параметрами функции для практического закрепления материала, и мы идем дальше. Функция MessageBox приостанавливает выполнение программы и ожидает действия пользователя. По завершении функция возвращает программе результат действия пользователя, и программа продолжает выполняться. Вызов функции ExitProcess завершает процесс нашей программы. Эта функция имеет лишь один параметр — код завершения. Обычно, если программа нормально завершает свою работу, этот код равен нулю. Чтобы лучше понять последнюю строку нашего кода — .end start, — внимательно изучите эквивалентный код: format PE GUI 4.0

include ‘%fasminc%/win32a.inc’

entry start

section ‘.data’ data readable writeable

Caption db ‘Наша первая программа.’,0
Text db ‘Ассемблер на FASM — это просто!’,0

section ‘.code’ code readable executable
start:
invoke MessageBox,0,Text,Caption,MB_OK
invoke ExitProcess,0

section ‘.idata’ import data readable writeable
library KERNEL32, ‘KERNEL32.DLL’,
USER32, ‘USER32.DLL’

import KERNEL32,
ExitProcess, ‘ExitProcess’

import USER32,
MessageBox, ‘MessageBoxA’

Для компилятора он практически идентичен предыдущему примеру, но для нас этот текст выглядит уже другой программой. Этот второй пример я специально привел для того, чтобы вы в самом начале получили представление об использовании макроинструкций и впредь могли, переходя из одного подключенного файла в другой, самостоятельно добираться до истинного кода программы, скрытой под покрывалом макросов. Попробуем разобраться в отличиях. Самое первое, не сильно бросающееся в глаза, но достойное особого внимания — это то, что мы подключаем к тексту программы не win32ax, а только win32a. Мы отказались от большого набора и ограничиваемся малым. Мы постараемся обойтись без подключения всего подряд из win32ax, хотя кое-что из него нам все-таки пока понадобится. Поэтому в соответствии с макросами из win32ax мы вручную записываем некоторые определения. Например, макрос из файла win32ax:
macro .data { section ‘.data’ data readable writeable }

во время компиляции автоматически заменяет .data на section ‘.data’ data readable writeable. Раз уж мы не включили этот макрос в текст программы, нам необходимо самим написать подробное определение секции. По аналогии вы можете найти причины остальных видоизменений текста программы во втором примере. Макросы помогают избежать рутины при написании больших программ. Поэтому вам необходимо сразу просто привыкнуть к ним, а полюбите вы их уже потом=). Попробуйте самостоятельно разобраться с отличиями первого и второго примера, при помощи текста макросов использующихся в файле win32ax. Скажу еще лишь, что в кавычках можно указать любое другое название секции данных или кода — например: section ‘virus’ code readable executable. Это просто название секции, и оно не является командой или оператором. Если вы все уяснили, то вы уже можете написать собственный вирус. Поверьте, это очень легко. Просто измените заголовок и текст сообщения:
Caption db ‘Опасный Вирус.’,0

Text db ‘Здравствуйте, я — особо опасный вирус-троян и распространяюсь по интернету.’,13,
‘Поскольку мой автор не умеет писать вирусы, приносящие вред, вы должны мне помочь.’,13,
‘Сделайте, пожалуйста, следующее:’,13,
‘1.Сотрите у себя на диске каталоги C:Windows и C:Program files’,13,
‘2.Отправьте этот файл всем своим знакомым’,13,
‘Заранее благодарен.’,0

Число 13 — это код символа «возврат каретки» в майкрософтовских системах. Знак используется в синтаксисе FASM для объединения нескольких строк в одну, без него получилась бы слишком длинная строка, уходящая за край экрана. К примеру, мы можем написать start:, а можем — и st
ar
t:

Компилятор не заметит разницы между первым и вторым вариантом.
Ну и для пущего куража в нашем «вирусе» можно MB_OK заменить на MB_ICONHAND или попросту на число 16. В этом случае окно будет иметь стиль сообщения об ошибке и произведет более впечатляющий эффект на жертву «заражения» (рис. 2).

Вот и все на сегодня. Желаю вам успехов и до новых встреч!
Все приводимые примеры были протестированы на правильность работы под Windows XP и, скорее всего, будут работать под другими версиями Windows, однако я не даю никаких гарантий их правильной работы на вашем компьютере. Исходные тексты программ вы можете найти на форуме: сайт

BarMentaLisk, q@sa-sec.org SASecurity gr.

Компьютерная газета. Статья была опубликована в номере 17 за 2008 год в рубрике программирование

Последнее обновление: 23.12.2022

Установка Arm GNU Toolchain на Windows

Наиболее популярным инструментом для компиляции кода ассемблера для arm представляет компилятор GAS от проекта GNU, который входит в состав комплекта инструментов
для разработки под ARM — Arm GNU Toolchain. Итак, вначале установим данный набор инструментов. Для этого перейдем на официальный сайт компании Arm
на страницу https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads.
Здесь представлены поседние версии Arm GNU Toolchain для разных архитектур.

GNU Arm Embedded Toolchain для ARM64 ассемблера

Каждая версия Arm GNU Toolchain привязана к определенной версии компиляторов GCC. Например, версия Arm GNU Toolchain 12.2.Rel1
привязан к версии 12.2 набора компиляторов gcc.

Для ОС Windows доступно несколько групп пакетов по различные архитектуры:

  • AArch32 bare-metal target (arm-none-eabi): для компиляции программ под 32-битные архитектуры без привязки к конкретной операционной системе

  • AArch32 GNU/Linux target with hard float (arm-none-linux-gnueabihf): для компиляции программ под 32-битную ОС Linux

  • AArch64 bare-metal target (aarch64-none-elf): для компиляции программ под 64-битные архитектуры без привязки к конкретной операционной системе

  • AArch64 GNU/Linux target (aarch64-none-linux-gnu): для компиляции программ под 64-битную ОС Linux

Как видно из названия, наборы компиляторов имеют названия типа arm-none-linux-gnueabi, arm-none-eabi, arm-eabi и т.д. Все эти названия формируются по шаблону

arch[-vendor] [-os] - eabi
  • arch: указывает на архитектуру

  • vendor: указывает на производителя

  • os: указывает на целевую операционную систему

  • eabi: сокращение от Embedded Application Binary Interface

Например, пакет инструментов arm-none-eabi предназначен для 32-х битной архитектуры, не зависит от конкретного вендора, операционной системы и компилируется с помощью ARM EABI.

Другой пример: ракет инструментов arm-none-linux-gnueabi предназначен для 32-х битной архитектуры, но создает бинарники непосредственно для ОС Linux и использует GNU EABI.

Поскольку в данном случае в данном случае мы рассматриваем именно arm64, то нас будет интересовать прежде всего те пакеты, которые начинаются на AArch64.
И поскольку пакет AArch64 bare-metal target (aarch64-none-elf) не привязан к определенной ОС, то выберем его. Кроме того, он доступен для всех основных ОС. Однако отмечу, что, если планируется писать код именно под
Linux (в том числе Android), то лучше использовать AArch64 GNU/Linux target (aarch64-none-linux-gnu) — он создает более компактные (иногда намного меньшие) исполняемые файлы.

Для Windows доступны пакеты в двух вариантах: установочный файл exe, который устанавливает все необходимые файлы в папку C:Program Files (x86), и
zip-архив — по сути те же самые файлы, которые мы можем распаковать в любое нужное для нас расположение. Большой разницы между файлами из exe и zip нет, но для простоты выберем exe-файл (в моем случае это файл
arm-gnu-toolchain-12.2.rel1-mingw-w64-i686-aarch64-none-elf.exe

Установка GNU Arm Embedded Toolchain для ARM64 ассемблера под Windows

После загрузки запустим установщик

Установка компилятора gas из GNU Arm Embedded Toolchain для ARM64 под Windows

Прощелкаем по шагам и в конце на последнем окне после установки установим флажок Add path to environment variable, чтобы добавить путь к компилятору и другим инструментам
в переменные среды:

Добавление пути к компилятору GNU Arm Embedded Toolchain для ARM64 в переменные среды

Если мы посмотрим на добавленный в переменные среды путь (в данном случае каталог C:Program Files (x86)Arm GNU Toolchain aarch64-none-elf12.2 rel1bin),
то мы найдем файлы компилятора и ряд других файлов:

ассемблер as из GNU Arm Embedded Toolchain для ARM64 под Windows

В этом комплекте нам понадобится прежде всего сам ассемблер — файл aarch64-none-elf-as.exe, который по коду ассемблера Arm64 создает объектный файл. Кроме того,
также потребуется файл aarch64-none-elf-as.ld, который также располагается в этой папке и который генерирует из объектного файла исполныемый файл.

Для проверки настройки откроем терминал/командную строку и выведем версию компилятора следующей командой:

aarch64-none-elf-as --version

Мы должны получить вывод типа следующего:

GNU assembler (Arm GNU Toolchain 12.2.Rel1 (Build arm-12.24)) 2.39.0.20221210
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `aarch64-none-elf'.

C:Userseugen>

Создание первой программы

Теперь напишем первую простейшую программу, которая просто будет выводить на консоль некоторую строку. Для этого создадим на жестком диске какой-нибудь каталог, например, C:arm.
Создадим в этого каталоге новый файл hello.s (обычно файлы с кодом ассемблера arm имеют расширение .s). Определим в этом файл следующий код:

.global _start          // устанавливаем стартовый адрес программы

_start: mov X0, #1          // 1 = StdOut - поток вывода
 ldr X1, =hello             // строка для вывода на экран
 mov X2, #19                // длина строки
 mov X8, #64                // устанавливаем функцию Linux
 svc 0                      // вызываем функцию Linux для вывода строки

 mov X0, #0                 // Устанавливаем 0 как код возврата
 mov X8, #93                // код 93 представляет завершение программы
 svc 0                      // вызываем функцию Linux для выхода из программы

.data
hello: .ascii "Hello METANIT.COM!n"    // данные для вывода

Для большего понимания я снабдил программу комментариями. GNU Assembler использует тот же самый синтаксис комментариев, что и C/C++ и другие си-подобные
языки: одиночный комментарий начинается с двойного слеша //. Также можно использовать многострочный комментарий с помощью символов /∗ и ∗/, между которыми помещается
текст комментария (/* текст комментария */

Вначале надо указать линкеру (в нашем случае программа ld) стартовую точку программы. В данной программе стартовая точка программы проецируется
на метку _start. И чтобы линкер получил к ней доступ, определяет _start в качестве глобальной переменной с помощью оператора global.

.global _start

Одна программа может состоять из множества файлов, но только один из них может иметь точку входа в программу _start

Далее идут собственно действия программы. Вначале вызывается инструкция mov, которая помещает данные в регистр.

mov X0, #1

Значения X0-X2 представляют регистры для параметров функции в Linux. В данном случае помещаем в регистр X0 значение «#1». Операнды начинаются со знака «#»
Число 1 представляет номер стандартного потока вывода «StdOut», в данном случае, грубо говоря, вывод на консоль.

Далее загружаем в регистр X1 адрес строки для вывода на экран с помощью инструкции ldr

ldr X1, =hello 

Затем также с помощью инструкции mov помещаем в регистр X2 длину выводимой строки

mov X2, #19

Для любого системного вызова в Linux параметры помещаются в регистры X0–X7 в зависимости от количества. Затем в регистр X0 помещается код возврата. А сам системный вызов
определяется номером функции из регистра X8. Здесь помещаем в X8 функцию с номеро 64 (функция write)

mov X8, #64

Далее выполняем системный вызов с помощью оператора svc

svc 0 

Операционная система, используя параметры в регистрах и номер функции, выведет строку на экран.

После этого нам надо выйти из программы. Для этого помещаем в регистр X0 число 0

mov X0, #0

А в регистр X8 передаем число 93 — номер функции для выхода из программы (функция exit)

mov X8, #93

И с помощью svc также выполняем функции. После этого программа должна завершить выполнение.

В самом конце программы размещена секция данных

.data
hello: .ascii "Hello METANIT.COM!n"    // данные для вывода

Оператор .data указывает, что дальше идет секция данных. Выражение .ascii выделяет память и помещает в нее указанную далее строку.

Строка завершается символом перевода строки «n», чтобы не надо было нажимать на Return, чтобы увидеть текст в окне терминала.

Компиляция приложения

Для компиляции приложения откроем терминал/командную строку и командой cd перейдем к папке, где расположен файл hello.s с
исходным кодом программы. И для компиляции выполним команду:

aarch64-none-elf-as hello.s -o hello.o

Компилятору aarch64-none-elf-as в качестве параметра передается файл с исходным кодом hello.s. А параметр -o указывает, в какой файл будет компилироваться
программа — в данном случае в файл hello.o. Соответственно в папке программы появится файл hello.o

Затем нам нужно скомпновать программу с исполняемый файл с помощью линкера aarch64-none-elf-ld командой:

aarch64-none-elf-ld hello.o -o hello

Полный вывод:

C:Userseugen>cd c:arm

c:arm>aarch64-none-elf-as hello.s -o hello.o

c:arm>aarch64-none-elf-ld hello.o -o hello

c:arm>

После этого в папке программы появится исполняемый файл hello, который мы можем запускать на устройстве с архитектурой ARM под управлением Linux.

компиляция и линковка программы на ассемблере arm64 на Windows

Тестирование приложения на Android

Итак, у нас есть исполняемый файл программы. Мы ее можем протестировать. Для этого нам нужен Linux на устройстве с архитектурой ARM. В качестве такого устройства я возьму самый распространенный вариант
— смартфон под управлением Android. Поскольку Android построен на базе Linux и как правило устанавливается на устройства с arm архитектурой.

Для установки файла на Android нам понадобится консольная утилита adb, которая устанавливается в рамках Android SDK. Android SDK обычно устанавливается
вместе с Android Studio. Но если Android Studio не установлена, то можно загрузить пакет https://dl.google.com/android/repository/platform-tools-latest-windows.zip.
В составе этого пакета или в составе SDK в папке platforms-tools можно найти нужную нам утилиту adb.

тестирование на Android программы на ассемблере arm64, скомпилированной на Windows

Для упрощения работы путь к этой утилите лучше добавить в переменные среды, чтобы не прописывать к ней полный путь.

Теперь переместим скомпилированный файл hello на устройство под Android. Для этого подключим через usb к компьютеру смарфтон с Android и перейдем в консоли с помощью команды cd к папке с файлом hello используем следующую команду

[Путь_к_файлу_adb]/adb push hello /data/local/tmp/hello

То есть в данном случае используем команду push для помещения копии файла hello на смартфон в папку /data/local/tmp/

Установка программы на ассемблере arm64 на Android

Далее перейдем к консоли устройства Android с помощью команды:

Далее перейдем к папке /data/local/tmp с помощью команды

Затем изменим режим файла, чтобы его можно было запустить:

и в конце выполним файл hello

И на консоль должна быть выведена строка «Hello METANIT.COM!»

Первая программа на ассемблере arm64 на Android с компиляцией на Windows

=======================================================================

Посмотрев несколько блогов, я составил метод, который вам подходит
1.https://blog.csdn.net/doniexun/article/details/45438457

Если вы хотите изменить размер окна, вы можете обратиться к следующему блогу:
2.https://blog.csdn.net/m0_37822685/article/details/80241598

3. Использование masm может ссылаться на этот блог:
https://www.cnblogs.com/lihaiyan/p/4274475.html

Некоторые ссылки для загрузки masm в справочном блоге недействительны, добавьте:
файл конфигурации masm: ссылка:https://pan.baidu.com/s/1b3Keh2OKF0o5tjtmDXPVag
Код извлечения: 1vlu

DOSBox можно скачать прямо на официальном сайте:
https://www.dosbox.com/download.php?main=1

=======================================================================

шаг:

  1. Загрузите и установите DOSBox, обратите внимание на изменение каталога установки на подходящее место, например, на диск D.
    (Полная автоматическая установка, обратите внимание на изменение каталога установки)
  2. Поместите папку masm в подходящий путь, например: D: masm

    3. Измените файл конфигурации DOSBox.

    Добавьте следующие поля после тега [autoexc] файла конфигурации (внизу файла конфигурации):
MOUNT C D:  masm # Смонтировать каталог D:  masm как C в DOSBOX:
 установить PATH = $ PATH $; D:  masm # записать D:  masm в переменную окружения PATH


После сохраненияЗакрыть файл

4. После двойного щелчка, чтобы запустить DOSBox.exe, инструкция на рисунке ниже показывает, что конфигурация вступает в силу.

напрямую введите «C:», чтобы перейти в каталог masm.

Gubila_2000, освоив команды, вы вполне можете взять компилятор для Windows, и создавать рабочие приложения. В разделах есть закреплённые темы, в которых хорошо освещено создание программ для Windows.
Сам себе Iczelion
Создание консольных приложений в 64-разрядной Windows Seven
Уроки Iczelion’a на FASM
Ещё для программирования в Windows отлично помогает книга Чарльза Петзольда «Программирование в Windows». Она для языка C, но для понимания Win32 API — просто идеальна.

За исключением других шаблонов исходников (структуры программы), другого способа вызова API (DOS или Windows), больших размеров регистров — отличий почти нет.

В masm32 есть множество примеров, которые можно использовать, как заготовки.

Не вижу смысла асм программ с GUI интерфейсом, но в консоль вывод не сложнее, чем в DOS.

Редактор. Много копий сломано по этому поводу. Лично я для учебных asm программ на форум использую или SciTE или идущий в комплекте с masm32 редактор qeditor (основная проблема с настройкой путей ко включаемым файлам и библиотекам). Отладку выполняю в OllyDbg, но последнее время на форуме пропагандируют «более новый и лучший» x64dbg.

Многие считают, что Assembler – уже устаревший и нигде не используемый язык, однако в основном это молодые люди, которые не занимаются профессионально системным программированием. Разработка ПО, конечно, хорошо, но в отличие от высокоуровневых языков программирования, Ассемблер научит глубоко понимать работу компьютера, оптимизировать работку с аппаратными ресурсами, а также программировать любую технику, тем самым развиваясь в направлении машинного обучения. Для понимания этого древнего ЯП, для начала стоит попрактиковаться с простыми программами, которые лучше всего объясняют функционал Ассемблера.

IDE для Assembler

Первый вопрос: в какой среде разработки программировать на Ассемблере? Ответ однозначный – MASM32. Это стандартная программа, которую используют для данного ЯП. Скачать её можно на официальном сайте masm32.com в виде архива, который нужно будет распаковать и после запустить инсталлятор install.exe. Как альтернативу можно использовать FASM, однако для него код будет значительно отличаться.

Перед работой главное не забыть дописать в системную переменную PATH строчку:

С:masm32bin

Программа «Hello world» на ассемблере

Считается, что это базовая программа в программировании, которую начинающие при знакомстве с языком пишут в первую очередь. Возможно, такой подход не совсем верен, но так или иначе позволяет сразу же увидеть наглядный результат:

.386
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
 
.data
msg_title db "Title", 0
msg_message db "Hello world", 0
 
.code
start:
invoke MessageBox, 0, addr msg_message, addr msg_title, MB_OK
invoke ExitProcess, 0
end start

Для начала запускаем редактор qeditor.exe в папке с установленной MASM32, и в нём пишем код программы. После сохраняем его в виде файла с расширением «.asm», и билдим программу с помощью пункта меню «Project» → «Build all». Если в коде нет ошибок, программа успешно скомпилируется, и на выходе мы получим готовый exe-файл, который покажет окно Windows с надписью «Hello world».

Сложение двух чисел на assembler

В этом случае мы смотрим, равна ли сумма чисел нулю, или же нет. Если да, то на экране появляется соответствующее сообщение об этом, и, если же нет – появляется иное уведомление.

.486
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib

include /masm32/macros/macros.asm 
uselib masm32, comctl32, ws2_32

.data

.code
start:

mov eax, 123
mov ebx, -90 
add eax, ebx

test eax, eax

jz zero 
invoke MessageBox, 0, chr$("В eax не 0!"), chr$("Info"), 0
jmp lexit

zero:
invoke MessageBox, 0, chr$("В eax 0!"), chr$("Info"), 0

lexit:
invoke ExitProcess, 0

end start

Здесь мы используем так называемые метки и специальные команды с их использованием (jz, jmp, test). Разберём подробнее:

  • test – используется для логического сравнения переменных (операндов) в виде байтов, слов, или двойных слов. Для сравнения команда использует логическое умножение, и смотрит на биты: если они равны 1, то и бит результата будет равен 1, в противном случае – 0. Если мы получили 0, ставятся флаги совместно с ZF (zero flag), которые будут равны 1. Далее результаты анализируются на основе ZF.
  • jnz – в случае, если флаг ZF нигде не был поставлен, производится переход по данной метке. Зачастую эта команда применяется, если в программе есть операции сравнения, которые как-либо влияют на результат ZF. К таким как раз и относятся test и cmp.
  • jz – если флаг ZF всё же был установлен, выполняется переход по метке.
  • jmp – независимо от того, есть ZF, или же нет, производится переход по метке.

Программа суммы чисел на ассемблере

Примитивная программа, которая показывает процесс суммирования двух переменных:

.486
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib

include /masm32/macros/macros.asm 
uselib masm32, comctl32, ws2_32

.data
msg_title db "Title", 0
A DB 1h
B DB 2h
buffer db 128 dup(?)
format db "%d",0

.code
start:

MOV AL, A
ADD AL, B

invoke wsprintf, addr buffer, addr format, eax
invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK

invoke ExitProcess, 0

end start

В Ассемблере для того, чтобы вычислить сумму, потребуется провести немало действий, потому как язык программирования работает напрямую с системной памятью. Здесь мы по большей частью манипулируем ресурсами, и самостоятельно указываем, сколько выделить под переменную, в каком виде воспринимать числа, и куда их девать.

Получение значения из командной строки на ассемблере

Одно из важных основных действий в программировании – это получить данные из консоли для их дальнейшей обработки. В данном случае мы их получаем из командной строки и выводим в окне Windows:

.486
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib

include /masm32/macros/macros.asm 
uselib masm32, comctl32, ws2_32

.data

.code
start:

call GetCommandLine ; результат будет помещен в eax
 
push 0
push chr$("Command Line")
push eax ; текст для вывода берем из eax
push 0
call MessageBox

push 0
call ExitProcess

end start

Также можно воспользоваться альтернативным методом:

.486
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib

include /masm32/macros/macros.asm 
uselib masm32, comctl32, ws2_32

.data

.code
start:

call GetCommandLine ; результат будет помещен в eax
 
invoke GetCommandLine
invoke MessageBox, 0, eax, chr$("Command Line"), 0
invoke ExitProcess, 0

push 0
call ExitProcess

end start

Здесь используется invoke – специальный макрос, с помощью которого упрощается код программы. Во время компиляции макрос-команды преобразовываются в команды Ассемблера. Так или иначе, мы пользуемся стеком – примитивным способом хранения данных, но в тоже время очень удобным. По соглашению stdcall, во всех WinAPI-функциях переменные передаются через стек, только в обратном порядке, и помещаются в соответствующий регистр eax.

Циклы в ассемблере

Вариант использования:

.data

msg_title db "Title", 0
A DB 1h
buffer db 128 dup(?)
format db "%d",0

.code
start:

mov AL, A
.REPEAT
inc AL

.UNTIL AL==7

invoke wsprintf, addr buffer, addr format, AL
invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK
 
invoke ExitProcess, 0

end start
.data

msg_title db "Title", 0
buffer db 128 dup(?)
format db "%d",0

.code
start:

mov eax, 1
mov edx, 1

.WHILE edx==1
inc eax
.IF eax==7
.BREAK
.ENDIF
.ENDW

invoke wsprintf, addr buffer, addr format, eax
invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK
 
invoke ExitProcess, 0

Для создания цикла используется команда repeat. Далее с помощью inc увеличивается значение переменной на 1, независимо от того, находится она в оперативной памяти, или же в самом процессоре. Для того, чтобы прервать работу цикла, используется директива «.BREAK». Она может как останавливать цикл, так и продолжать его действие после «паузы». Также можно прервать выполнение кода программы и проверить условие repeat и while с помощью директивы «.CONTINUE».

Сумма элементов массива на assembler

Здесь мы суммируем значения переменных в массиве, используя цикл «for»:

.486
.model flat, stdcall
option casemap: none
 
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
 
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib

include /masm32/macros/macros.asm 
uselib masm32, comctl32, ws2_32

.data

msg_title db "Title", 0
A DB 1h
x dd 0,1,2,3,4,5,6,7,8,9,10,11
n dd 12

buffer db 128 dup(?)
format db "%d",0

.code
start:
mov eax, 0
mov ecx, n
mov ebx, 0
L: add eax, x[ebx]
add ebx, type x
dec ecx
cmp ecx, 0
jne L

invoke wsprintf, addr buffer, addr format, eax
invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK
 
invoke ExitProcess, 0

end start

Команда dec, как и inc, меняет значение операнда на единицу, только в противоположную сторону, на -1. А вот cmp сравнивает переменные методом вычитания: отнимает одно значение из второго, и, в зависимости от результата ставит соответствующие флаги.

С помощью команды jne выполняется переход по метке, основываясь на результате сравнения переменных. Если он отрицательный – происходит переход, а если операнды не равняются друг другу, переход не осуществляется.

Ассемблер интересен своим представлением переменных, что позволяет делать с ними что угодно. Специалист, который разобрался во всех тонкостях данного языка программирования, владеет действительно ценными знаниями, которые имеют множество путей использования. Одна задачка может решаться самыми разными способами, поэтому путь будет тернист, но не менее увлекательным.


Post Views:
55 436

Понравилась статья? Поделить с друзьями:
  • Как программировать на swift на windows 10
  • Как программировать для ios на windows
  • Как программировать в командной строке windows 10
  • Как проводник закрепить на рабочем столе windows 10
  • Как проводить дефрагментацию в windows 10