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

1. Язык. Преимущества и отличия от ЯВУ


Ассемблер (Assembly) — язык программирования, понятия которого отражают архитектуру электронно-вычислительной машины. Язык ассемблера — символьная форма записи машинного кода, использование которого упрощает написание машинных программ. Для одной и той же ЭВМ могут быть разработаны разные языки ассемблера. В отличие от языков высокого уровня абстракции, в котором многие проблемы реализации алгоритмов скрыты от разработчиков, язык ассемблера тесно связан с системой команд микропроцессора. Для идеального микропроцессора, у которого система команд точно соответствует языку программирования, ассемблер вырабатывает по одному машинному коду на каждый оператор языка. На практике для реальных микропроцессоров может потребоваться несколько машинных команд для реализации одного оператора языка.

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

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

Для успешного использования ассемблера необходимы сразу три вещи:

  • знание синтаксиса транслятора ассемблера, который используется (например, синтаксис MASM, FASM и GAS отличается), назначение директив языка ассемблер (операторов, обрабатываемых транслятором во время трансляции исходного текста программы);
  • понимание машинных инструкций, выполняемых процессором во время работы программы;
  • умение работать с сервисами, предоставляемыми операционной системой — в данном случае это означает знание функций Win32 API. При работе с языками высокого уровня очень часто к API системы программист прямо не обращается; он может даже не подозревать о его существовании, поскольку библиотека языка скрывает от программиста детали, зависящие от конкретной системы. Например, и в Linux, и в Windows, и в любой другой системе в программе на Си/Си++ можно вывести строку на консоль, используя функцию printf() или поток cout, то есть для программиста, использующего эти средства, нет разницы, под какую систему делается программа, хотя реализация этих функций будет разной в разных системах, потому что API систем очень сильно различается. Но если человек пишет на ассемблере, он уже не имеет готовых функций типа printf(), в которых за него продумано, как «общаться» с системой, и должен делать это сам.

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

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

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

  • объем используемой памяти (программы-загрузчики, встраиваемое программное обеспечение, программы для микроконтроллеров и процессоров с ограниченными ресурсами, вирусы, программные защиты и т.п.);
  • быстродействие (программы, написанные на языке ассемблера выполняются гораздо быстрее, чем программы-аналоги, написанные на языках программирования высокого уровня абстракции. В данном случае быстродействие зависит от понимания того, как работает конкретная модель процессора, реальный конвейер на процессоре, размер кэша, тонкостей работы операционной системы. В результате, программа начинает работать быстрее, но теряет переносимость и универсальность).

Кроме того, знание языка ассемблера облегчает понимание архитектуры компьютера и работы его аппаратной части, то, чего не может дать знание языков высокого уровня абстракции (ЯВУ). В настоящее время большинство программистов разрабатывает программы в средах быстрого проектирования (Rapid Application Development) когда все необходимые элементы оформления и управления создаются с помощью готовых визуальных компонентов. Это существенно упрощает процесс программирования. Однако, нередко приходится сталкиваться с такими ситуациями, когда наиболее мощное и эффективное функционирование отдельных программных модулей возможно только в случае написания их на языке ассемблера (ассемблерные вставки). В частности, в любой программе, связанной с выполнением многократно повторяющихся циклических процедур, будь это циклы математических вычислений или вывод графических изображений, целесообразно наиболее времяемкие операции сгруппировать в программируемые на языке ассемблера субмодули. Это допускают все пакеты современных языков программирования высокого уровня абстракции, а результатом всегда является существенное повышение быстродействия программ.

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

2. О компиляторах


Какой ассемблер лучше?


Для процессора x86-x64, имеется более десятка различных ассемблер компиляторов. Они отличаются различными наборами функций и синтаксисом. Некоторые компиляторы больше подходят для начинающих, некоторые ? для опытных программистов. Некоторые компиляторы достаточно хорошо документированы, другие вообще не имеют документации. Для некоторых компиляторов разработано множеством примеров программирования. Для некоторых ассемблеров написаны учебные пособия и книги, в которых подробно рассматривается синтаксис, у других нет ничего. Какой ассемблер лучше?

Учитывая множество диалектов ассемблеров для x86-x64 и ограниченное количество времени для их изучения, ограничимся кратким обзором следующих компиляторов: MASM, TASM, NASM, FASM, GoASM, Gas, RosAsm, HLA.

Какую операционную систему вы бы хотели использовать?


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

Windows DOS Linux BSD QNX MacOS, работающий на
процессоре Intel/AMD
FASM x x x x
GAS x x x x x x
GoAsm x
HLA x x
MASM x x
NASM x x x x x x
RosAsm x
TASM x x

Поддержка 16 бит


Если ассемблер поддерживает DOS, то он поддерживает и 16-разрядные команды. Все ассемблеры предоставляют возможность писать код, который использует 16-разрядные операнды. 16-разрядная поддержка означает возможность создания кода, работающего в 16-разрядной сегментированной модели памяти (по сравнению с 32-разрядной моделью с плоской памятью, используемой большинством современных операционных систем).

Поддержка 64 бит


За исключением TASM, к которому фирма Borland охладела в середине нулевых, и, который не поддерживает в полном объеме даже 32-разрядные программы, все остальные диалекты поддерживают разработку 64-разрядных приложений.

Переносимость программ


Очевидно, что вы не собираетесь писать код на ассемблере x86-x64, который запускался бы на каком-то другом процессоре. Однако, даже на одном процессоре вы можете столкнуться с проблемами переносимости. Например, если вы предполагаете компилировать и использовать свои программы на ассемблере под разными операционными системами. NASM и FASM можно использовать в тех операционных системах, которые они поддерживают.

Предполагаете ли вы писать приложение на ассемблере и затем портировать, это приложение с одной ОС на другую с «перекомпиляцией» исходного кода? Эту функцию поддерживает диалект HLA. Предполагаете ли вы иметь возможность создавать приложения Windows и Linux на ассемблере с минимальными усилиями для этого? Хотя, если вы работаете с одной операционной системой и абсолютно не планируете работать в какой-либо другой ОС, тогда эта проблема вас не касается.

Поддержка высокоуровневых языковых конструкций


Некоторые ассемблеры предоставляют расширенный синтаксис, который обеспечивает языковые высокоуровневые структуры управления (типа IF, WHILE, FOR и так далее). Такие конструкции могут облегчить обучение ассемблеру и помогают написать более читаемый код. В некоторые ассемблеры встроены «высокоуровневые конструкции» с ограниченными возможностями. Другие предоставляют высокоуровневые конструкции на уровне макросов.

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

Качество документации


Удобство использования ассемблера напрямую связано с качеством его документации. Учитывая объем работы, который тратится для создания диалекта ассемблера, созданием документации для этого диалекта авторы компиляторов практически не заморачиваются. Авторы, расширяя свой язык, забывают документировать эти расширения.

В следующей таблице описывается качество справочного руководства ассемблера, которое прилагается к продукту:

