Знакомимся с ассемблерами: от популярных до малоизвестных

от автора

Введение

Привет, Хабр! Сегодня я хочу поделиться своими наблюдениями и опытом по работе с различными ассемблерами. Я сам пишу на языке C и относительно редко касался темы ассемблера. Но недавно решил восполнить этот пробел в знаниях и посмотреть на различные ассемблеры. В данной статье мы не будем рассматривать ARM, AVR и другие микроконтроллерные архитектуры, а сосредоточимся исключительно на компьютерных ассемблерах. Давайте не будем судить строго, ведь это скорее исследовательский опыт, чем глубокое погружение.

Введение в ассемблеры

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

Классика жанра: NASM и GAS

NASM (Netwide Assembler) — это свободный ассемблер для архитектуры Intel x86, известный своей простотой и мощью. Он поддерживает 16-, 32- и 64-разрядные программы и предлагает богатый набор макросов. NASM часто используется для написания высокопроизводительных участков кода, драйверов устройств и операционных систем.

  • Автор: Simon Tatham и Julian Hall.

  • Репозиторий: NASM GitHub

  • Инструкции: NASM поддерживает порядка 700+ инструкций, включая различные расширения и специфические команды.

GAS (GNU Assembler) — ассемблер проекта GNU, используемый компилятором GCC. Это кроссплатформенный инструмент, поддерживающий множество архитектур. GAS отличается мощными возможностями по работе с макросами и директивами, что делает его незаменимым инструментом для разработки системного программного обеспечения.

  • Автор: Проект GNU.

  • Репозиторий: GAS в составе GNU Binutils

  • Инструкции: Поддерживает более 1000 инструкций, так как покрывает множество процессорных архитектур

ReLax и AsmX

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

AsmX — это язык программирования на основе NodeJS. AsmX G2 является вторым поколением этой платформы. AsmX пытается предложить ассемблер для разработчиков, знакомых с веб‑технологиями.

Relax и AsmX: Первые впечатления

Relax, несмотря на заявления о компиляции, вызвал у меня больше вопросов, чем ответов. Отсутствует понятная документация, а сам процесс компиляции неясен. Хоть автор и позиционирует Relax как компилятор, по факту его реализация больше напоминает байт‑машину. Я не нашел информации о конкретных инструкциях компиляции, что показалось мне странным, ведь продукт должен быть готов к использованию. На страницах GitHub‑репозиториев RVM и IRasm присутствует лицензия, но документации по использованию языка я не нашел.

AsmX, в отличие от Relax, обладает более структурированным подходом. На GitHub доступна документация, позволяющая разобраться с установкой и использованием. AsmX Foundation реализовали довольно необычную систему, которая больше похожа на JIT‑компилятор, но не является классической виртуальной машиной. Впервые я сталкиваюсь с подобным подходом, и это можно считать своего рода ноу‑хау. Автор в README‑файлах репозиториев подробно описывает обновления и новые возможности языка.

Оценка Relax и AsmX

Relax:

  • Плюсы:

    • Автор пытается создать свой язык программирования на C++.

    • Написан на C++.

  • Минусы:

    • Отсутствие технической документации.

    • Сложно понять, что можно писать на Relax.

AsmX:

  • Плюсы:

    • Доступна техническая документация.

    • Установку и использование легко понять благодаря мануалам.

  • Минусы:

    • Написан на NodeJS.

Таблицы сравнения

Сравнение синтаксиса комментариев в различных ассемблерах

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

GAS

NASM

ReLax

AsmX

AsmX G2

#

#

;

Как видно из таблицы, большинство ассемблеров используют символ # или ; для обозначения комментариев. Однако AsmX G2 использует два символа ;; для комментариев.

Сравнение наличия и определения точки входа

Точка входа — это место в программе, с которого начинается её выполнение. В различных ассемблерах подход к определению точки входа может различаться. Рассмотрим, как это реализовано в каждом из ассемблеров.

GAS

Нужно определять вручную (например, main)

NASM

Нужно определять вручную (например, _start)

ReLax

MainClass.Main

AsmX

Не имеет явной точки входа

AsmX G2

main

В GAS и NASM разработчику необходимо явно указать точку входа, что дает гибкость, но требует дополнительной настройки. ReLax использует объектно‑ориентированный подход, где точка входа — это метод MainClass.Main. AsmX, в свою очередь, не имеет явно определенной точки входа, что может быть необычно для традиционных ассемблеров. AsmX G2 возвращается к более традиционному подходу, используя main как точку входа, что может облегчить переход для разработчиков, привыкших к C‑подобным языкам.

Наличие инструкций SIMD в разных ассемблерах

