Что такое Ассемблер и для чего нужен
Изучаете как программировать на удобных высокоуровневых языках, но ничего не слышали об Assembler? Вашему вниманию занимательная статья о том, как всё начиналось.
Ассемблер — общее название части языков программирования низкого уровня. Это наиболее близкий для машины язык, который может написать человек. Кому может сегодня быть нужен язык, созданный в середине 20го века, и почему в вакансиях до сих пор упоминают знание Ассемблера?
Что такое Ассемблер
Давайте для начала разберемся с уровнями языка. В программировании их всего два: низкоуровневые и высокоуровневые.
Высокоуровневые языки просты для человеческого понимания: такие же простые, как английский, русский или разговорный язык любой страны. На таких языках легко писать программы и приложения. Они созданы для решения конкретных проблем и задач. Среди языков программирования к таковым относятся С, С++, Pascal, Python, Basic.
Говоря о низкоуровневых языках, их можно поделить на две основные категории:
-
Машинный код
К сожалению, компьютер воспринимает только такой язык. Максимально неудобный для нас, так как состоит только из 0 и 1. Условно говоря, «есть ток» и «нет тока». Последовательность цифр становится сигналом для запуска процессов в машине.
Они имеют следующий вид:
0100011101011111000101100
Программы, написанные подобным языком, машина выполняет очень быстро. Примерно так, как вы легко понимаете родную речь (значительно легче, чем любой иностранный язык, пусть и хорошо выученный).
В случае машины все инструкции направляются напрямую в центральный процессор, не нуждаясь в предварительной обработке и переводе.
Казалось бы, почему не писать на машинном коде все программы?
На это есть четыре серьезных причины:
-
Отсутствие универсальности. Программа подойдет не для всех машин – устройство у всех разное, программа может работать на определенной машине и не подойти для другой
-
Сложность. Программист обязан знать аппаратную часть машины, для которой пишет программу
-
Риск ошибки. Учитывая однообразность языка, включающего всего два символа, вероятность ошибиться огромна
-
По этой же причине практически невозможно редактировать готовый код
Как видите, работать с машинным языком в его исходном виде не представляется возможным. Поэтому программисты придумали более комфортный язык Ассемблера.
-
Языки Ассемблера
Фактически это примитивный переводчик с высокоуровневого языка, понятного человеку, на простой двоичный машинный код.
Код на ассемблере пишет все еще человек, но тот максимально близок к принципу работы машины. В целом ассемблер – это не один язык, а группа языков с общим синтаксисом и принципами, но ввиду схожести их решили назвать общим понятием «Ассемблер».
Преимущества Ассемблера:
-
Легко найти ошибку и исправить ее
-
Легко редактировать код
-
В целом язык легче понимать и использовать, ведь коды и числа тут заменены специальными короткими словами — мнемониками. Например, перемещение информации обозначается мнемоником MOV, добавление Add
Впрочем, есть и недостатки, в основном пришедшие из машинного кода:
-
Сохраняется зависимость от машины. Программы все еще работают только для конкретной марки и модели ПК
-
Программист должен знать аппаратное обеспечение машины, для которой пишет код
Резюмируя сказанное:
Ассемблер — это промежуточный язык-переводчик между высокоуровневыми языками программирования, удобными для людей, и двоичным кодом, удобным для машин. Это все еще сложный для понимания и работы язык, лишь на одну ступень проще машинного кода — но благодаря мнемоникам он уже доступен для редактирования. Позволяет без серьезных усилий переносить программу с машины с одной системой команд на другую.
Есть также дизассемблер — программа, переводящая с машинного языка на понятный человеку ассемблер.
О процессорах и языке
Сейчас попробуем объяснить принципы работы ассемблера. Для этого нужно понимать, как именно работает ЦП, и как воспринимает поступающие команды.
Процессор это в первую очередь электронное устройство, воспринимающее только уровень напряжения: высокий либо низкий. Уровни напряжения кодируются условно как 0 и 1, поэтому команды для ЦП выглядят как непрерывная последовательность нулей и единиц.
Это единственный язык, который может понять ЦП, слова и цифры ему недоступны. Всю поступающую информацию нужно переводить в формат 0-1.
На основе двоичного языка создается машинный код. Это перечень инструкций, каждая из которых содержит одно простое действие: числовую арифметику, логическую операцию, ввод-вывод данных и другие.
Например, так выглядит команда сложения двух чисел для ЦП Intel 8088:
0000001111000011В
Практически невозможно программировать на голом машинном языке: вам придется иметь дело с множеством нулей и единиц. Вы легко можете совершить ошибку.
Поэтому от идеи писать в двоичном коде отказались еще в 50х годах, а в 70х начали активно использовать возможности Ассемблера.
В нем коды операции обозначались сокращениями от английских слов (обычно 2-3 буквы в сокращении).
Пример: чтобы переместить число 7 в ячейку AV, использовалась команда MOV AV, 7.
История создания
Еще в 50х годах 20го века Кэтлин Бут придумала язык Ассемблер. Будучи инженером и ученым, она стала новатором с области информатики, прославив Канаду и Британию, откуда была родом.
Ассемблер применялся тогда на огромных ЭВМ, работавших на электронных лампах. Память у таких компьютеров была ограничена, потому чтобы ввести команду, приходилось переключать рубильники и кнопки. Даже простые вычисления на таких аппаратах занимали много времени и сил.
Ситуация упростилась, когда память компьютеров выросла достаточно, чтобы хранить в ней программы. Тогда и потребовался Ассемблер для перевода написанных человеком программ в машинный код. От этого пошло название программы – Assemble (англ. «собирать»), программа-сборщик.
Изобретение не сразу оценили по достоинству, и Ассемблер начали активно использовать только через 20 лет в появившихся тогда калькуляторах с памятью. И только потом язык стали применять для программирования ПК. Тогда оказалось, что программы, написанные на ассемблере весят существенно меньше их вариантов в машинном коде – что для ограниченных резервов ЭВМ было критически важно.
Как устроен
Чтобы понять, как именно функционирует Ассемблер, давайте разберемся в устройстве компьютерного процессора и том, как он обрабатывает данные.
Мы уже знаем, что процессор – это мозг ЭВМ, ответственный за выполнение операций. В процессе работы промежуточные данные хранят в регистрах в процессоре компьютера, так называемых ячейках памяти.
Они есть четырех видов:
-
Общего назначения (восемь штук, по четыре байта любых данных в каждом)
-
Указатели команд (хранят адреса команд)
-
Сегментные (только для оперативной памяти)
-
Регистр флагов (помечают процессорное свойство, которым обозначают код)
Итак, ассемблер работает исключительно с процессорными командами, а также переменными и различными регистрами. Они не затрагивают операционную систему или файлы, а работают только с самым нижним уровнем, доступным для человека. Такой способ позволяет напрямую обращаться к регистрам и любому устройству вне ПК, взаимодействуя через адаптер.
Команды для Ассемблера имеют следующий вид:
[<метка>:] <команда> [<операнд>] [;<комментарии>]
-
Меткой именуется определенная часть кода. Так можно отметить место, с которого начнем дальнейшую работу, либо отметить нужный участок памяти, к которому будем обращаться.
-
Команда является словом или обозначением (add, sub), которое будет передано в процессор в виде строки машинного кода. Через команды программисту проще понимать код и работать с ним.
-
Операнда – действие, которое нужно выполнить при получении команды. Т.е. из каких ячеек брать информацию, куда помещать результат. Все манипуляции с памятью определяются операндами.
-
Комментарии — тут все понятно, это уточнение по поводу участка кода, не влияет на алгоритм и нужно для работы программиста.
Теперь разберем на примере, как именно процессор работает с операндами, и какие операции выполняет.
Коды операций, как мы говорили ранее, обозначаются с помощью мнемоников. Например:
-
ADD — сложение
-
SUB — вычитание
-
MUL — умножение
У ячеек памяти и регистров тоже есть символические имена:
EBX, AH, AX, EAX – регистры
Meml — ячейка памяти
Разберем на примерах. Вам нужно вычесть числа из регистров АХ и ВХ. Команда выглядит так:
SUB AX, BX
А это команда сложения чисел из регистров
ADD AX, BX
В Ассемблере есть также директивы, они нужны для управления программой-ассемблером (она же компилятор).
Примеры таких команд:
-
Include — открыть файл и начать работу
-
Exit — прекратить работу
-
Def — определить регистр, дав ему имя
Будет заблуждением считать Ассемблер обычным переводчиком на машинный язык, представленным рядом команд и инструкций. Это полноценный язык программирования, и, хотя он значительно сложнее языков высокого уровня, он позволяет организовывать переходы, циклы, функции и другие необходимые вещи.
При этом для языков Ассемблера не предусмотрен единый стандарт. В целом можно выделить два синтаксиса: Intel и AT&T, но они равноценны по качеству и отличаются только функционалом: Intel используют в Microsoft, а AT&T в Linux.
При этом команды в этих синтаксисах выглядят по-разному:
-
MOV EAX, EBX для Intel
-
Movl %eax, %ebx для AT&T
Управление файлами в Ассемблер предполагает три стандартных файловых потока:
-
Stdin — ввод
-
sdout — вывод
-
stderr — ошибка
Дескриптор файла – это целое число в 16бит, его присваивают файлу, чтобы оно служило его идентификатором. Далее дескриптор используется для доступа к новому, либо уже существующему файлу.
Обычно это выглядит следующим образом:
-
Stdin — 0
-
Stdout — 1
-
Stderr — 2
Указатель файла показывает его место расположения для дальнейших операций (запись, чтение). Когда файл открыт, его файловый указатель имеет значение 0, далее задается смещение в байтах с точкой отсчета в начале файла.
Системные вызовы требуют следующих шагов обработки:
-
Системный вызов помещаете в регистр ЕАХ
-
Сохраняете аргументы системного вызова в регистрах В, С, D
-
Вызываете прерывание 80h
-
Получаете результат в регистре EAX.
Чтобы создать файл, делаете следующее:
-
Системный вызов sys_creat() помещаете в регистр EAX под номером 8
-
Имя размещаете в регистре EBX
-
Права доступа размещаете в ECX
Если вы все сделали корректно, файловый дескриптор вернется в регистр EAX. В случае ошибки код ошибки будет находиться там же.
Для чего нужен
Вы можете применять Ассемблер в следующих сферах:
-
разработке драйверов
-
программировании процессоров
-
организации микроконтроллеров
-
разработке частей ОС
-
создании антивирусов и/или вирусов
Обычно Ассемблер применяют там, где нужна большая скорость обработки данных, и где возможностей С++ объективно не хватает. Но так как сам язык в разработке неудобен, большие программы на нем не пишут, скорее создают части программ и встраивают в общий код.
Есть области, в которых не может справиться ни один язык кроме Ассемблера:
-
Любые компьютеры, у которых ограничена память
В первую очередь это микроконтроллеры в сигнализациях, датчиках, даже в бытовой технике на вашей кухне. Пульты управления всех видов, модемы и масса других устройств функционируют благодаря микроконтроллерам. Их используют даже в навигационных системах современных спутников и в робототехнике.
Для таких микросистем используется именно Ассемблер, так как каждая его команда преобразуется строго в определенную команду двоичного кода. Время выполнения команды также заранее известно, а объем занимаемой ею памяти фиксированный.
-
Драйверы устройств (ядро и процессы загрузки)
То есть то, с чего стартует ваш компьютер, приставка, мультимедийный центр. Кстати, некоторые любительские ОС вроде MenuetOS и KolibriOS целиком написаны на Ассемблере.
-
Обратная разработка программ
Она ж реверс-инжиниринг, процесс разбора программы для понимания принципов ее работы. Это бывает нужно, если нет исходного кода, и его нужно понять по работе программы.
Такой разбор нужен компаниям-производителям антивирусов, создателям ОС и драйверов, ну и конечно просто любопытным программистам.
Конечно, бывает и обратная ситуация, когда за реверс-инжиниринг садятся взломщики программ в поисках уязвимостей, для создания вирусов или генерации нелегальных ключей.
Почему один Ассемблер не подходит для всех процессоров?
Суть в том, что каждый процессор имеет свою особую архитектуру — набор характеристик, определяющий принципы работы и исходную конструкцию. Он влияет на регистры, набор команд и вид адресации памяти.
Процессоры из одного семейства имеют одинаковую архитектуру, и к ним может применяться один и тот же Ассемблер. Но если архитектура отличается, то программа, созданная на Ассемблере, не будет работать в другом процессоре (в отличии от программ, написанных на высокоуровневых языках, таких как Python и C++). Поэтому Ассемблер называют машинно-ориентированным.
Востребованность сейчас
Ассемблер как первый язык для изучения – не самый удачный выбор. Сегодня этот язык используется сравнительно нечасто и в очень ограниченных процессах. Он громоздкий и сложный, писать не нам большие программы затруднительно – а при наличии таких языков как С++, еще и нерационально.
Также, изучая Ассемблер, вы не получите представления о других языках программирования. Большинство действующих языков является высокоуровневыми, в то время как ассемблер относится к низкоуровневым языкам и работает по совершенно другим принципам. Так что, когда после Ассемблера решите выучить Python, вам фактически придется разбирать язык и его принципы с нуля, без какой-либо базы.
Так стоит ли изучать Ассемблер
Как ни странно, да.
Это машинно-ориентированный язык, и изучая его, вы получите много полезной информации о принципах работы компьютера. Эти знания даст вам преимущество в дальнейшей работе с высокоуровневыми языками, особенно Си.
В каком порядке учить языки?
Лучше начинать с более популярного высокоуровневого языка, а потом переходить с Ассемблеру. Высокоуровневые языки проще в понимании, так у вас не произойдет потеря интереса к учебе. Ведь низкоуровневый язык вы можете забросить еще до того, как напишете свою первую программу и получите результат.
Востребованы ли сейчас специалисты в Ассемблере?
Если вы знаете только этот язык — то, увы, работу вы не найдете. Как мы уже сказали, язык слишком специфичен. Но если вы владеете C, C++ или Python, и при этом знаете также Ассемблер, то ваши шансы найти хорошую работу повышаются.
Вы можете претендовать на должность специалиста по безопасности ПК, по разработке драйверов, можете стать системным программистом, работать с микропроцессорами и микроконтроллерами, заниматься реверс-инженерией.
Все эти профессии востребованы и хорошо оплачиваются: от 80 до 300 тысяч рублей в зависимости от вашего опыта. Преимущество еще и в том, что многие вакансии предполагают работу онлайн, с которой вы не будете привязаны к одному городу или даже стране, получая возможность работать из любой точки мира.