Обновить
59.8

Assembler *

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

Сначала показывать
Порог рейтинга
Уровень сложности

AsmX G3: Записки из лаборатории. Что мы тестируем прямо сейчас

Время на прочтение4 мин
Охват и читатели635

Прежде чем технология изменит мир, она проходит через тысячи часов испытаний в лаборатории. Мы открываем двери нашего R&D отдела и показываем, над чем инженеры AsmX Foundation работают прямо сейчас. Улучшенная диагностика ошибок, новый синтаксис и первые шаги к полноценным вызовам библиотечных функций. Загляните в будущее компилятора.

Войти в лабораторию

I always come back: Анонс AsmX G3 — Новый этап в программировании

Время на прочтение5 мин
Охват и читатели2.1K

Привет, читатель! Ты видишь это лицо и надпись "I ALWAYS COME BACK"? Это не просто мем для хайпа — это моё обещание. И я его сдержал.

Я вернулся, чтобы анонсировать AsmX G3 — новое поколение моего проекта, которое вот-вот перевернёт твоё представление о низкоуровневом программировании. Это событие, частью которого я хочу тебя видеть.

🚀 Прыгнуть в будущее

Оптимизация языковой модели Mamba для выполнения на CPU

Уровень сложностиСложный
Время на прочтение4 мин
Охват и читатели2.1K

Как оптимизировать модель Mamba для выполнения на CPU? Ускоряем код в 20 раз по сравнению с PyTorch, нарушая в процессе все правила оптимизации.

Читать далее

Как я обнаружил древнюю пасхалку в Power Mac G3

Время на прочтение5 мин
Охват и читатели3.2K

Недавно залез в ROM оригинального Power Macintosh G3 и случайно обнаружил там пасхалку, о которой до этого ещё нигде не писали.

Началось с того, что одним воскресным утром я решил заглянуть в файл-шаблон ROM для Mac с помощью программы HEX Fiend Эрика Хармана. Меня интересовало, какие ресурсы хранятся в постоянной памяти Power Mac G3. Эта ROM использовалась в моделях Beige, Mini Tower и всех G3, выпускавшихся с 1997 по 1999 годы.

Пишу я эту статью в середине 2025, и мне не верится, что сегодня Power Mac G3 уже больше 27 лет. Невероятно!

Читать далее

FastCGo: как мы ускорили вызов C-кода в Go в 16,5 раза

Уровень сложностиСложный
Время на прочтение19 мин
Охват и читатели5.5K

В Deckhouse Prom++ мы переписали ядро хранения и обработки горячих данных на C++, при этом вся оркестрация и периферия остались в Prometheus на Go, что позволило сохранить полную совместимость с Prometheus. Для частых вызовов кода C++ мы использовали механизм CGo, однако первые тесты показали, что производительность CPU практически не улучшилась из-за его медлительности. В итоге мы переписали CGo, создав собственный механизм вызова.

В статье разберём, что такое CGo и почему он такой медленный, сделаем простейший собственный механизм CGo-вызова и доведём этот механизм до полноценного решения.

Читать далее

Ускоряем валидацию UTF-8 в 10 раз (>10 ГБ/с): реализация алгоритма Lemire-Keiser на Go с ARM NEON

Время на прочтение8 мин
Охват и читатели747

UTF-8 валидация — одна из базовых операций при работе с текстом, которая выполняется миллионы раз в секунду в современных приложениях. Стандартная реализация в Go, хоть и корректная, далека от оптимальной по производительности. В этой статье расскажу, как мне удалось ускорить валидацию UTF-8 в 10 раз, используя SIMD‑инструкции ARM NEON и алгоритм из статьи «Validating UTF-8 In Less Than One Instruction Per Byte» Джона Кейзера и Дэниела Лемира.

Читать далее

О векторном вычислении экспоненциальной функции

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели2.4K

Как вычислить экспоненциальную функцию быстро и с минимальной погрешностью? Пишем векторизованный код.

Читать далее

Цифровой фильтр без умножения

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели1.7K

Представлен цифровой фильтр без использования явной аппаратной или программной операции умножения, выполненный на основе двоичных сдвигов. Имеет дискретный ряд АЧХ, ФЧХ, при этом, эффективно реализуется на простейших контроллерах.

Читать далее

Об ошибках округления и способах борьбы с ними

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели3.6K

Почему при сложениии одинаковых чисел в разном порядке получаются разные результаты?
Как мининмизировать ошибки округления или избавиться от них совсем?

Читать далее

Не стоит пугаться машинного кода

Время на прочтение7 мин
Охват и читатели9.1K

