Ассемблеры бывают разные: по синтаксису (
Intel или
AT&T), по архитектуре компьютера и/или процессора. И доступные API операционных систем тоже различаются. Также, в некоторых ассемблерах есть поддержка макросов (позволяют генерировать шаблонный код).
Могу рассказать только немного по фоннеймовской архитектуре (например x86_64), не знаю, как ассемблер выглядит на гарвардской.
Во-первых, надо иметь представление, что такое стек и регистры. Когда процесс запускается в оперативной системе, ему этой системой выделяется виртуальная память (как бы бесконечно растущая лента), где создаётся и системный стек, и туда же вроде копируется код программы.
Код программы обычно состоит из секций: команд, переменных, констант, импорта.
Секция команд выполняется сверху вниз, но неизвестно с какой строки. В зависимости от ассемблера и/или формата исполняемого файла, который зависит от ОС, в коде нужно как-то указать это место. Оно называется точкой входа. Например, в
FASM в формате PE оно обозначается сразу после формата ключевым словом entry, за которым идёт метка, с которой начнётся выполнение.
Секция команд состоит из:
- перемещений (mov) данных между ячейками памяти, регистрами, памятью и регистрами, регистрами и памятью, а также помещение литералов в эти места;
- помещение значений (из регистров, памяти и литералов) на вершину стека (push) или доставание значений обратно (pop);
- меток;
- прыжков, т.е. безусловных переходов на метку (jmp, аналог GOTO) или сравнений (cmp) и условных переходов (обозначаются похожими на jmp командами), которые выполняют или не выполняют переход, в зависимости от условий по значениям определённых регистров (это основа работы if);
- вызовов аппаратных прерываний (особенно актуально для программ, которые выполняются не в ОС, а на голом железе);
- вызовов импортированных функций командами invoke, cinvoke (это может быть вызов функции из стандартной библиотеки Си, WinAPI, других библиотек, эти команды задействуют стек);
- вызовов своих процедур командой call (почти как jmp, но место вызова и параметры помещаются на вершину стека);
- возвращение управления в процедуру, которая вызвала текущую процедуру, командой ret (использует стек).
Динамическое выделение памяти проще всего делать через стандартную библиотеку (malloc и т.п.), а в переменных держать указатели.
Самые быстрые ячейки - это регистры (часть процессора), а также стек, т.к. он обычно попадает в процессорный кэш.
В общем, чтобы писать на ассемблере, надо выбрать архитектуру, ассемблер и операционную систему (или отсутствие таковой), а затем изучить это всё по соответствующему учебнику. Только надо быть морально готовым, что скорее всего код будет гвоздями прибит к архитектуре и операционной системе, поэтому рекомендовать могу только для расширения кругозора. Практической пользы в этом мало.
Изменено. Чуть не забыл, есть сайт WASM.in
с большим количеством статей по теме и форумом. Сайт
очень старый, и многое в нём поломано (например, ссылки оглавления статей, форматирование кода в некоторых местах). Раньше он назывался WASM.RU. Некоторый контент можно найти на других сайтах по заголовкам, чтобы было проще читать. Можно начать знакомство с языком со статьи
Ассемблер в Linux для программистов C.
Изменено 2. Еще есть вполне живой
раздел форума на Исходниках. Вообще, удивительно, сайту 20 лет, и почти во всех разделах форума есть активность. Форум
Vingrad уже в 2001 попал в веб-архив, и там аналогичная ситуация.