Документация Комментарии
FASM Хорошая Большую часть свободного времени автор отдает в разработку инновационного FASMG. Тем не менее, автор обеспечивает поддержку FASM время от времени обновляет мануалы, а новые функции описывает на собственном форуме. Документацию можно считать достаточно хорошей. Веб-страница документации.
Gas
Плохая
документирован слабо и документация, скорее, имеет «общий вид». gas ? это ассемблер, который был разработан, чтобы можно было легко писать код для разных процессоров. Документация, которая существует, в основном описывает псевдо коды и ассемблерные директивы. В режиме работы «intel_syntax» документация практически отсутствует. Книги, в которых используется синтаксис «AT&T»: «Программирование с нуля» Джонатона Бартлетта и «Профессиональный язык ассемблера» Ричарда Блюма, Konstantin Boldyshev asmutils — Linux Assembly.
GoAsm
Слабая
Большая часть синтаксиса описана в руководстве, и опытный пользователь найдет то, что ищет. Множество руководств и размещено на сайте (http://www.godevtool.com/). Несколько учебников GoAsm:

HLA
Обширая
HLA имеет справочное руководство на 500 страниц. Сайт содержит десятки статей и документацию по HLA.
MASM
Хорошая
Компанией Microsoft написано значительное количество документацию для MASM, существует большое количество справочников написанных для этого диалекта.
NASM
Хорошая
Авторы NASM больше пишут программное обеспечение для этого диалекта, оставляя написание руководства на «потом». NASM существует достаточно долго, поэтому несколько авторов написали руководство для NASM Джефф Дунтеман (Jeff Duntemann) «Assembly Language Step-by-Step: Programming with Linux», Jonathan Leto «Writing A Useful Program With NASM», на русском языке есть книга Столярова (Сайт А.В. Столярова).
RosAsm
Слабая
не очень интересные «онлайновые учебники».
TASM
Хорошая
Компания Borland в свое время выпускала отличные справочные руководства, для TASM были написаны справочные руководства авторами-энтузиастами не связанными с фирмой Borland. Но Borland больше не поддерживает TASM, поэтому большая часть документации, предназначенная для TASM, не печатается и ее становится всё труднее и труднее найти.


Учебники и учебные материалы


Документация на самом ассемблере, конечно, очень важна. Еще больший интерес для новичков и других, изучающих язык ассемблера (или дополнительные возможности данного ассемблера), ? это наличие документации за пределами справочного руководства для языка. Большинство людей хотят, чтобы учебник, объясняющий, как программировать на ассемблере, не просто предоставляет синтаксис машинных инструкций и ожидает, что читателю объяснят, как объединять эти инструкции для решения реальных проблем.

MASM является лидером среди огромного объема книг, описывающих, как программировать на этом диалекте. Есть десятки книг, которые используют MASM в качестве своего ассемблера для обучения ассемблеру.

Большинство учебников по ассемблеру MASM/TASM продолжают обучать программированию под MS-DOS. Хотя постепенно появляются учебники, которые обучают программированию в Windows и Linux.

Комментарии
FASM Несколько учебников, в которых описывается программирование на FASM:

Gas
Учебник с использованием синтаксиса AT&T
HLA
32-разрядная версия «The Art of Assembly Language Programming» (существует и в электронной, и в печатной форме), программирование под Windows или Linux
MASM
большое количество книг по обучению программированию под DOS. Не очень много книг о программировании под Win32/64 Пирогов, Юров, Зубков, Фленов
NASM
много книг, посвященных программированию в DOS, Linux, Windows. В книге Джеффа Дунтемана «Assembly Language Step-by-Step: Programming with Linux» используется NASM для Linux и DOS. Учебник Пола Картера использует NASM (DOS, Linux).
TASM
Как и для MASM, для TASM было написано большое количество книг на основе DOS. Но, так как Borland больше не поддерживает этот продукт, писать книги об использовании TASM перестали. Том Сван написал учебник, посвященный TASM, в котором было несколько глав о программировании под Windows.


3. Литература и веб ресурсы


Beginners


  1. Абель П. Язык Ассемблера для IBM PC и программирования. – М.: Высшая школа, 1992. – 447 с.
  2. Брэдли Д. Программирование на языке ассемблера для персональной ЭВМ фирмы IBM.– М.: Радио и связь, 1988. – 448 с.
  3. Галисеев Г.В. Ассемблер IBM PC. Самоучитель.: – М.: Издательский дом «Вильямс», 2004. – 304 с.: ил.
  4. Дао Л. Программирование микропроцессора 8088. – М.: Мир, 1988. – 357 с.
  5. Жуков А.В., Авдюхин А.А. Ассемблер. – Спб.: БХВ-Петербург, 2003. – 448 с.: ил.
  6. Зубков С.В., Ассемблер для DOS, Windows и UNIX. – М.: ДМК Пресс, 2000. – 608 с.: ил. (Серия «Для программистов»).
  7. Ирвин К. Язык ассемблера для процессоров Intel, 4-е издание.: пер. с англ. – М.: Издательский дом «Вильямс», 2005. – 912 с.: ил. – Парал. тит. англ.(см. также свежее 7-ое издание в оригинале)
  8. Нортон П., Соухэ Д. Язык ассемблера для IBM PC.– М.: Компьютер, 1992.– 352 с.
  9. Пильщиков В.Н. Программирование на языке ассемблера IBM PC.– М.: ДИАЛОГ-МИФИ, 1994–2014 288 с.
  10. Скляров И.С. Изучаем ассемблер за 7 дней www.sklyaroff.ru


Advanced


  1. Касперски К. Фундаментальные основы хакерства. Искусство дизассемблирования. – М.: СОЛОН-Пресс, 2004. 448 с. – (Серия «Кодокопатель»)
  2. Касперски К. Техника отладки программ без исходных текстов. – Спб.: БХВ-Петербург, 2005. – 832 с.: ил.
  3. Касперски К. Компьютерные вирусы изнутри и снаружи. – Спб.: Питер, 2006. – 527 с.: ил.
  4. Касперски К. Записки исследователя компьютерных вирусов. – Спб.: Питер, 2006. – 316 с.: ил.
  5. Кнут Д. Искусство программирования, том 3. Сортировка и поиск, 2-е изд.: пер. с англ. – М.: Издательский дом «Вильямс», 2003. – 832 с.: ил. – Парал. тит. англ.
  6. Колисниченко Д.Н. Rootkits под Windows. Теория и практика программирования «шапок-невидимок», позволяющих скрывать от системы данные, процессы, сетевые соединения. – Спб.: Наука и Техника, 2006. – 320 с.: ил.
  7. Лямин Л.В. Макроассемблер MASM.– М.: Радио и связь, 1994.– 320 с.: ил.
  8. Магда Ю. Ассемблер для процессоров Intel Pentium. – Спб.: Питер, 2006. – 410 с.: ил.
  9. Майко Г.В. Ассемблер для IBM PC.– М.: Бизнес-Информ, Сирин, 1997.– 212 с.
  10. Уоррен Г. Алгоритмические трюки для программистов, 2-е изд.: пер. с англ. – М.: Издательский дом «Вильямс», 2004. – 512 с.: ил. – Парал. тит. англ.
  11. Скляров И.С. Искуство защиты и взлома информации. – Спб.: БХВ-Петербург, 2004. – 288 с.: ил.
  12. Уэзерелл Ч. Этюды для программистов: Пер. с англ. – М.: Мир, 1982. – 288 с., ил.
  13. Электронная библиотека братьев Фроловых www.frolov-lib.ru
  14. Чекатов А.А. Использование Turbo Assembler при разработке программ.– Киев: Диалектика, 1995.– 288 с.
  15. Юров В. Assembler: специальный справочник.– Спб.: Питер, 2001.– 496 с.: ил.
  16. Юров В. Assembler. Практикум. 2-е изд. – Спб.: Питер, 2006. – 399 с.: ил.
  17. Юров В. Assembler. Учебник для вузов. 2-е изд. – Спб.: Питер, 2007. – 637 с.: ил.
  18. Пирогов В. Assembler учебный курс. 2001 Нолидж
  19. Пирогов В. АССЕМБЛЕР учебный курс 2003 Нолидж-БХВ
  20. Пирогов В. Assembler для windows 
    1-ое издание ? М.: изд-во Молгачева С.В., 2002 
    2-ое издание ? СПб.:. БХВ-Петербург, 2003 ? 684 с.: ил. 
    3-ье издание ? СПб.:. БХВ-Петербург, 2005 ? 864 с.: ил. 
    4-ое издание ? СПб.:. БХВ-Петербург, 2012 ? 896 с.: ил.
  21. Пирогов В. Ассемблер на примерах. ? СПб.:. БХВ-Петербург, 2012 ? 416 с.: ил.
  22. Пирогов В. АССЕМБЛЕР и дизассемблирование. ? СПб.:. БХВ-Петербург, 2006. ? 464 с.: ил.
  23. Пирогов В. работа над книгой '64-битовое программирование на ассемблере (Windows,Unix)'. В книге рассматривается программирование на fasm в 64-разрядных Windows и Unix
  24. Юров В., Хорошенко С. Assembler: учебный курс.– Спб.: Питер, 1999. – 672 с.
  25. Ю-Чжен Лю, Гибсон Г. Микропроцессоры семейства 8086/8088. Архитектура, программирование и проектирование микрокомпьютерных систем.– М.: Радио и связь, 1987.– 512 с.
  26. Agner Fog: Software optimization resources (assembly/c++) 1996 – 2017. Веб-страница
  27. Intel ® 64 and IA-32 Architectures Optimization Reference Manual
  28. Intel ® 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture
  29. Intel ® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A: Instruction Set Reference, A-M
  30. Intel ® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B: Instruction Set Reference, N-Z
  31. Intel ® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1
  32. Intel ® 64 and IA-32 Architectures Software Developer’s Manual Volume 3B: System Programming Guide, Part 2
  33. Leiterman J.C. 32/64-BIT 80x86 Assembly Language Architecture. © 2005, Wordware Publishing, Inc (568 pages) 2320 Los Rios Boulevard Plano, Texas 75074
  34. Turbo Assembler® Version 3.2 User's Guide Borland International. Inc 1800 Green Hills Road P.O. BOX 660001, Scotts Valley, CA 95067-0001
  35. Статьи с сайта wasm.in
  36. Статьи с сайта sasm.narod.ru
  37. Сайт MASM32 и форум
  38. Сайт FASM и форум
  39. Сайт NASM

4. Практика


Итак, вы уже знаете, что такое ассемблер и с чем его едят. Вы запаслись парой/тройкой книг и веб мануалами, возможно определились и с компилятором… К сожалению уроки программирования выходят за рамки данной статьи, но для тех чей выбор пал на MASM/FASM можете воспользоваться следующими макетами:


Остается открытым вопрос, в каком редакторе писать код? Кто-то пишет в блокноте и компилирует через командную строку, более смекалистые готовят скрипты – упрощая процесс, другие же используют специальные среды разработки. Да, есть IDE и в области низкоуровневого программирования, их обзор также выходит за рамки статьи. Однако пользуясь возможностью, осмелюсь предложить вам попробовать свою среду для программирования на ассемблере – ASM Visual. Кроме базовых возможностей, отличается от аналогов наличием инструментов рефакторинга, метрик кода, в целом более интуитивно понятными интерфейсами и собственным типом проекта.

спойлер
Так получилось, что среда не полностью бесплатная. Вы можете поддержать проект приобретая Pro лицензию за свободную стоимость. Используйте код: HABR_zzdBG1qadG (если бесплатно установите бегунок в позицию 0).

Желаем вам, друзья, значительных достижений и новых знаний в 2018 году!

С уважением
Михаил Смоленцев MiklIrk (Иркутский государственный университет путей сообщения),
Алексей Гриценко expressrus (Донской государственный технический университет).


Ps1: Уважаемый, Хабрахабр! Добавьте в ваш редактор подсветку ассемблера (Intel-синтаксис), это пригодится для будущих статей!

Ps2: В скором времени мы запустим портал с тестами (вопрос – варианты ответа) на знание ассемблера и архитектуры компьютера. Тесты будут структурированы по уровню сложности. Если вы преподаете ассемблер или имеете достаточные знания в этой области – напишите нам на почту express-rus@yandex.ru вы можете принять участие предложив свой тест в систему.

Комментарии (146)


  1. ZyXI
    02.01.2018 14:51

    А ещё в природе есть такая вещь, как i386 в корпусе PQFP. У нас под него писали на ассемблере, потому что nasm может сразу выдать Intel hex, содержащий только нашу программу, а возиться для получения аналогичного результата на C никому не хотелось.


    1. izzholtik
      02.01.2018 15:08

      визуально это довольно просто…

      gcc test.c -o test
      objcopy -O ihex test.o test.hex

      не факт, что я прав, конечно.


      1. ZyXI
        02.01.2018 15:44

        На работе у меня Windows (7, WSL нету), там не ELF’ы и objcopy есть разве что в cygwin (у меня тоже установлен). И вряд ли всё так просто: нужно разместить безусловный переход по строго определённому адресу (вектора прерываний), а сама программа должна быть по нулевому адресу. И ещё к аргументам нужно добавить, как минимум, -march=i386 -static -Os. И нужно понять как записывать и считывать регистры специального назначения. Разобраться можно, но зачем?


        Помимо этого написание программы на ассемблере позволило использовать «память» в режиме «только чтение», обошедшись без стека и без собственно реализации записи в память — самой памяти в системе никогда не было, была имитация на FPGA, которую тоже нужно написать.


        1. MacIn
          02.01.2018 16:04

          Fasm тоже прекрасно выдает чистый бинарник.


          1. ZyXI
            02.01.2018 16:22

            Не понимаю, к чему этот комментарий. Если какой?то *asm не способен выдавать «чистый бинарник», то зачем он вообще нужен?


            1. MacIn
              02.01.2018 18:34

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


              1. johnfound
                02.01.2018 19:39

                скорее всего и не .exe а .obj


                1. MacIn
                  02.01.2018 20:14

                  Да, но это уже деталь. На Fasm много проще создать код «вне формата».


                  1. johnfound
                    02.01.2018 21:06

                    На Fasm много проще создать код «вне формата».

                    Конечно, на то он и FASM. ;)


  1. tidsresenarens
    02.01.2018 15:32

    Говоря про Ирвина, я бы «обновил» издание до 7-го, пусть оно и на английском языке


    1. expressrus Автор
      02.01.2018 15:44

      Добавил в скобки факт его существования. Благодарю.


  1. Daniil1979
    02.01.2018 15:33

    Хех… Я был уверен, что НИКОГДА уже не увижу на Хабре (да и любом другом сайте) статьи про ассемблер.
    Вспомнил молодость, ассемблер, Clipper, с чего начинается Родина… В смысле, первые символы dos-овского .exe-файла и первые символы .exe-файла под Windows, как ставили Windows 95 поверх MS-DOS и Windows 3.1, а потом пытались откатиться при помощи установки Windows 3.1… Эх…


    1. izzholtik
      02.01.2018 16:42
      +1

      Ассемблер будет использоваться всегда. Потому что всегда будут микроконтроллеры по $0.2 с килобайтом флэша и тремя с половиной регистрами, которых достаточно для управления микроволновкой.


      1. boblenin
        02.01.2018 17:23
        +1

        Одно дело ассемблер для этих микроконтроллеров, другое дело x64


      1. 0xd34df00d
        02.01.2018 17:47

        Под такие микроконтроллеры можно тоже писать на плюсах, есть положительный опыт с attiny. Не микроволновкой, правда, а лазером в экспериментальной установке управляли, но то такое.


        1. izzholtik
          02.01.2018 23:47

          Да без проблем, я под AVR на C++ писал. Сейчас кто угодно эту платформу поддерживает, даже раст.


        1. Daddy_Cool
          03.01.2018 07:22

          Аналогично. Управляем установкой, МК — Atmega какая-то, пишем на С. Наверное можно и на асме, но зачем? На ассемблере написал «Жизнь» — когда на курсах по нему учился и всё.


      1. AllexIn
        02.01.2018 18:23

        В мире, где железо стремительно дешевеет, а программиста — стремительно дорожают ваше утверждение выглядит сомнительным.


        1. VEG
          02.01.2018 18:28

          Дешевеет уже давно не так стремительно как раньше, и со временем будет дешеветь всё меньше.

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


          1. NetBUG
            03.01.2018 04:30

            Ну да, поскольку мы, кажется, уже упёрлись в стоимость пластика и рамки с выводами.


    1. monah_tuk
      02.01.2018 20:34

      Я на ассемблере не пишу, пишу на C++, но знать и понимать его стоит. Как минимум для целей отладки или понимания происходящего под капотом: иногда после этого сильно по другому смотришь на более высокий уровень. Обязательно нужно знакомится с соглашениями по вызовам для вашей платформы и так далее. Особенно это актуально для всякого embedded.


  1. Hokum
    02.01.2018 16:00

    Может быть у вас есть пример из реального проекта, когда вставки на ассемблере существенно дали выигрыш в скорости для десктоп приложения? Или использование ассемблера все таки ограничивается драйверами и узкоспециализированным ПО, где действительно нужно быть уверенным в том, что происходит на уровне процессора? Я не пытаюсь приуменьшить достоинства ассемблера, просто мне кажется, что современные компиляторы оптимизируют код лучше, чем среднестатистический программист сможет написать ассемблере.

    Знание ассемблера безусловно полезное, например в случае отладки, когда есть только бинарный код, но насколько целесообразно в прикладном ПО делать вставки на ассемблере?


    1. MacIn
      02.01.2018 16:03

      Ну, здесь на Хабре была серия статей — человек написал на языке ассемблера сервер и форум на его основе, поищите.


      1. leotsarev
        02.01.2018 16:29

        Да, и выяснилось, что он не самый быстрый. Например, фаза рендеринга markdown в html там не кешируется.


        1. MacIn
          02.01.2018 18:35

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



    1. ValdikSS
      02.01.2018 16:16

      Если говорить про ассемблерные вставки, а не про написание программы полностью на ассемблере, то они в высокопроизводительных программах используются повсеместно: в рендерерах 3D, в видеокодеках, в программах для изменения размеров изображений.

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


      1. 0xd34df00d
        02.01.2018 17:48

        В первом случае почти всегда достаточно интринсиков.


    1. j-ker
      02.01.2018 17:00

      https://github.com/cisco/openh264 — полистайте здесь


    1. expressrus Автор
      02.01.2018 17:19
      +1

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


      1. iig
        02.01.2018 18:02

        Ну, не буду сильно спорить..


        Возьмем достаточно большой файл.


        time cat 700mb.iso > /dev/null 
        
        real    0m13.280s
        user    0m0.024s
        sys 0m0.632s
        
        time cat 700mb.iso > /dev/null 
        
        real    0m0.275s
        user    0m0.004s
        sys 0m0.220s

        Из диска он читается 13с, из кеша — меньше секунды.


        time cat 700mb.iso | md5sum -
        73fe07300ad456cff2f7b9524c295fd1  -
        
        real    0m1.518s
        user    0m1.336s
        sys 0m0.544s

        Хеш-сумма этих 700 мб считается около 1 с.


        Нехитрый эксперимент показывает, что самое медленное при работе с файлами — дисковый ввод-вывод; его в первую очередь нужно оптимизировать.


      1. 4eyes
        02.01.2018 18:58

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

        Вот С++ код умножения на 5 и суммирования 1024 байт из буффера, и я с трудом представляю, каких сил будет стоить написание и сопровождение подобного кода вручную:

        godbolt.org/g/2QW1Qx


        1. iig
          02.01.2018 19:17

          Так на ассемблере писать никто не будет. С этим замечательно справится компилятор.
          Цикл из 1024 сложений и одно умножение на 5 (2 сдвига и сложение) — это как-то более логично.


          1. 4eyes
            02.01.2018 19:40

            А что ж тогда писать на ассемблере в контексте оптимизации?


            1. iig
              02.01.2018 20:20

              А это смотря что нужно оптимизировать. В смысле написания и поддержки — 2 строки на C++ конечно же, оптимальное решение.
              В смысле быстродействия… Напрашивающийся цикл из 1024 сложений выглядит лучше… На 8086 это бы прокатило ;) Но компилятор лучше знает архитектуру процессора, и, подозреваю, что эти странные 128-битные операции неспроста..


              1. 4eyes
                02.01.2018 20:38

                Напрашивающийся цикл из 1024 сложений выглядит лучше…
                Вряд ли он лучше. Работать будет в лучшем случае так же, но скорее всего — медленнее. И дело не только в странных и не очень операциях, а еще и в ветвлениях и затратах на сам цикл.


                1. iig
                  02.01.2018 20:57

                  Да. Если написать коротко и понятно — это будет, скорее всего, неоптимально. А если написать оптимально — будет сложно (а то и невозможно) поддерживать.
                  Так, в вашем примере, если заменить int на short (или long) — компилятор использует совершенно другие инструкции. Получается, для разных типов данных написанный на ассемблере алгоритм нужно переписывать.


              1. tyomitch
                03.01.2018 10:29

                Нет, даже во времена 8086 для быстродействия приходилось разворачивать циклы, иначе ветвления пожирали всё время выполнения.


      1. 4eyes
        02.01.2018 19:14

        Вдогонку к предыдущему сообщению:

        … а С++ реализация cosine similarity между одним float-вектором размерностью 192 и 1.7 гигабайтами других таких же векторов с использованием SIMD-intrinsics вычисляется за 0.3 секунды на процессоре Celeron J1900 @ 1.99GHz, на NAS-е, внутри виртуалки.

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


    1. lexa
      02.01.2018 19:45

      Обработка изображения в моем/нашем FastRawViewer — это SSSE3 (и AVX2 на тех процессорах, где оно есть).
      Это не ассемблер в чистом виде, а вот как-то вот так:

      xlo = _mm256_unpacklo_epi16(row0, zero);
      xhi = _mm256_unpackhi_epi16(row0, zero);
      pix0_0_7 = _mm256_cvtepi32_ps(xlo);
      pix0_8_f = _mm256_cvtepi32_ps(xhi);
      row1 = _mm256_permutevar8x32_epi32(_mm256_loadu_si256((const _m256i*)&srcrow2[scol]), b256m);

      Относительно очень близкой по логике обработки dcraw/LibRaw, выигрыш на SSSE3 — примерно порядок, от AVX2 — еще раза в полтора (плюс dcraw/LibRaw — целочисленные, а FRV — внутри в плавучке, что несколько улучшает качество теней)


      1. 4eyes
        02.01.2018 19:47

        Это не просто «не ассемблер в чистом виде», это Си :)


        1. monah_tuk
          02.01.2018 20:39

          Это даже не сколько Си, это интринсики :)


          1. 4eyes
            02.01.2018 20:50

            Так в том-то и посыл, что по-моему, чаще всего ассемблер для задач оптимизиции нужен только для того, чтобы читать код. А писать и проще и лучше на С/С++, используя интринсики там, где это нужно. Главное отличие в том, что программисту не нужно следить за регистрами и адресами.

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

            Конечно, бывают задачи, которые проще решаются на ассемблере: первое, что приходит в голову из того, что писал сам — загрузчик в MBR. Но когда речь идет об оптимизации, я подозреваю баг компилятора или ошибку в высокоуровневом коде.


            1. monah_tuk
              02.01.2018 22:03

              Так в том-то и посыл...

              Полностью согласен.


              что приходит в голову из того, что писал сам — загрузчик в MBR

              Что удивительно, беглый поиск не показал мне ни одного pureC бутлодера в MBR на Си… Хотя вру: https://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part хотя и тут без вставок никак.


              1. tyomitch
                03.01.2018 12:21

                Более новые архитектуры, чем x86, изначально разрабатываются с учётом того, чтобы загрузчик можно было писать на чистом Си с интринсиками.

                Говорить «для загрузчика необходим ассемблер», глядя на x86 — всё равно, что говорить «для завода двигателя необходим кривой стартёр», глядя на 2101.


                1. monah_tuk
                  03.01.2018 19:00

                  Тут конкретно про MBR речь была. Так то да, взять тот же UEFI.


            1. monah_tuk
              03.01.2018 19:11

              Кстати, вспомнилось: мне однажды нужно было сделать инъекцию: был закрытый код, который вызывался в контексте ISR и ошибочно вызывал функцию логирования (косвенно, через общий код), которая аллоцировала большой буффер на стеке, чем срывала его, будучи запущенной из ISR.


              Инъекция заключалась в том, что имя функции логирования подменялось (средствами GCC и линкера) и вместо неё вызывался враппер, который дополнительно делал проверку. Вот врапер оказалось проще написать на ассемблере, используя знание о соглашениях на вызовы, не портя стек (функция была с переменным числом аргументов).


              Ну и да, я понимаю, что это костыль. Но решилось автоматом ещё несколько проблем и стало обоснованием более предметно предъявить разработчикам закрытой части SDK.


        1. lexa
          03.01.2018 09:48

          Ну да. Адресную арифметику оставляю компилятору.
          Плюс, некоторые компиляторы позволяют себе переупорядочить порядок действий.

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


    1. Hokum
      02.01.2018 23:41

      MacIn, acyp спасибо за указания на статьи. Но я имел ввиду пример, когда целесообразно сделать ассемблерные вставки. Вот пишу я некоторое десктопное приложение на C++ и в какой-то момент понимаю, что вот здесь лучше написать на ассемблере. Есть ли такое в современное практике у кого-нибудь? И если да, то какой прирост получился? Понятно, что если захотеть, то можно написать сколь угодно большое приложение на ассемблере, включая многопоточность, работу с сетью и т.д. и т.п. Но хочется не доказательства того что это возможно, а примера когда это было целесообразно. Не холивара ради, а просто из любопытства. Так как я вряд ли смогу написать на ассемблере эффективнее компилятора, но вполне допускаю, что такие люди есть и такие ситуации тоже.


      1. old_bear
        03.01.2018 00:03

        У меня есть вполне обширный опыт по написанию asm-функций для вычислительно-интенсивных частей алгоритмов, с применением simd-ов. Прирост для конкретно этого кода в разы, иногда в десятки раз. Для всего приложения включение оптимизаций даёт прирост в несколько раз. Правда этих оптимизаций в приложении уже довольно много накопилось.
        Но это именно отдельные функции, а не вставки asm-а в С-код.


        1. Hokum
          03.01.2018 00:11

          Спасибо. Тут еще выше привели пример с инструкциями SSE3, не совсем про ассемблер, но то же интересно.


          1. old_bear
            03.01.2018 00:29

            Интринсики (intrinsics) — неплохая штука, когда нужно быстро объяснить глупому компилятору, как можно сделать при помощи simd-ов что-то относительно простое. Но к сожалению они не дают контроля над регистрами. Даже в том примере, на который вы обратили внимание, нет никаких гарантий, что, например, переменная «xlo» не будет запихнута в стек в промежутке между первой и третьей строчками кода (а это, на минуточку, 32 байта). И такие ситуации частенько возникают, когда количество одновременно используемых simd-регистров (переменных) становится больше 6-8 (при том, что всего их доступно 16 в режиме х86-64).
            С другой стороны хорошие компиляторы могут и самостоятельно использовать эффективные simd-инструкции при правильно написанном С-коде и высоком уровне оптимизации. И временами это бывает не менее эффективно, чем использование интринсиков.


            1. bibmaster
              04.01.2018 03:53

              С intrinsics ещё такая штука, если поддержку того или иного instruction set надо проверять в runtime, приходится generic/optimized версии функций компилировать отдельно. Или же можно использовать явный вызов через asm. Кстати, о SSE… Не зря например в протоколе Kafka используют CRC32C. Потому что для него есть инструкции в SSE4.2.


              1. 0xd34df00d
                04.01.2018 18:46
                +2

                приходится generic/optimized версии функций компилировать отдельно

                Зачем? Есть же атрибуты, вроде __attribute__((target("ssse3"))) для gcc и clang. Можно в одном translation unit держать версии для нескольких SIMD-наборов.

                gcc вам даже сам трамплин сгенерирует.


      1. Cheater
        03.01.2018 00:45

        Использование знания ассемблера в C/C++ разработке не ограничивается только переписыванием кусков кода на ассемблере. У меня лично самый частый сценарий использования ассемблера — это смотреть, в какой вообще ассемблерный код компилятор превратил критичный кусок C++ кода. Например заинлайнил ли вызов функции, или статическую константу. Если обнаружен неоптимальный вызов — значит можно пытаться выиграть ещё, причём косвенно (меняя высокоуровневый код), кстати то ещё развлечение по сравнению с переписыванием напрямую на асме.


      1. vdem
        04.01.2018 00:06
        +1

        Лет ~20 назад в бытность школьником писал свою реализацию графических примитивов для VESA-режимов (с высоким разрешением) на Borland Pascal (я тогда не знал что есть родные BGI драйверы для этих режимов). Вывод работал заметно медленно, особенно линии и окружности. После переписывания этих методов (и еще нескольких оптимизаций) на inline-ассемблер скорость возросла на порядок минимум. Но сейчас компиляторы гораздо умнее.


    1. AlexeiZavjalov
      03.01.2018 00:13

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


    1. Jef239
      03.01.2018 07:17
      +1

      Может быть у вас есть пример из реального проекта, когда вставки на ассемблере существенно дали выигрыш в скорости для десктоп приложения?


      1. Битовый массив. Ассемблерные инструкции позволили напрямую ставить/снимать/проверять бит. То же самое чрез маску — работало прилично медленней.
      2. Критическая секция для однопроцессорных машин. Работала без переключения в режим ядра для случая, когда вход в критсекцию свободен. Применялась в серверном приложении при одновременной работе 20 тредов. Проблема была в том, что нужно было обращение к регистру FS, которое компилятор не поддерживал

      но насколько целесообразно в прикладном ПО делать вставки на ассемблере?
      В прикладном не знаю, а в библиотеках такого очень много. Можете полюбоваться на ассемблерную версию memchr из glibc.


      1. AnutaU
        03.01.2018 10:59

        Битовый массив. Ассемблерные инструкции позволили напрямую ставить/снимать/проверять бит. То же самое чрез маску — работало прилично медленней.
        Хм, мне казалось, что компиляторы умеют генерировать битовые инструкции из обращений к битовым полям.


        1. tyomitch
          03.01.2018 12:31

          Конечно умеют: godbolt.org/g/oDZDxw


          1. aleaksah
            04.01.2018 00:06

            На моем опыте под битовыми операциями понимаются следующие конструкции: https://godbolt.org/g/1Ayj7e
            В то время как это вполне себе описывается:
            mov eax, dword ptr [x]
            sub eax, 5
            BTR argc, eax
            add eax, 7
            BTS argc, eax


            1. tyomitch
              04.01.2018 01:20

              1. aleaksah
                04.01.2018 11:22

                Указанный gcc8.0 все еще в разработке, а текущие компиляторы не умеют оптимизировать работу с битами.


        1. Jef239
          03.01.2018 17:05

          Конкретно Delphi 5 — не умел. Компиляторы вообще не умеют использовать наборы инструкций, получившие распространение после их написания. :-)


          1. tyomitch
            03.01.2018 18:49

            Напомню, что здесь обсуждают "как зачем писать на ассемблере в 2018 году", а не «зачем надо было писать на ассемблере в 1999 году, когда компиляторы были глупее, а системы команд — проще».


            1. Jef239
              03.01.2018 23:41

              А чем 2018ый год отличается? Вы или ждете, пока выйдет релиз компилятора с поддержкой нужных вам команд — или пишете ассемблерные вставки. Если не боитесь, то на опенсорсных компиляторах можно ещё и нестабильные ночные билды попробовать.

              Лично мне больше нравится стабильный проверенный компилятор + ассемблерные вставки, чем экспериментальные версии.


    1. konservs
      03.01.2018 07:27

      Есть пример проекта, когда использование ассемблера дало прирост в энергоэффективности устройств.
      В студенческие годы разрабатывал с товарищем АСКУЭ (автоматическая система контроля и учёта электроэнергии). Использование ассемблера и знание режимов работы микроконтроллера позволило запитать 7 кучек (по кучке на подъезд) из 30+ устройств (по устройству на квартиру) очень небольшим блоком питания. Не помню точно потребления, но та что-то в районе микроампер в режиме ожидания и раз в 15 минут при опросе — милиамперы для каждого устройства) Что дало преимущество, когда понадобилось поставить ИБП для всех устройств.


    1. Cooler2
      05.01.2018 21:40

      Есть такие примеры (это десктопные игры): ассемблерные реализации работы с растром и геометрией (особенно на базе MMX/SSE) зачастую дают существенный выигрыш в скорости. Беда правда в том, что такой код привязан к платформе, и не работает на ARM :(


  1. MacIn
    02.01.2018 16:02

    Документация FASM слабая? Простите, но базовая документация, которая идет в стандартной поставке — исчерпывающая.


    1. johnfound
      02.01.2018 17:22

      Я не знаю откуда это пошло, что у FASM документация слабая???


      Это не так! FASM ассемблер простой и та документация которая идет в стандартной поставке и вправду исчерпывающая.


    1. expressrus Автор
      02.01.2018 17:23

      У нас с коллегой немного противоречивое мнение. Когда он появиться (а время у него GMT+8) мы придем к общей позиции и обязательно ответим вам, так же в случае чего подредактируем этот момент в статье. Благодарю.


      1. Acuna
        02.01.2018 20:44

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


        1. expressrus Автор
          03.01.2018 15:07

          Нет не замечал, спасибо что сказали. FASM кстати поправили.


          1. Acuna
            04.01.2018 00:50

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

            За FASM спасибо, у них ман действительно неплохой.


    1. expressrus Автор
      03.01.2018 15:08

      Обсудили и поправили. Спасибо.


  1. masai
    02.01.2018 16:39

    Статья посвящена языку ассемблер с учетом актуальных реалий.

    К сожалению про язык ассемблера в статье ничего. Да и озаглавить бы её стоило, наверное, «Сравнение ассемблеров», чтобы не вводить людей в заблуждение. По моему мнению, (не могу судить о большинстве) заголовок «Как писать на ассемблере в 2018 году» предполагает, что в статье пойдёт речь о там как писать код на языке ассемблера с учётом современных наборов команд или технологий.


    А кто-то реально сейчас пишет на TASM да ещё и для DOS? Устаревшие вузовские курсы не в счёт.


    1. expressrus Автор
      02.01.2018 17:20
      -1

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


  1. glowingsword
    02.01.2018 18:00

    Помню в своём время игрался с FASM и MASM. В качестве IDE использовал RadASM. Давно это было. Последний раз когда имел дело с ASM — использвоал GNU Assembler. В наше время материалов по Asm-тематике мало, народ всё больше к высокоуровневым ЯП тяготеет. Спасибо автору, что занимается просветительской деятельностью по данной тематике в 2018, может кого-то цикл статей по теме заинтересует, и появится новое поколение любителей ассемблера:)


  1. Vanellope
    02.01.2018 18:07

    Реквестирую разработку на асм под х64.


  1. Profi_GMan
    02.01.2018 18:26
    +1

    Спасибо, что хоть кто-то ещё пишет про ассемблер. Очень мало про ассемблер статей


  1. singular_asm
    02.01.2018 19:00

    FASM для BSD существует.
    На flatassembler.net/download.php 4-я ссылка, в описании упоминается OpenBSD


    1. expressrus Автор
      02.01.2018 19:00

      Есть такое дело. Добавили. Благодарю.


      1. johnfound
        02.01.2018 19:49

        Кстати, для MacOS X тоже:


        https://board.flatassembler.net/topic.php?t=13413


        И конечно для Menuet/KolibriOS и всяких экспериментальных ОС. Вообще, FASM, несмотря на то, что написан на ассемблере, переносится очень легко на всяких ОС. Намного легче чем тот же NASM.


  1. KoCMoHaBT61
    02.01.2018 19:21
    +1

    Не знаю, как других, а меня уже давненько выбешивают такие статьи… «Как писать на ассемблере в 2018»…
    Очевидно, что имеется ввиду The Assembler x86. Не какой-то там ARM9 с его баррел-шифтами (правда, кому они нужны?), не какая-то там SH, и не о разнице между MIPS и Loongson, не об Эльбрусовском чего-то там они придумали, не о сетевых всяких там — об их величестве x86.
    Ну, ладно, допустим… Об x86-64… Допустим… Так опять-же не об жонглированием ядрами и атомных инструкциях…
    «Я писал на АСМЕ» — ага, да… Вотиманно на «АСМЕ».


    1. olartamonov
      02.01.2018 21:29

      правда, кому они нужны?


      Гггг. Сегодня сравнивал производительность на Cortex-M3 двух реализаций AES-128 — на C и на асме, в последней как раз barrel shift используется.

      Ну, асм быстрее. Меньше, чем в два раза, но быстрее. Ещё б на фоне недостатков кода на нём это кого-нибудь бы в контексте данного проекта волновало бы.


      1. 0xd34df00d
        02.01.2018 21:39

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


    1. Ardanay
      03.01.2018 07:30

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


  1. Kobalt_x
    02.01.2018 19:57

    На сайте А.В. Столярова книга по NASM, а у вас в таблице она отнесена к GAS. И если не ошибаюсь, то синтаксис AT&T там только упоминается дальше 5й страницы идет интеловский синтаксис.


    1. expressrus Автор
      03.01.2018 15:33

      Спасибо что заметили. Исправили.


  1. DustCn
    02.01.2018 20:49

    Использование ассемблера в вычислительном коде скорее всего приведет к замедлению ваших программ.
    «Компактный код» сейчас совершенно не значит «быстрый код».
    Писать UI, или IO на ассемблере это практически убивать свое время на скучнейшую работу. Если так уж горит — можно сделать всю обвязку на плюсах или еще чем то, а потом сделать ассемблерную вставку.


    1. mapron
      02.01.2018 21:12

      «Использование ассемблера в вычислительном коде скорее всего приведет к замедлению ваших программ.»

      Моих — да, любых — нет)
      К слову, разработчики видеокодеков по-прежнему активно используют асм. Посмотрите исходные коды libvpx, libx265, libx265, да вообще ffmpeg директории asm.


      1. sumanai
        02.01.2018 22:40

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


    1. johnfound
      02.01.2018 21:12

      Использование ассемблера в вычислительном коде скорее всего приведет к замедлению ваших программ.

      А вы пробовали? Я да. Несколько раз. И дело в том, что нет, не получается. На ассемблере всегда получается намного быстрее.


      На C/C++ можно написать быстрые программы, но дело в том, что надо ясно представлять как они должны выглядеть на ассемблере. А потом обмануть компилятора, чтобы сгенерировать нужный ассемблерский код. Для меня проще написать сразу на ассемблере. :P


      1. 0xd34df00d
        02.01.2018 21:41

        Не надо представлять, как они должны выглядеть на ассемблере. Надо представлять, что делает процессор, а это таки совсем немножко другое.

        В моих задачах плюсов достаточно, чтобы что шину памяти насытить, что иногда Intel IPP обогнать (которые, вероятно, на ассемблере). Иными словами, на ассемблере быстрее работать не будет, а вот писать сильно дольше.


        1. old_bear
          02.01.2018 23:23

          Производительность IPP оставляет желать, скажу я вам. У меня куча самописных asm-функций быстрее работают, чем их аналоги в IPP.


      1. masai
        04.01.2018 11:56

        Думаю, все хоть раз игрались с компиляцией программы, а потом с декомпиляцией, чтоб посмотреть, как компилятор выкрутился. Так вот, в последние годы он настолько всё оптимизирует, что для понимания получившегося ассемблерного кода нужно знать назубок чуть ли не все команды процессора (а для x86-64 это здоровенная такая куча), да ещё и огромную кучу трюков. Может, конечно, кто-то на такое и способен, я же просто смирился с тем, что компиляторы оптимизируют лучше человека (да и я не видел, чтобы кто-то этот тезис оспаривал).


        То о чём вы говорите верно разве что для программирования AVR или MSP430, где горсть команд, и человек может ещё конкурировать с компилятором, и где без ассемблера порой никак.


        1. tyomitch
          04.01.2018 16:17
          +1

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


        1. johnfound
          04.01.2018 17:32
          -1

          Может, конечно, кто-то на такое и способен, я же просто смирился с тем, что компиляторы оптимизируют лучше человека (да и я не видел, чтобы кто-то этот тезис оспаривал).

          Я не только оспариваю, но и несколько раз проверял экспериментально. Получается парадоксальный результат — все верно – компилятор компилирует отлично, но все равно, программы на ассемблере получаются быстрее. Дело в том, что человек на ассемблере пишет не так как на ЯВУ (и в этом ошибаются все, которые сравнивают программирование на ассемблер и ЯВУ). Когда пишет на ассемблере, программист выбирает другие алгоритмы, другую архитектуру программы.


          Потому что ленивый и выбирает то, что легче написать именно на ассемблере и то что легче будет поддерживаться. Та же самая программа, можно написать и на C/C++, только код будет смотреться совершенно дико и неестественно.


          Я проверял все это несколько раз, и всегда результат одинаков. Можете попробовать сами. Надо только писать более менее реальную программу, а не "алгоритм XYZ".


          1. MacIn
            04.01.2018 18:43

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


  1. mapron
    02.01.2018 21:12

    (мимо ветки)


  1. m0Ray
    02.01.2018 22:09

    Часто пишу на 8-битном AVR-ассемблере. Часто встречаются задачи, как на плату в 8мм диаметром встроить, скажем, генератор хитрого сигнала, и 555-х там потребуется минимум три, да с обвесом, а ATtiny13 хватит одного.
    В статье же вообще никак не рассмотрены процессоры AVR, особенности avra, да и вообще, гляжу, программирование микроконтроллеров не затронуто.
    Как-то мимо…
    Программировать на асме под x86 — тот ещё ад, кстати. Я пробовал не раз и проклинал всё.


  1. old_bear
    02.01.2018 23:17

    В списке источников явно не хватает Агнера нашего Фога (Agner Fog) с его software optimization resources.


    1. expressrus Автор
      03.01.2018 15:33

      Добавили! Спасибо.


  1. stoune
    02.01.2018 23:56

    Статься начинается как писать на асм, а по сути рассматривается как обучать.
    На мой взгляд учить asm сейчас стоит для всяких ARM Cortex M3 на крайний случай Broadcomm/Raspberry Pi. На PC потребности в нем минимальны. А в embedded — это требование жизни.
    x86 особенно, MIPS частично, во встроееной технике проиграли маркетинговую войну ARM. Его и стоит учить.
    Keil, gnu asm.
    bob.cs.sonoma.edu/IntroCompOrg-RPi/intro-co-rpi.html — интересная книга.


    1. VBKesha
      03.01.2018 01:26

      На мой взгляд учить asm сейчас стоит для всяких ARM Cortex M3 на крайний случай Broadcomm/Raspberry Pi. На PC потребности в нем минимальны. А в embedded — это требование жизни.

      Три года уже работаю в embedded'е ни разу за всё время ни мне ни кому из коллег не довелось использовать ассемблер, дизассемблер приходилось а вот ассемблер нет. Даже тем кто пишет под AVR. Так что очень преувеличено его необходимость в современном embedded'е.
      Что надо это понимание как будет выполнятся программа на том чипе под который пишешь и каким ботом это может выйти.


      1. Gryphon88
        03.01.2018 03:25

        На PICах тоже не требуется? Из-за большого разнообразия комбинаций периферии в линейке наверняка кто-то подбирает впритирку под задачу.


        1. VBKesha
          03.01.2018 12:45
          +1

          Вполне вероятно что где то так и делают. Но там где работаю я обычно сжатые сроки, там не до того чтобы вылизывать всё до байта. На моей памяти был только один проект в котором использовали все ресурсы на 100%, но всё равно в ассемблер не перешли. Слишком дорога получается разработка и поддержка.


          1. johnfound
            03.01.2018 13:13

            На моей памяти был только один проект в котором использовали все ресурсы на 100%, но всё равно в ассемблер не перешли.

            А значит, на 100%, все равно не использовали. :P


    1. quwy
      03.01.2018 02:38

      Современный embedded уже вплотную подошел к жабаскрипту в качестве единственного инструмента, какой, нафиг, ассемблер? Даже страно, что никто до сих пор не выпустил кристалл с аппаратным декодером/интерпретатором этого скриптового безумия.


      1. Jef239
        03.01.2018 07:25

        Думаю, что всем хватило аппаратной оптимизации под яву.


        1. tyomitch
          03.01.2018 10:40

          Java — не первый ЯВУ с аппаратной реализацией:

          Неудивительно, что ни один из «байткод-процессоров» — ни для p-кода, ни для Java — не стал коммерчески успешным. (Сюда же можно отнести и намного более ранний процессор Intel iAPX 432 (1981) — аппаратную реализацию байткода для Ады.) <...> Для того, чтобы «в железе» отслеживать зависимости между данными, распределять их по «железным» регистрам, и переставлять обращения к ним так, чтобы уложиться в «железные» ограничения — требуются очень сложные механизмы. Получается, что при одном и том же уровне полупроводниковых технологий эффективнее создать процессор для простой ISA, и на нём реализовать трансляцию байткода, — чем выполнять этот же байткод «в железе». Вновь и вновь мечтательные айти-предприниматели убеждались, что превратить «универсальный машинный язык» в настоящий — хоть и возможно технически, но коммерчески бесперспективно.


          1. Jef239
            03.01.2018 16:52

            Ну как раз ARM9EJ-S был коммерчески успешным. Мобильников на нем было много. У самого был мобильник c этой технологией. Отличались они от собратьев в 2-3 более шустрой явой.


            1. tyomitch
              03.01.2018 18:55

              Если бы Jazelle была коммерчески успешной, то её бы не выпилили из всех последующих чипов, я полагаю?
              Автор книги «Processor Design» считает так же: «These Java-specific processors prompted some interest, but not a lot of enthusiasm.»


              1. Jef239
                04.01.2018 01:13

                Увы, потребитель пропал. Вы когда в последний раз держали в руках кнопочный телефон с поддержкой java? А в смартфонах — JIT-компиляциия, своя VM, они не нуждаются в специальном процессоре. Так что вторая реинкарнация (на Cortex A8) тоже завершилась.

                Так что запилили-выпилили, опять запилили — опять выпилили, запасаемся покорном и ждем третьей реинкарнации.


          1. Jef239
            03.01.2018 17:00

            Что касается ЯВУ с аппаратной реализацией, то если найдете — почитайте «Как паскаль и оберон попадают на Самсон», вот краткое описание. Там сделали взаимную заточку кодогенератора под железа, а железа под кодогенератор.


          1. MacIn
            03.01.2018 18:46

            А как же МИР?


    1. KoCMoHaBT61
      03.01.2018 07:08

      Какое там обучать, если даже в заголовке «The Assembler»?
      Если обучать, тогда надо брать какой нибудь восьмибитный процессор с регистровой адресной парой, чтобы студентам жизнь мёдом не казалась — КР580, Z80, MOS6510. И писать на этом многозадачную операционку с TCP/IP. Без ограничений языка. Хочешь — пиши на С, только компилятор пиши сам…
      Только, боюсь, 70% студентов вылетят нафиг.
      Да и 70% преподавателей тоже…


      1. tyomitch
        03.01.2018 10:48

        В Технионе (бывшем в двадцатке лучших CS-факультетов в мире) до сих пор учат ассемблеру PDP-11, просто потому что для него лекции и задания уже составлены и выучены наизусть поколениями преподов, а новые составлять ни у кого руки никак не дойдут.
        Я у тамошних преподов спрашивал, не собираются ли они переводить курс на ARM или на ещё что-нибудь актуальное для практических (embedded) целей. Нет: говорят, что если и будут переводить, то на x86 или x64, просто по причине доступности инструментов разработки и сред выполнения.
        :-(


        1. KoCMoHaBT61
          03.01.2018 11:35

          И они молодцы (кроме шуток). У PDP-11 отличнейший высокоуровневый ассемблер, который даст нормальное понимание как оно вообще всё.
          Не надо готовить ARM (Java/Pascal) программистов в ВУЗах, все будут в пролёте! Уже, в общем-то, кадровый голод. Не языкам студентов учат, и не конкретным ассемблерам, а общим принципам.


          1. tyomitch
            03.01.2018 12:43

            1) Неплохо было бы обучать общим принципам на примере чего-нибудь практически применимого, чтобы выигрыш был сразу по обоим фронтам. Ассемблер x86, или ARM, или MIPS какой-нибудь, для обучения общим принципам ничуть не хуже PDP-11, но конспекты по нему не отправятся в мусорку сразу же после экзамена.

            2) Как раз для обучения современным архитектурам — PDP-11, с его сверх-высокоуровневыми инструкциями, довольно нерепрезентативен.


            1. KoCMoHaBT61
              03.01.2018 13:57

              Люди обычно не понимают чему их обучают, потому, что для того, чтобы задать правильный вопрос нужно знать половину ответа.


          1. iig
            03.01.2018 14:22
            +1

            У PDP-11 отличнейший высокоуровневый ассемблер, который даст нормальное понимание как оно вообще всё было 30 лет назад ;)


          1. Dr_Dash
            03.01.2018 22:02

            тогда уж лучше msp 430, очень похож на PDP11 и очень актуален


      1. AnutaU
        03.01.2018 10:58

        Ооо, мне на моей первой в жизни работе как юному падавану досталась задача — запилить компилятор для Z80. Было познавательно.


      1. MacIn
        03.01.2018 18:47

        У нас использовали ассемблер машины VAX (2010е годы). Но наравне с х86, просто в разных курсах.


      1. tyomitch
        04.01.2018 17:04

        По дальнейшему размышлению, отличной платформой для обучения новичков ассемблеру/низкоуровневому программированию был бы мегапроцессор — чтобы выполнение машкода сделать буквально осязаемым.
        Без такого экспоната процессор так и останется чёрным ящиком, в котором волшебные гномики понимают и выполняют инструкции.


        1. KoCMoHaBT61
          04.01.2018 18:39
          +1

          Офигенная штука.


        1. MacIn
          04.01.2018 18:45

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


  1. Godless
    03.01.2018 01:30

    почему-то ожидал тут увидеть какую-нибудь модную кросплатформенную замену redasm…


  1. VBKesha
    03.01.2018 01:32

    В скором времени мы запустим портал с тестами (вопрос – варианты ответа) на знание ассемблера и архитектуры компьютера.

    Ох всегда меня это раздражало. Знания ассемблера, блин ну вы же сами пишите:
    Язык ассемблера — символьная форма записи машинного кода, использование которого упрощает написание машинных программ.

    Ну что значит в таком случае знание ассемблера? Если вы имеете ввиду что это x86 так так и напишите. Но есть ведь ещё ARM, MISP, x51, AVR, Z80, Microbalze, NIOSII, PIC и прочее прочее. Так знания какого ассемблера вы хотите проверять?


    1. VEG
      03.01.2018 10:19
      +1

      Обычно (если явно не указано) подразумевается x86. Это как Default City =)


  1. malishich
    03.01.2018 07:34

    Сам писал на FASM, Очень удобная штука. Одна библиотека для x86-64, до сих пор используется в продакшине. Кстати, автору на заметку, FASM также поддерживает ARM. А еще у Томаса есть версия FASM G которая более продвинута, и способна собирать «x86, x64, 8052, AVR, or Java Virtual Machine». Думаю это стоит указать.


    1. VEG
      03.01.2018 10:16

      FASMG в принципе можно обучить собирать под любую платформу, потому что набор инструкций там — это просто макросы. То есть x86 и всё остальное там реализовано просто наборами макросов. PE-файлы и таблицы релоков тоже формируются на макросах.


      1. MacIn
        03.01.2018 18:49

        И макросы FASMа — это реально круто, такой гибкости можно завидовать. Можно пересобрать файл на его макросах, например. Сделать работу за компоновщик т.е.


  1. kalininmr
    03.01.2018 08:47

    TASM жалко. в свое время был весьма неплох.


    1. vdem
      04.01.2018 00:12

      Он даже поддерживал ООП — с наследованием, инкапсуляцией и полиморфизмом :)


  1. we1
    03.01.2018 09:16

    А мне несколько лет назад очень нравилось на masm32 делать мелкие утилитки. Да, возни с WinAPI немало (не то что под DOS), но зато обращение к памяти проще, не надо запариваться с типами переменных, это даже удобнее Си.
    Конечно, в основном это мелкие вещи, которые один раз пишутся как шаблон, а потом нужные переменные подставляются (в памяти что-нибудь подправить, запускалку с закрытием ненужных окон сделать и т.п.). Но для этого уже давно инструменты есть и тоже вроде как смысл теряется.
    Мне больше интересно, как сейчас дела обстоят (и обстоят ли) с программированием под FreeDOS или что-то подобное. Там ведь ассемблер вполне себе удобен (особенно для резидентных программ).


    1. johnfound
      03.01.2018 09:39

      Мне больше интересно, как сейчас дела обстоят (и обстоят ли) с программированием под FreeDOS или что-то подобное. Там ведь ассемблер вполне себе удобен (особенно для резидентных программ).

      Работать под (Free)DOS не имеет никакого смысла, потому что просто нельзя использовать возможности компьютера. А вот в Linux программировать на ассемблере очень просто. Почти как в DOS.


      1. MacIn
        03.01.2018 18:50

        Есть какие-нибудь полезные ресурсы на эту тему (под Linux)?


        1. johnfound
          03.01.2018 19:01

          Я читаю вот это: https://fresh.flatassembler.net/lscr/


  1. longtolik
    03.01.2018 10:30

    Спасибо за тему. Хотелось бы также увидеть материалы, описывающие красоту программирования на ассемблере и для чего он, собственно говоря, нужен. Например, как в статье «Программные трюки на ассемблере» из журнала «Микропроцессорные средства и системы». Про рекурсию, реентерабельность программ и про сопрограммы, по-моему, интересно хотя бы для общего развития.
    Сравнение ассемблеров/архитектур — когда-то ассемблер DEC мне казался самым лучшим (там архитектура позволяла циклы чтение-модификация-запись при работе с памятью), потом было разочарование от ассемблера для Intel x86 (тут надо делать операции через регистр-аккумулятор AX/EAX и, если уж мы читаем слева-направо, то почему надо писать MOV DX,200, а не MOV 200,DX?). Позже, на Palm III познакомился с ассемблером Pila для Motorola 68000 — вот где красивая архитектура!
    Еще интересно было бы узнать про самомодифицирующийся код (и про то, что его нельзя уже изменить, когда попал в конвейер команд/данных, что может быть использовано для определения, что ваша программа прогоняется под отладчиком.
    Также можно было бы включить в будущие статьи, например, проект из блога компании Intel, в котором в приложение для Android вставлен и работает программа на Ассемблере. То есть, получается, мы можем писать на Ассемблере для Android! Ну, хотя бы чуть-чуть, для native библиотек.
    Еще вопрос: есть книга П.Брамм, Д.Брамм «Микропроцессор 80386 и его программирование». В ней описаны, в частности, дескрипторы страниц и перевод процессора в защищенный режим. Не понятно (простите за невежество), если ОС переводит процессор в защищенный режим и участки памяти вообще не видны для приложений пользователя, то как тогда вирусы могут туда проникнуть? Возможно, меняя код в BIOS или на загрузочном диске.
    Для ARM Ассемблера хотелось бы узнать, как включать/останавливать ядра.


    1. j-ker
      03.01.2018 10:44

      +1 Моторолы в сердце навсегда ))) Недостаточно кармы, но таки "стрелка вверх"!


    1. KoCMoHaBT61
      03.01.2018 11:29

      +1 за Моторолу 680x0


  1. some_name
    03.01.2018 15:11

    Как методичку прочитал.

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


    Писал вот такой вот код на третьем курсе (MASM):

    includelib D:\masm32\lib\kernel32.lib
    ExitProcess PROTO, :DWORD
    GetStdHandle Proto, :DWORD
    Sleep PROTO, :DWORD
    WriteConsoleA PROTO, handle: DWORD, lpBuffer:PTR BYTE, nNumberOfBytesToWrite:DWORD, lpNumberOfBytesWritten:PTR DWORD, lpReserved:DWORD
    ReadConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
    .data
    STD_OUTPUT_HANDLE EQU -11
    STD_INPUT_HANDLE EQU -10
    coh dd ? ;store console output handle here
    cih dd ? ;store console input handle here
    .code

    ReadingCA proc msg:DWORD, col:DWORD
    sub esp,8
    push STD_INPUT_HANDLE
    call GetStdHandle
    mov [ebp-4],eax ;Local Variable for this subroutine
    push 0
    lea eax,[ebp-8]
    push eax
    push [ebp+12]
    push [ebp+8]
    push [ebp-4]
    call ReadConsoleA
    ret 8
    ReadingCA endp

    Так что WinAPI использовать возможно.


  1. fukkit
    03.01.2018 23:51

    «Как» писать — это ерунда. Как и во все предыдущие годы: запасшись спеками, кофеином/никотином и парой бесконечных жизней. А вот «когда» и «зачем» — те ещё вопросы.


  1. chicagoist
    04.01.2018 00:06
    -1

    Благодарю за труд. Мне очень помогла статья.