Моим первым языком программирования был ActionScript. Написание кода для Macromedia Flash максимально далеко от голого железа, и эта специфика работы глубоко засела в моём сознании. В результате меня интересовали преимущественно высокоуровневые языки для веб-программирования. Низкоуровневые же казались непостижимыми. Со временем я постепенно из разных источников узнавал о них всё больше, но это моё убеждение оставалось прежним. Низкоуровневые языки пугают, и машинный код подтверждал это наглядно. Когда я обращался к Google с запросом «понятный машинный код», то результат выдачи чаще представлял нечто пугающее и отталкивающее, нежели полезное для обучения.

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

Машинный код вовсе не страшен. Если вы можете обеспечить, чтобы документ JSON соответствовал схеме JSON, то без проблем сможете писать машинный код.

Читать далее

QapDSL — декларативное описание AST и парсеров для C++

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели1K



QapDSL — декларативное описание AST и парсеров для C++


QapDSL — это специализированный язык (DSL), который позволяет описывать абстрактные синтаксические деревья (AST) и правила их разбора для языков программирования, прежде всего C++. Такая формализация помогает автоматизировать построение парсеров, генерацию кода, анализ исходников и даже рефакторинг.



Зачем нужен QapDSL?


  • Компактно и наглядно описывать структуру и грамматику языка.
  • Автоматически генерировать C++-структуры, парсеры, сериализаторы и визиторы.
  • Ускорять эксперименты с языками, создавая прототипы компиляторов и анализаторов.
  • Упрощать анализ и рефакторинг сложных языков, в т.ч. C++.


Пример QapDSL-описания


Рассмотрим, как описывается объявление класса C++ на QapDSL:


t_class{
  string keyword;
  t_sep sep0;
  string name;
  t_sep sep1;
  TAutoPtr<t_parents> parents;
  t_sep sep2;
  TAutoPtr<t_class_body> body;
  t_sep sep3;
  {
    M+=go_any_str_from_vec(keyword,split("struct,class,union",","));
    O+=go_auto(sep0);
    M+=go_str<t_name>(name);
    O+=go_auto(sep1);
    O+=go_auto(parents);
    O+=go_auto(sep2);
    O+=go_auto(body);
    O+=go_auto(sep3);
    M+=go_const(";");
  }
}

Читать дальше →

Векторы в RISC-V на практике: вычисление softmax

Уровень сложностиСредний
Время на прочтение13 мин
Охват и читатели1.1K

С 10 по 14 апреля 2025 года прошел первый онлайн RISC-V хакатон, организованный Ассоциацией RISC-V. Участникам на выбор давались 2 задачи. Одна задача от Codasip -доработать программу и кастомный процессор для вычисления LLM трансформера. Другая от Andes - улучшить вычисление функции softmax. Для демонстрации работы векторного расширения RISC-V задача с softmax мне показалась более подходящей.

Интересно было изучить, как в процессорах реализуется вычисление нелинейных функций, как например экспоненциальная функция, нужная для softmax.

Читать далее

Как ускорить сложение и вычитание при помощи 2^51

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели7.1K

Помните, как долго выполняется сложение на бумаге?

¹¹ ¹
6876
+ 3406
------
10282

Начиная с единиц, мы складываем 6 + 6 = 12, записываем 2 и переносим 1. Затем пошагово двигаемся влево, пока складываемые разряды не закончатся.

При реализации сложения больших чисел (например, от 264 и выше) обычно пишут код, похожий на этот алгоритм. Любопытно здесь то, что существует простой трюк, позволяющий существенно ускорить этот процесс на современных CPU.

Но сначала я задам вопрос: почему сложение столбиком мы начинаем с самого младшего разряда? Почему бы не начать слева?

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

Читать далее

Ближайшие события

Пишем на C самоизменяющуюся программу x86_64

Время на прочтение14 мин
Охват и читатели12K


«Зачем вообще писать программу, меняющую код в процессе выполнения? Это же ужасная идея!»


Да, всё так и есть. Но это и хороший опыт. Такое делают только тогда, когда хотят что-то исследовать, или из любопытства.


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


Предупреждение: в этом посте активно используется язык ассемблера x86_64, в котором я ни в коем случае не являюсь специалистом. Для написания статьи мне пришлось изучать приличный объём материалов, и, возможно (почти наверняка), в ней есть ошибки.
Читать дальше →

Любителям x86-64 assembler посвящается: DIY волокна в C++

Уровень сложностиСложный
Время на прочтение26 мин
Охват и читатели9.2K

Нас ждёт мозговыносящая смесь 64/32-битного ассемблера и старого-доброго C++. Мы сделаем собственную реализацию... Волокон (fibers) без вызова Win API и звонков в службу спасения.

Читать далее

Решение задачи с Route 256 на goalng

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели1.6K

В этой статье разбирается решение задачи «Гистограммы» с контеста Route 256 от Ozon с помощью SIMD.

Условие задачи

Гистограммой является массив, каждый элемент которого указывает высоту столбика на соответствующей позиции. Две гистограммы считаются совпадающими, если при совмещении одной гистограммы с другой гистограммой, повёрнутой на угол 180°, получается ровный прямоугольник без наложений и пропусков.

Читать далее

Низкоуровневое программирование под 8086 для любопытных, часть 2

Уровень сложностиСредний
Время на прочтение15 мин
Охват и читатели7.1K

В этой части нас ждёт погружение в один из способов организации мультипоточности на базе единственного ядра процессора. Мы научимся принудительно переключать выполнение между полностью зацикленными участками кода, ничего не "знающими" о каком-то другом коде, конкурирующем за процессорное внимание. По ходу повествования будут даны все необходимые пояснения и читателю не придётся обращаться к другим источникам, кроме первой части статьи.

Читать далее

Часть 3. Векторизация на Go: CGo, транзакции, компиляторы, поддержка, байтовые инструкции

Время на прочтение8 мин
Охват и читатели1.6K

В первой части статьи мы рассмотрели, как можно вручную ускорить Go-код с помощью векторизации и SIMD-инструкций, реализованных через Go-ассемблер. Написали простую, но показательно быструю реализацию sliceContains и увидели, что даже базовая векторизация может дать ускорение в 10–14 раз по сравнению со стандартной реализацией.

Во второй части статьи погрузились в практическое применение SIMD в Go-ассемблере, реализовали функцию SliceContainsV1 и изучили, как с помощью VADD, VDUP и других инструкций можно добиться 10–14-кратного ускорения простых задач.

Но возможности оптимизации Go-программ на этом не заканчиваются. В этой части мы пойдём дальше: рассмотрим другие техники низкоуровневой оптимизации — от использования C-кода и альтернативных компиляторов с поддержкой векторизации до работы с аппаратными транзакциями памяти на Intel. Поговорим о том, как внедрять ассемблер в продакшен-код, не боясь за его поддержку, и как обойти ограничения стандартного Go-компилятора.

Привет, Хабр! Меня зовут Игорь Панасюк, я работаю в Яндекс, преподаю в ИТМО, а также в свободное время выступаю на конференциях, делюсь опытом в соцсетях и помогаю развитию Go-сообщества, веду телеграм-канал и youtube-канал. Если вы уже знакомы с базовыми техниками векторизации, эта часть поможет глубже понять, как устроены продвинутые способы ускорения Go-кода и на что стоит обратить внимание при работе с архитектурно-зависимыми оптимизациями.

Читать далее

Часть 2. Векторизация и SIMD в Go: ускорение поиска и сравнения в массивах

Время на прочтение10 мин
Охват и читатели1.7K

Ускорить простые задачи, вроде поиска в массиве и сравнения слайсов, поможет мощь SIMD. Эти векторные инструкции, которые обрабатывают десятки байт данных за один такт процессора, отличная замена традиционным циклам. Во второй части статьи мы погружаемся глубже в практическое применение SIMD в Go-ассемблере, реализуем функцию SliceContainsV1 и изучим, как с помощью VADD, VDUP и других инструкций можно добиться 10–14-кратного ускорения простых задач.

Из этой статьи вы узнаете:

Как устроено сравнение массивов с помощью SIMD-инструкций;

Почему векторизация быстрее бинарного поиска;

Как правильно работать с регистрами, фреймами и указателями в Go-ассемблере;

Что нужно учесть при переносимости и поддержке низкоуровневого кода;

Когда ассемблер оправдан и безопасен в реальных проектах на Go.

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

В первой части статьи мы разобрали саму идею ускорения кода на Go с помощью ассемблера. А в этой разберём её практическое применение.

Читать далее

Часть 1. Почему Go-ассемблер и векторизация могут быть полезны: идея для ускорения

Время на прочтение12 мин
Охват и читатели4.2K

Когда речь заходит о производительности в Go, большинство разработчиков полагаются на стандартные библиотеки и встроенные инструменты оптимизации, но компилятор Go не всегда генерирует оптимальный машинный код. В таких случаях можно взять дело в свои руки и использовать ассемблерные инструкции для ускорения критически важных участков.

Ассемблер может показаться сложным и пугающим, но он открывает большие возможности для работы с низкоуровневыми оптимизациями. Готовы разобраться, как это работает? Тогда погнали!

Привет, Хабр! Меня зовут Игорь Панасюк, я работаю в Яндекс, преподаю в ИТМО, а также в свободное время выступаю на конференциях, делюсь опытом в соцсетях и помогаю развитию Go-сообщества.

Читать далее