Теперь давайте посмотрим, как обстоят дела с поддержкой SIMD‑инструкций (Single Instruction, Multiple Data) в разных ассемблерах. Эти инструкции играют важную роль в высокопроизводительных вычислениях, например, в мультимедийных приложениях или обработке больших массивов данных. В таблице ниже представлены поддерживаемые наборы SIMD‑инструкций, такие как MMX, AVX, SSE и другие.

Assembler

MMX

AVX

SSE

AVX2

SSE2

SSE3

SSE4

AVX-512

SSE4.1

SSE4.2

GAS

+

+

+

+

+

+

+

+

+

+

NASM

+

+

+

+

+

+

+

+

ReLax

AsmX

AsmX G2

+

+

  • + означает, что ассемблер поддерживает соответствующий набор инструкций SIMD.

  • - означает, что ассемблер не поддерживает соответствующий набор инструкций SIMD.

Анализ поддержки SIMD-инструкций

  • GAS и NASM показывают полную или почти полную поддержку современных SIMD инструкций, что делает их предпочтительными для разработки высокопроизводительных приложений. Однако, NASM не поддерживает SSE4.1 и SSE4.2, что может быть ограничением для некоторых специфических задач.

  • ReLax и AsmX не поддерживают никакие SIMD инструкции, что может ограничить их применение в задачах, требующих высокой производительности.

  • AsmX G2 поддерживает базовые MMX и SSE, что может быть достаточно для некоторых задач, но отсутствие поддержки более новых инструкций, таких как AVX или AVX-512, может ограничить его использование в современных вычислениях.

Итоги

Если вам нужны мощные SIMD‑инструкции для работы с мультимедийными данными или высокопроизводительными вычислениями, GAS и NASM — это ваши лучшие друзья. GAS лидирует по поддержке SIMD, включая самые современные наборы инструкций, такие как AVX-512. NASM также хорош, но с небольшими ограничениями. ReLax и AsmX не подходят для программ, требующих инструкций SIMD. AsmX G2 может быть использован для программ, требующих только MMX и SSE.

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

Пример кода для вычисления квадрата числа

square(x) = x^2

Для сравнения я написал простую программу на разных ассемблерах: вычисление квадрата числа. Это не «Hello, World!» (он слишком прост), но и не факториал (он слишком сложен для первого знакомства с ассемблером).

Скрытый текст

GAS:

.section .data number: .int 500 result: .int 0  .section .text .global main  main:     movl number, %eax   # Загрузить число в регистр eax     imull %eax, %eax    # Вычислить квадрат числа     movl %eax, result   # Сохранить результат в переменную result      # Завершение программы     movl $1, %eax       # Системный вызов для выхода     xorl %ebx, %ebx     # Код возврата 0     int $0x80           # Вызов ядра 

NASM:

section .data number dd 500 result dd 0  section .text global _start  _start:     mov eax, [number]   ; Загрузить число в регистр eax     imul eax, eax       ; Вычислить квадрат числа     mov [result], eax   ; Сохранить результат в переменную result      ; Завершение программы     mov eax, 1          ; Системный вызов для выхода     xor ebx, ebx        ; Код возврата 0     int 0x80            ; Вызов ядра 

AsmX:

@mul 500 500          # Вычислить квадрат числа

AsmX G2:

@function main {    ;; Точка входа C/C++     @mul 500 500    ;; Вычислить квадрат числа }

Бенчмарк: Вычисление квадрата числа

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

Assembler

memory

min

avg

max

GAS

1024kb

0.38s

0.4s

0.587s

NASM

256kb

0.36s

0.38s

0.505s

AsmX

?????

0.17s

0.21s

0.262s

AsmX G2

?????

0.15s

0.19s

0.259s

К сожалению, провести бенчмарки для Relax оказалось невозможным из‑за отсутствия возможности запуска.

Примечание: Бенчмарки носят ориентировочный характер и могут варьироваться в зависимости от аппаратного обеспечения и конфигурации системы.

Итоги

  • GAS и NASM — это классические ассемблеры, прекрасно подходящие для работы с языками программирования C/C++ и другими.

  • AsmX — интересный проект, который может быть полезен для бэкенд и фронтенд разработчиков, благодаря использованию NodeJS.

  • NASM показал себя более экономичным в плане потребления памяти по сравнению с GAS.

  • AsmX G2 имеет синтаксис, напоминающий смесь C++ и ассемблера.

  • Бенчмарки удивили нас, демонстрируя высокую производительность AsmX и AsmX G2. Однако, из‑за отсутствия информации о памяти для этих ассемблеров, сравнение не может быть полным.

Спасибо за внимание! Надеюсь, статья была полезной и интересной. Пишите в комментариях о вашем опыте работы с ассемблерами и какие ещё малоизвестные инструменты стоит рассмотреть.


ссылка на оригинал статьи https://habr.com/ru/articles/843172/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *