Введение

Язык программирования низкого уровня

В компьютерном программировании, язык ассемблера (или язык ассемблирования, часто называемый просто ассемблером и обычно сокращаемый как ASM или asm) – это любой язык программирования низкого уровня с очень тесным соответствием между инструкциями языка и инструкциями машинного кода архитектуры. Код на языке ассемблера преобразуется в исполняемый машинный код с помощью специальной программы, называемой ассемблером. Термин "ассемблер" обычно приписывается Уилксу, Уилеру и Гиллу в их книге 1951 года "Подготовка программ для электронной цифровой вычислительной машины", и он специфичен для конкретной компьютерной архитектуры. Иногда для одной архитектуры существует несколько ассемблеров, а иногда ассемблер предназначен для конкретной операционной системы или нескольких операционных систем. Большинство языков ассемблера не предоставляют специального синтаксиса для системных вызовов операционной системы, и большинство языков ассемблера могут использоваться универсально с любой операционной системой, поскольку язык обеспечивает доступ ко всем реальным возможностям процессора, на которых в конечном итоге основаны все механизмы системных вызовов. В отличие от языков ассемблера, большинство языков программирования высокого уровня обычно переносимы между различными архитектурами, но требуют интерпретации или компиляции – гораздо более сложных задач, чем ассемблирование. В первые десятилетия развития вычислительной техники было обычным явлением, когда как системное, так и прикладное программирование выполнялось полностью на языке ассемблера. Хотя в некоторых случаях он по-прежнему незаменим, в настоящее время большая часть программирования выполняется на языках более высокого уровня, которые интерпретируются или компилируются. В книге "No Silver Bullet" Фред Брукс подвел итоги последствий отказа от программирования на языке ассемблера: "Несомненно, самым мощным фактором повышения производительности, надежности и простоты программного обеспечения стало постепенное использование языков высокого уровня для программирования. Большинство наблюдателей считают, что это развитие привело к увеличению производительности как минимум в пять раз, а также к повышению надежности, простоты и понятности".

Синтаксис языка ассемблера

Язык ассемблера использует мнемонические обозначения для представления, например, каждой низкоуровневой машинной инструкции или опкода, каждой директивы, как правило, также каждого архитектурного регистра, флага и т.п. Некоторые мнемонические обозначения могут быть встроенными, а некоторые – определяемыми пользователем. Многие операции требуют один или несколько операндов для формирования полной инструкции. Большинство ассемблеров допускают использование именованных констант, регистров и меток для программ и ячеек памяти, а также могут вычислять выражения для операндов. Таким образом, программисты освобождаются от утомительных повторяющихся вычислений, а программы на языке ассемблера гораздо более читабельны, чем машинный код. В зависимости от архитектуры, эти элементы могут также комбинироваться для конкретных инструкций или режимов адресации, используя смещения или другие данные, а также фиксированные адреса. Многие ассемблеры предлагают дополнительные механизмы для упрощения разработки программ, контроля процесса ассемблирования и помощи в отладке. Некоторые из них имеют столбцовую структуру, с определенными полями в заданных столбцах; это было широко распространено для машин, использующих перфокарты в 1950-х и начале 1960-х годов. Некоторые ассемблеры используют синтаксис свободной формы, где поля разделяются разделителями, например, знаками препинания или пробелами. Некоторые ассемблеры являются гибридными, например, с метками в определенном столбце и другими полями, разделенными разделителями; это стало более распространенным, чем столбцовый синтаксис, в 1960-х годах.

Терминология

Макроассемблер – это ассемблер, включающий в себя средства макроинструкций, позволяющие представить (параметризованный) текст языка ассемблера именем, которое затем можно использовать для вставки развернутого текста в другой код. Открытый код относится к любому входному коду ассемблера вне определения макроса. Кросс-ассемблер (см. также кросс-компилятор) – это ассемблер, работающий на компьютере или операционной системе (хост-системе) отличного типа от системы, для которой предназначен полученный код (целевой системы). Кросс-ассемблирование облегчает разработку программ для систем, не имеющих ресурсов для поддержки разработки программного обеспечения, таких как встраиваемые системы или микроконтроллеры. В этом случае полученный объектный код необходимо передать в целевую систему через память только для чтения (ROM, EPROM и т.д.), программатор (когда память только для чтения интегрирована в устройство, как в микроконтроллерах), или канал передачи данных, использующий точную побитовую копию объектного кода или текстовое представление этого кода (например, Intel HEX или Motorola S-record). Ассемблер высокого уровня – это программа, предоставляющая языковые абстракции, чаще ассоциируемые с языками высокого уровня, такие как продвинутые структуры управления (IF/THEN/ELSE, DO CASE и т.д.) и высокоуровневые абстрактные типы данных, включая структуры/записи, объединения, классы и множества. Микроассемблер – это программа, помогающая подготовить микропрограмму, называемую прошивкой, для управления низкоуровневой работой компьютера. Метаассемблер – это "программа, принимающая синтаксическое и семантическое описание языка ассемблера и генерирующая ассемблер для этого языка". Sperry Univac также предоставляла метаассемблеры для серии UNIVAC 1100/2200. Инлайн-ассемблер (или встроенный ассемблер) – это код ассемблера, содержащийся в программе на языке высокого уровня. Он чаще всего используется в системных программах, которым требуется прямой доступ к аппаратному обеспечению.

Сборщик

Ассемблер создает объектный код, преобразуя комбинации мнемоник и синтаксиса операций и режимов адресации в их числовые эквиваленты. Это представление обычно включает в себя код операции ("опкод"), а также другие управляющие биты и данные. Ассемблер также вычисляет константные выражения и разрешает символические имена для ячеек памяти и других сущностей. Ассемблеры появились в 1950-х годах, представляя собой первый шаг выше машинного языка и предшествуя языкам программирования высокого уровня, таким как Fortran, Algol, COBOL и Lisp. Существовали также различные классы трансляторов и полуавтоматических генераторов кода, обладающих свойствами, схожими как с языками ассемблера, так и с языками высокого уровня, причем Speedcode является, пожалуй, одним из наиболее известных примеров. Для конкретного процессора или архитектуры набора команд может существовать несколько ассемблеров с различным синтаксисом. Например, инструкция для добавления данных из памяти к регистру в процессоре семейства x86 может выглядеть как `add eax, [ebx]` в оригинальном синтаксисе Intel, в то время как в синтаксисе AT&T, используемом GNU Assembler, она будет записана как `addl (%ebx), %eax`. Несмотря на различные варианты записи, разные синтаксические формы обычно генерируют один и тот же числовой машинный код. Один и тот же ассемблер может также иметь различные режимы для поддержки вариаций в синтаксических формах, а также их точных семантических интерпретаций (например, синтаксис FASM, синтаксис TASM, идеальный режим и т.д., в частности, при программировании на ассемблере x86).