Turbo assembler (tasm) 3.0.1
Содержание:
- Как мыслит процессор
- О программе
- Инструкции MIPS
- Разбор: что значат этот весь текст?
- Трансляция и запуск программы
- О компиляторах
- Оговорочки
- Подытожим…
- 6.5.4 elf-расширение директивы COMMON
- 6.6 aout: Объектные файлы a.out Линукс
- 6.7 aoutb: Объектные файлы a.out NetBSD/FreeBSD/OpenBSD
- 6.8 as86: Объектные файлы as86 Линукс
- 6.9 rdf: Перемещаемые динамические объектные файлы
- Простейшая программа
Как мыслит процессор
Чтобы понять, как работает Ассемблер и почему он работает именно так, нам нужно немного разобраться с внутренним устройством процессора.
Кроме того, что процессор умеет выполнять математические операции, ему нужно где-то хранить промежуточные данные и служебную информацию. Для этого в самом процессоре есть специальные ячейки памяти — их называют регистрами.
Регистры бывают разного вида и назначения: одни служат, чтобы хранить информацию; другие сообщают о состоянии процессора; третьи используются как навигаторы, чтобы процессор знал, куда идти дальше, и так далее. Подробнее — в расхлопе ↓
Какими бывают регистры
Общего назначения. Это 8 регистров, каждый из которых может хранить всего 4 байта информации. Такой регистр можно разделить на 2 или 4 части и работать с ними как с отдельными ячейками.
Указатель команд. В этом регистре хранится только адрес следующей команды, которую должен выполнить процессор. Вручную его изменить нельзя, но можно на него повлиять различными командами переходов и процедур.
Регистр флагов. Флаг — какое-то свойство процессора. Например, если установлен флаг переполнения, значит процессор получил в итоге такое число, которое не помещается в нужную ячейку памяти. Он туда кладёт то, что помещается, и ставит в этот флаг цифру 1. Она — сигнал программисту, что что-то пошло не так.
Флагов в процессоре много, какие-то можно менять вручную, и они будут влиять на вычисления, а какие-то можно просто смотреть и делать выводы. Флаги — как сигнальные лампы на панели приборов в самолёте. Они что-то означают, но только самолёт и пилот знают, что именно.
Сегментные регистры. Нужны были для того, чтобы работать с оперативной памятью и получать доступ к любой ячейке. Сейчас такие регистры имеют по 32 бита, и этого достаточно, чтобы получить 4 гигабайта оперативки. Для программы на Ассемблере этого обычно хватает.
Так вот: всё, с чем работает Ассемблер, — это команды процессора, переменные и регистры.
Здесь нет привычных типов данных — у нас есть только байты памяти, в которых можно хранить что угодно. Даже если вы поместите в ячейку какой-то символ, а потом захотите работать с ним как с числом — у вас получится. А вместо привычных циклов можно просто прыгнуть в нужное место кода.
О программе
В SASM Вы можете легко разрабатывать и выполнять программы, написанные на языках ассемблера NASM, MASM, GAS, FASM. Вводите код в форму и запускайте приложение. В Windows также возможен запуск приложения в отдельном окне. Входные данные указывайте в поле «Ввод». В поле «Вывод» Вы сможете увидеть результат работы программы. При этом все сообщения и ошибки компиляции будут выводиться в форму снизу. Вы можете сохранять исходный или скомпилированный (exe) код программы в файл, а также загружать свои программы из файла.
Программа поддерживает работу с несколькими проектами – новые файлы открываются и создаются в новых вкладках. При выходе из программы текущий набор открытых файлов сохраняется. При следующем запуске Вы сможете восстановить предыдущую сессию. В параметрах настраивается шрифт, цветовая схема и текст, отображающийся при создании нового файла. Интерфейс программы доступен на восьми языках (русский, английский, турецкий (спасибо Ali Goren), китайский (спасибо Ahmed Zetao Yang), немецкий (спасибо Sebastian Fischer), итальянский (спасибо Carlo Dapor), польский (спасибо Krzysztof Rossa), иврит (спасибо Elian Kamal), испанский (спасибо Mariano Cordoba)). Все окна в программе плавающие, с возможностью закрепления в одной из множества позиций. Имеется возможность переназначения горячих клавиш.
Стандартное меню «Правка» дополнено возможностью комментирования/раскомментирования выделенного куска кода и создания/удаления отступа в 4 пробела (Tab/Shift+Tab).
В SASM вы можете находить ошибки в своих программах с помощью интерфейса к отладчику gdb. В программе можно просматривать значения регистров и переменных, а также устанавливать точки останова и перемещаться по отлаживаемой программе. Дополнительно имеется возможность выполнять произвольные команды отладчика gdb, результаты которых будут отображаться в логе.
SASM полностью поддерживает работу с четырьмя ассемблерами NASM, MASM, GAS, FASM в двух режимах — x64 и x86, переключаться между которыми можно в настройках на вкладке «Построение». Там же можно изменить опции ассемблера и компоновщика и выбрать, какие программы будут использоваться для ассемблирования и компоновки.
Инструкции MIPS
Примечание.MARSотсюда
Типы инструкций
- тип R (register). В роли операндов используются три регистра – регистр назначения (сокр. $rd), первый аргумент ($rs), и второй аргумент ($rt). Пример такой инструкции – сложение трёх регистров: В данном случае в $t2 будет помещён результат сложения значений в $t0 и $t1.
- тип I (immediate). Операнды – два регистра и число. Пример инструкции типа I: После выполнения в регистр $t3 будет помещён результат сложения $t2 и числа 12.
- Тип J (jump). Единственный операнд – 26-битный адрес, куда нужно перейти. Инструкция перейдёт на адрес 128 в .
Арифметические инструкции
- сумма rs и rt записывается в регистр rd. Аккуратно, может вызвать переполнение.
- rd = rs — rt. Также можно получить переполнение.
- почти то же самое, что и предыдущая инструкция, но эта не может вызвать переполнение. Для арифметических вычислений предпочтительно использовать именно эту инструкцию.
- rd = rs — rt. Также без переполнения, и поэтому рекомендуется к использованию.
- rt = rs + 16-битное целое число. Как и , может вызывать переполнение.
- то же самое, но без возможности переполнения. Use it.
отсюда
Разбор: что значат этот весь текст?
На 1 строчке: «format PE Console» — это строчка говорит FASM-у какой файл скомпилировать, точнее 1 слово, все остальные слова это аргументы (можно так сказать).
PE — EXE файл, программа.
Console — говорим что это у нас консольная программа, но вам некто не мешает сделать из консольной программы оконную и наоборот.
Но есть кроме это остальные:
-
format MZ — EXE-файл НО под MS-DOS
-
format PE — EXE-файл под Windows, аналогично format PE GUI 4.0
-
format PE64 — EXE-файл под Windows, 64 битное приложение.
-
format PE GUI 4.0 — EXE-файл под Windows, графическое приложение.
-
format PE Console — EXE-файл под Windows, консольная программа. (просто подключается заранее консоль)
-
format PE Native — драйвер
-
format PE DLL — DLL-файл Windows, поясню позднее.
-
format COFF — OBJ-файл Linux
-
format MS COFF — аналогично предыдущему
-
format ELF — OBJ-файл для gcc (Linux)
-
format ELF64 — OBJ-файл для gcc (Linux), 64-bit
Сразу за командой (для компилятора) идет это значит комментарий. К сожалению он есть только однострочный.
3 строка:
Говорим windows-у где\в каком месте стартовать. «start» это метка, но о метках чуть позже.
5 строка:
Подключает к проекту файл, в данном случае «win32a.inc» он находиться в папке INCLUDE (в папке с FASM). этот файл создает константы и создает макросы для облегчения программирования.
8 строка:
Секция данных, то есть программа делиться на секции (части), к этим секциям мы можем дать разрешение, имя.
Флаг «data» (Флаг это бит\байт\аргумент хранившей в себе какую-то информацию) говорит то что эта секция данных.
Флаги «readable writeable» говорят то что эта секция может читаться кем-то и записываться кем-то.
Текст ‘.data’ — имя секции
10 строка:
hello — это метка, она может быть любого имени (почти, есть некоторые зарезервированные имена), эта метка хранит в себе адрес строки, это не переменная, а просто адрес, но чтобы не запоминать адреса в ручную, помогает FASM он запоминает адрес и потом когда видит эту метку снова, то он заменяет слово на адрес.
db — говорит то что под каждый символ резервируем 1 байт. То есть 1 символ храниться в одном байте.
‘hello world!’ — наша строка в кодировке ASCII
Что значит «,0» в конце строки? — это символ с номером 0 (или просто ноль), у вас на клавиатуре нет клавиши которая имела символ с номером 0, по этому этот символ используют как показатель конца строки. То есть это значит конец строки. Просто ноль записываем в байт после строки.
12 строка:
Флаг «code» — говорит то что это секция кода.
Флаг «executable» — говорит то что эта секция исполняема, то есть в этой секции может выполняться код.
Все остальное уже разобрали.
14 строка:
Это второй вид меток. Просто эта метка указывает на следующую команду
Обратите внимание на то что в 3 строке мы указали start как метку входа в программу, это она и есть. Может иметь эта метка любое имя, главное не забудьте ваше новое имя метки вписать в
15 строка:
Функция printf — выводит текст\число в консоль. В данном случае текст по адресу «hello»
Это штото на подобие команды, но это и близко не команда ассемблера, а просто макрос.
Макрос — Это макро команда для компилятора, то есть вместо имени макроса подставляется что-то другое.
Например, макро команда invoke делиться на такие команды: (взят в пример команда с 15 строки)
Не переживайте если нечего не поняли.
17 строка:
getch — функция получения нажатой кнопки, то есть просто ждет нажатия кнопки и потом возвращает нажатую кнопку.
20 строка:
ExitProcess — WinAPI функция, она завершает программу. Она принимает значение, с которым завершиться, то есть код ошибки, ноль это нет ошибок.
23 строка:
Флаг «import» — говорит то что это секция импорта библиотек.
24-25 строки:
Макро команда «library» загружает DLL библиотеки в виртуальную память (не в ОЗУ, вам ОЗУ не хватит чтоб хранить всю виртуальную память).
Что такое DLL объясню позже.
kernel — имя которое привязывается к библиотеке, оно может быть любым.
Следующий текст после запятой: — это имя DLL библиотеки который вы хотите подключить.
Дальше есть знак это значит что текст на следующей строке нужно подставить в эту строку.
То есть код:
Заменяется на:
Это нужно потому что у ассемблера 1 строка это 1 команда.
27-28 строка:
— Макро команда, которая загружает функции из DLL.
— Имя к которой привязана DLL, может быть любым.
— Как будет называться функция в программе, это имя будет только в вашей программе, и по этому имени вы будете вызывать функцию. (WinAPI функция)
— Это имя функции которое будет загружено из DLL, то есть это имя функции которое прописано в DLL.
Дальше думаю не стоит объяснять, вроде все понятно.
Трансляция и запуск программы
Дважды щелкните по файлу , который вы скачали на шаге установки.
Откроется окно командной строки. Убедитесь, что все сделано правильно, набрав
команду и нажав . Вы должны увидеть, что в текущем каталоге
(вашем рабочем каталоге) находятся файлы и :
Примечание для тех, кто никогда прежде не работал с командной строкой.
Взаимодействие с ней устроено следующим образом: командная строка выводит
приглашение (в примере выше это ), далее пользователь вводит
команду (выше — ) и нажимает клавишу , после чего на
экране появляется вывод команды, то есть результат ее работы.
Для запуска программы требуется ее оттранслировать. Первый шаг — запуск
ассемблера MASM, который построит по исходному тексту програмы объектный
файл:
Аргумент инструктирует ассемблер выполнить только трансляцию в объектный
файл, без компоновки (которую мы выполним чуть позже). Аргумент
указывает формат объектного файла — COFF (Common Object File Format).
В рабочем каталоге появится файл . Запустите компоновщик:
Аргумент говорит компоновщику, что нужно построить
консольное Windows-приложение.
В рабочем каталоге появится файл . Это исполняемый файл, который
уже можно запустить:
О компиляторах
Какую операционную систему вы бы хотели использовать?
Windows | DOS | Linux | BSD | QNX | MacOS, работающий на процессоре Intel/AMD |
|
---|---|---|---|---|---|---|
FASM | x | x | x | x | ||
GAS | x | x | x | x | x | x |
GoAsm | x | |||||
HLA | x | x | ||||
MASM | x | x | ||||
NASM | x | x | x | x | x | x |
RosAsm | x | |||||
TASM | x | x |
Качество документации
Документация | Комментарии | |
---|---|---|
FASM | Хорошая | Большую часть свободного времени автор отдает в разработку инновационного FASMG. Тем не менее, автор обеспечивает поддержку FASM время от времени обновляет мануалы, а новые функции описывает на собственном форуме. Документацию можно считать достаточно хорошей. Веб-страница документации. |
Gas | Плохая | документирован слабо и документация, скорее, имеет «общий вид». gas ― это ассемблер, который был разработан, чтобы можно было легко писать код для разных процессоров. Документация, которая существует, в основном описывает псевдо коды и ассемблерные директивы. В режиме работы «intel_syntax» документация практически отсутствует. Книги, в которых используется синтаксис «AT&T»: «Программирование с нуля» Джонатона Бартлетта и «Профессиональный язык ассемблера» Ричарда Блюма, Konstantin Boldyshev asmutils — Linux Assembly. |
GoAsm | Слабая | Большая часть синтаксиса описана в руководстве, и опытный пользователь найдет то, что ищет. Множество руководств и размещено на сайте (http://www.godevtool.com/). Несколько учебников GoAsm:
|
HLA | Обширая | HLA имеет справочное руководство на 500 страниц. Сайт содержит десятки статей и документацию по HLA. |
MASM | Хорошая | Компанией Microsoft написано значительное количество документацию для MASM, существует большое количество справочников написанных для этого диалекта. |
NASM | Хорошая | Авторы NASM больше пишут программное обеспечение для этого диалекта, оставляя написание руководства на «потом». NASM существует достаточно долго, поэтому несколько авторов написали руководство для NASM Джефф Дунтеман (Jeff Duntemann) «Assembly Language Step-by-Step: Programming with Linux», Jonathan Leto «Writing A Useful Program With NASM», на русском языке есть книга Столярова (Сайт А.В. Столярова). |
RosAsm | Слабая | не очень интересные «онлайновые учебники». |
TASM | Хорошая | Компания Borland в свое время выпускала отличные справочные руководства, для TASM были написаны справочные руководства авторами-энтузиастами не связанными с фирмой Borland. Но Borland больше не поддерживает TASM, поэтому большая часть документации, предназначенная для TASM, не печатается и ее становится всё труднее и труднее найти. |
Учебники и учебные материалы
Комментарии | |
---|---|
FASM | Несколько учебников, в которых описывается программирование на FASM:
|
Gas | Учебник с использованием синтаксиса AT&TУчебник Ассемблер в Linux для программистов C |
HLA | 32-разрядная версия «The Art of Assembly Language Programming» (существует и в электронной, и в печатной форме), программирование под Windows или Linux |
MASM | большое количество книг по обучению программированию под DOS. Не очень много книг о программировании под Win32/64 Пирогов, Юров, Зубков, Фленов |
NASM | много книг, посвященных программированию в DOS, Linux, Windows. В книге Джеффа Дунтемана «Assembly Language Step-by-Step: Programming with Linux» используется NASM для Linux и DOS. Учебник Пола Картера использует NASM (DOS, Linux). |
TASM | Как и для MASM, для TASM было написано большое количество книг на основе DOS. Но, так как Borland больше не поддерживает этот продукт, писать книги об использовании TASM перестали. Том Сван написал учебник, посвященный TASM, в котором было несколько глав о программировании под Windows. |
Оговорочки
Хочу сразу оговориться, что правильно говорить не «ассемблер» (assembler), а «язык ассемблера» (assembly language), потому как ассемблер – это транслятор кода на языке ассемблера (т.е. по сути, программа MASM, TASM, fasm, NASM, UASM, GAS и пр., которая компилирует исходный текст на языке ассемблера в объектный или исполняемый файл). Тем не менее, из соображения краткости многие, говоря «ассемблер» (асм, asm), подразумевают именно «язык ассемблера».
Синтаксис директив, стандартных макросов и пр. структурных элементов различных диалектов (к примеру, MASM, fasm, NASM, GAS), могут отличаться довольно существенно. Мнемоники (имена) инструкций (команд) и регистров, а также синтаксис их написания для одного и того же процессора примерно одинаковы почти во всех диалектах (заметным исключением среди популярных ассемблеров является разве что GAS (GNU Assembler) в режиме синтаксиса AT&T для x86, где к именам инструкций могут добавляться суффиксы, обозначающие размер обрабатываемых ими данных, что бывает довольно удобно, но там есть и другие нюансы, сбивающие с толку программиста, привыкшего к классическому ассемблеру, к примеру, иной порядок указания операндов, хотя всё это лечится специальной директивой переключения в режим классического синтаксиса Intel).
Поскольку ассемблер – самый низкоуровневый язык программирования, довольно проблематично написать код, который корректно компилировался бы для разных архитектур процессоров (например, x86 и ARM), для разных режимов одного и того же процессора (16-битный реальный режим, 32-битный защищённый режим, 64-битный long mode; а ещё код может быть написан как с использованием различных технологий вроде SSE, AVX, FMA, BMI и AES-NI, так и без них) и для разных операционных систем (Windows, Linux, MS-DOS). Хоть иногда и можно встретить «универсальный» код (например, отдельные библиотеки), скажем, для 32- и 64-битного кода ОС Windows (или даже для Windows и Linux), но это бывает нечасто. Ведь каждая строка кода на ассемблере (не считая управляющих директив, макросов и тому подобного) – это отдельная инструкция, которая пишется для конкретного процессора и ОС, и сделать кроссплатформенный вариант можно только с помощью макросов и условных директив препроцессора, получая в итоге порой весьма нетривиальные конструкции, сложные для понимания.
Подытожим…
Итак, приведу неполный перечень того, в каких случаях используется ассемблер.
-
Создание загрузчиков, прошивок устройств (комплектующих ПК, встраиваемых систем), элементов ядра ОС.
-
Низкоуровневая работа с железом, в т.ч. с процессором, памятью.
-
Внедрение кода в процессы (injection), как с вредоносной целью, так и с целью защиты или добавления функционала. Системный софт.
-
Блоки распаковки, защиты кода и прочего функционала (с целью изменения поведения программы, добавления новых функций, взлома лицензий), встраиваемые в исполняемые файлы (см. UPX, ASProtect и пр).
-
Оптимизация кода по скорости, в т.ч. векторизация (SSE, AVX, FMA), математические вычисления, обработка мультимедиа, копирование памяти.
-
Оптимизация кода по размеру, где нужно контролировать каждый байт. Например, в демосцене.
-
Вставки в языки высокого уровня, которые не позволяют выполнять необходимую задачу, либо позволяют делать это неоптимальным образом.
-
При создании компиляторов и трансляторов исходного кода с какого-либо языка на язык ассемблера (например, многие компиляторы C/C++ позволяют выполнять такую трансляцию). При создании отладчиков, дизассемблеров.
-
Собственно, отладка, дизассемблирование, исследование программ (reverse engineering).
-
Создание файлов данных с помощью макросов и директив генерации данных.
-
Вы не поверите, но ассемблер можно использовать и для написания обычного прикладного ПО (консольного или с графическим интерфейсом – GUI), игр, драйверов и библиотек 🙂
6.5.4 elf-расширение директивы COMMON
ELF позволяет задавать требования к выравниванию общих переменных. Это делается
путем помещения числа (которое должно быть степенью двойки) после имени и размера
общей переменной и отделения этого числа (как обычно) двоеточием. Например,
массив двойных слов, который должен быть выровнен по двойным словам:
common dwordarray 128:4
Эта строка объявляет массив размером 128 байт и требует, чтобы он был выровнен
по 4-байтной границе.
6.6 aout: Объектные файлы
a.out Линукс
Формат aout генерирует объектные файлы a.out
в форме, используемой устаревшими Линукс системами. (Он отличается от других
объектных файлов a.out магическим числом в первых
четырех байтах файла. Также некоторые реализации a.out,
например NetBSD, поддерживают позиционно-независимый код, который реализация
Линукс не знает).
Формат a.out подразумевает расширение выходных
файлов по умолчанию .o.
Этот формат очень простой. Он не поддерживает специальных директив и символов,
не использует SEG или WRT
и в нем нет расширений никаких стандартных директив. Он поддерживает только
три стандартных секции с именами .text, .data и
.bss.
6.7 aoutb: Объектные файлы
a.out NetBSD/FreeBSD/OpenBSD
Формат aoutb генерирует объектные файлы a.out
в форме, используемой различными BSD-клонами UNIX: NetBSD, FreeBSD и OpenBSD.
Для большинства объектных файлов этот формат не отличается от aout
за исключением магического числа в первых четырех байтах файла. Однако формат
поддерживает (как и формат elf) позиционно-независимый
код, поэтому вы можете использовать его для написания разделяемых библиотек
BSD.
Расширение объектных файлов формата aoutb по умолчанию
.o.
Формат не поддерживает специальных директив и символов и имеет только три стандартных
секции с именами .text, .data и .bss.
Несмотря на это, для обеспечения типов перемещений в позиционно-независимом
коде он поддерживает использование WRT так же,
как это делает elf. Более подробно это описано
в .
aoutb, как и elf
поддерживает также расширение директивы GLOBAL:
см. .
6.8 as86: Объектные файлы
as86 Линукс
16-битный ассемблер Линукс as86 имеет свой собственный
нестандартный формат объектных файлов. Хотя его компаньон компоновщик ld86
выдает что-то близкое к обычным бинарникам a.out,
объектный формат, используемый для взаимодействия между as86
и ld86, все же не является a.out.
NASM на всякий случай поддерживает данный формат как as86.
Расширение выходного файла по умолчанию для данного формата .o.
Формат as86 это очень простой объектный
формат (с точки зрения NASM). Он не поддерживает специальных директив и символов,
не использует SEG и WRT,
и в нем нет никаких расширений стандартных директив. Он поддерживает только
три стандартных секции с именами .text, .data и
.bss.
6.9 rdf: Перемещаемые динамические
объектные файлы
Выходной формат rdf создает объектные файлы RDOFF.
RDOFF это «доморощенный» формат объектных файлов, разработанный вместе
с NASM и отражающий в себе внутреннюю структуру ассемблера.
RDOFF не используется никакими широко известными операционными системами. Однако
тот, кто пишет собственную систему, возможно захочет использовать его в качестве
собственного объектного формата, так как разработан он прежде всего для упрощения
и содержит очень мало бюрократии в заголовках файлов.
Архив Unix NASM и архив DOS с исходниками имеют подкаталог rdoff,
содержащий набор RDOFF-утилит: RDF-компоновщик, менеджер статических библиотек,
утилита, делающая дамп RDF-файла, и программа, загружающая и выполняющая RDF-исполнимый
файл под Линукс.
Формат rdf поддерживает только стандартные секции
с именами .text, .data и .bss.
Простейшая программа
Для следующего шага вам потребуется текстовый редактор, пригодный для работы
с программным кодом. Заметим, что Microsoft Word или встроенный в Windows
редактор WordPad являются текстовыми процессорами и для работы с программным
кодом непригодны. Редактор Notepad (Блокнот) подходит для работы с текстовыми
файлами (plain text), но неудобен в качестве программистского
редактора — в нем отсутствует подсветка синтаксиса и другие стандартные
для таких редакторов функции.
Вы можете воспользоваться вашим любимым текстовым редактором или, если вы
затрудняетесь с выбором, скачать простой программистский текстовый редактор
Notepad2.
Примечание: Если вы решили скачать Notepad2, при первом запуске
установите ширину табуляции (Tabulator width) в значение 8 при помощи
меню Settings > Tab Settings.
Создайте в вашем рабочем каталоге файл следующего содержания:
Примечание: В Notepad2 при сохранении введите имя файла , и
подсветка синтаксиса включится автоматически.
Эта программа выводит пять раз строчку “Hello World” на экран. Для вывода
текста используется макрос , который определен в файле
.