Как стать автором
Обновить

Комментарии 155

К примеру, автоматическую векторизацию кода (приведение обычных скалярных вычислений к параллельным вычислениям с использованием SIMD: SSE, AVX и т.п.), компиляторы делают весьма посредственно.

Уже давно для этого дела придуманы интринсики.


Когда у меня только появился Core i7-2600K (первая линейка с AVX), я ради интереса переписал несколько операций обработки изображений, например, свёртку, на ассемблере с использованием новых инструкций. Впечатлился. Но когда возникла необходимость переписать код с x86 на x64, я ощутил боль, потому что писать нужно, фактически, заново.


Так я открыл для себя инстринсики — низкоуровневые абстракции для работы с регистрами на низком уровне, не опускаясь до ассемблера. И оказалось, что это круто:


  • один и тот же код прекрасно компилируется и под x86, и под x64;
  • вместо пары дней реализации на ассемблере достаточно потратить пару часов;
  • код, сгенерированный компилятором, оказался быстрее написанного вручную на ассемблере, потому что сложность кода такая, что у человека уже не хватает ресурсов на учёт всех нюансов архитектуры.

Интринсик – это аналог инструкции процессора. Поэтому изучая интринсики вы изучаете и ассемблер (в несколько ином синтаксисе) :)

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

Ну да, пытался интринсиками сделать код для определения быстродействия в тактах, с высокой точностью. На асме всё просто, интристиками ещё проще, но дебильный компилятор удалил часть инструкций, потому что они ничего не делают, хотя они делают, очищают конвейер. Попытался использовать ассемблерные вставки, опять косяк, компилятор не знал что CPUID меняет 4 регистра, ebx в том числе, хотя использовал этот регистр в качестве счётчика.

Компилятор GCC 8.2 вроде хороший.

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

И так же у асмовставок в gcc есть способ указать, какие регистры портятся вставкой.

Я там какие то слова вставлял, но всё равно код не работал, разбираться не стал. В gcc даже интринсики как то не так работают, сложней чем студии.

Я там какие то слова вставлял, но всё равно код не работал, разбираться не стал.

Хороший подход, одобряю.

Делал в прошлом году измерялку скорости кода (в тактах).

Если интересно: https://gist.github.com/jin-x/88358e9bb1d58d01b7a318d0873208e3

Если есть понимание как улучшить, буду рад ;)

А что именно вас интересует? Я писала про них давно и много разного :) например, https://habr.com/en/post/94789/

Я погуглил подобные статьи на Хабре. Обычно их просто вал (как, например, ежемесячное обсасывание SOLID), а именно про интринсики и нет ничего. Только вот это:
https://habr.com/ru/post/326900/
Видимо, не особо людям это интересно, да и на английском документации достаточно:
https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/intrinsics/details-about-intrinsics.html
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#

а именно про интринсики и нет ничего. Только вот это:

Как раз интринсики изрядно заезженная тема, возьмите любую статью по SIMD, и там будут интринсики. Переносимость у них по-моему посредственная, вы не сможете даже скомпилировать AVX-интринсики под SSE, не то что под другой процессор.

Менее известны векторные расширения (gcc, Clang, также ICC поддерживает gcc-нотацию). Здесь я выкладывал пример, полная версия.

Вот ещё пример успешной автовекторизации с незаурядной перетасовкой данных в исполнении gcc.

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

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

Проблема во фрагментарности подаваемого материала.

"код, сгенерированный компилятором, оказался быстрее написанного вручную на ассемблере."
Тут дело не в сложности, а что процессоры давно уже не хавают инструкции как есть и просто обрабатывают их группами. От того написание циклов через dec-jn будет не такое эффективное как написать mov-sub-jn. (пример от балды)
И те кто пишут компиляторы под х86 вкурсе про это всё. Тот же компилятор С от intel выдаёт просто какие-то неестественные оптимизации для кода, что даже банальные циклы a[i]+=b[i] начинают работать раза в 2 быстрее чем на асм. (преувеличил) (По сути генерируя код именно под свою микроархитектуру транслятора х86 в МОП-ы у процессорах)

Хотя если мы пишем под процессоры\микроконтроллеры без МОП-ов и реордеров, то асм станет эффективней по производительности многих ЯВУ. (если ты кнш помнишь сколько тактов каждая команда исполняется и какие там условия)

И те кто пишут компиляторы под х86 вкурсе про это всё

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

"а почему вы думаете, что те, кто пишут руками, не в курсе?" - Те кто занимаются этим профессионально то в курсе, но учитывать ВСЕ нюансы архитектуры достаточно трудно. Это надо под пол года чисто под одну микроархитектуру кодить чтоб начать в ней спокойно разбираться. И те трудозатраты не очень стоят того результата, ибо это же можно решить директивами компилятора и вскими инстринсиками.
ЗЫ хотя я знаю что есть некоторый класс задач который мало на каком языке можно реализовать эффективно. (в голову лезут только битовые операции, типо цикличн сдвигов и команды для работы с отдельными битами)

Есть такой небезызвестный товарищ, Агнер Фог, который пишет маны по оптимизации (и не только). Очень полезно к изучению: https://www.agner.org/optimize/#manuals

К примеру, мне очень нравилось писать резидентные программы
На Turbo C писались в два счёта.

Да, я тоже писал на паскале. Но на асме было всё же веселее :)

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

мне больше нравится такой формат:
https://firststeps.ru/asm/tasm1.html
с https://firststeps.ru я начинал свой тур по с/с++
Пысы. Что с меня взять, я кинестетик :)

Т.к. чем выше (абстрактнее) ЯВУ , тем выше средняя зарплата разработчика и наоборот, чем ближе ЯП к ассемблеру - тем она ниже.

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

Дело не в этом, а в востребованности, конкуренции (кол-во разработчиков на вакансию), сложности языка, ИМХО. Я бы не сказал, что зарплаты программистов Python выше, чем на C++, хотя последний явно куда ближе к низкому уровню.

В области информационной безопасности, кстати, бывают вакансии с весьма достойными зарплатами (250 т.р. и выше), где в качестве требований указывают знание C/C++, ассемблера, опыт написания драйверов, знание внутреннего устройства ОС.

Не поленился сейчас и посмотрел на HH з/п ассемблерщиков. На первой странице нашёл ARM-разработчика с з/п до 350 т.р и инженера-программиста BIOS с з/п до 200 т.р. Есть ещё 160 и от 110. Так что, всё не так уж и плохо.

Для ARM и BIOS разработчиков ассемблер если и нужен то в следовых количествах. Там больше обычный С используется.

Со своей колокольни добавлю. В вебе сейчас есть WASM и WebGL. Достаточно низкоуровневые технологии. И сейчас довольно много задач, где они активно используются. Я например, не так давно делал конфигуратор кастомной футболки, где прямо на 3D модели футболки можно вставлять рисунки, изменять их размеры, писать и редактировать текст, поворачивать. И это все прямо на веб-странице. Половина работы здесь - это написание шейдеров на WebGL. Это конечно не ассемблер, но без понимания, как все работает на низком уровне здесь не обойтись. Вроде бы пишешь на C-подобном языке, но не покидаешь ощущение, что делаешь все на Ассемблере :)

Привет! А можно где-то увидеть результат? Очень интересно.

Пока @raamidне ответил, много всего интересного на шейдерах можете посмотреть здесь: https://www.shadertoy.com.

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

К своему стыду не знал, что WASM это не только про графику.

Я бы сказал оно совсем не про графику. WebAssembly на самом деле самое путающее название, т.к. оно и не Web и не assembly: оно изначально задумывалась как ускорение JS в браузере, но примерно в то же время стрельнул Node.js и JS рантаймы вылезли за пределы обычного Web. Плюс на текущий момент существует довольно немало standalone runtime для запуска wasm. За час даже можно написать свой собственный. Ну а не-ассемблер он потому что ассемблер транслируется напрямую в машинный код, а wasm — в код виртуальной машины, который транслирует инструкции в машинный код, считай IR, с некоторым ассемблероподобным синтаксисом.

standalone runtime для запуска wasm

То есть запуск не самого быстрого кода на виртуальной машине вне браузера? А в чем смысл если есть куча других языков для локальный программ?

В первую очередь безопасность и простота. Как говорил создатель докер — если бы wasm был во время того как создавался докер, то докер мог и не стрельнуть.
Во-вторых, как и в случае с node js — можно шарить один рантайм между фронтом и бэком.
В-третьих, кроссплатформа и возможность run on 4 billion devices тут же под боком. Есть мнение, что edge-вычисления могут иметь немалый профит с этого.
А так есть FAQ по теме

На мой сугубо субъективный взгляд из реально обоснованных применений для десктопа сейчас остались только #3 и #9, а оттуда пол-шага и до взлома, чего уж отрицать. Точечные правки в двоичном файле похожи на генную инженерию, когда в бинарнике на 10 мегабайт меняется 5-20 байт, но это правильные 20 байт. И вот такой патч без понимания ассемблера не сочинить.

 И вот такой патч без понимания ассемблера не сочинить.

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

Почему? Сертификат отрезается от файла в три минуты и вот файл уже и не был подписан. Контрольная сумма в PE-заголовке? Пересчитывается в HIEW чуть ли не автоматически...

Да, но проаерку подписи обрезанный файл не проходит. Привет неподписаным драйверам винды.

Вы так говорите будто все трои подписаны украденными у крупных разработчиков сертификатами. Но нет, они в массе не подписаны вовсе ни чем и ничего, работают

Windows отказывается загружать неподписанные драйвера, а с этого года откажется загружать и подписанные просроченными сертификатами.

Проблема только в 64-битных Windows. И эту проверку можно отключить.

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

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

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

Требования к драйверам — тоже не остановят, при необходимости. А т.к. драйвера "лечатся" сильно реже usermode приложений, то и проблема совсем небольшая.

На ассемблере можно написать ВСЁ, он всемогущ!

не знаю, байка или правда, но слышал историю, как очередная версия lotus 1-2-3 писалась на асме, писалась-писалась, релиз откладывался-откладывался, в то время, как excel зарелизился в разумные сроки и начал подминать под себя рынок.

Когда эксель релизился, Джоел писал об этом, они сидели и выкидывали «не нужный» функционал из него) За счет этого и успели

Можно написать всё при условии бесконечного умственного потенциала и бесконечной длительности жизни. :-)

  1. Создание загрузчиков
  2. Вы не поверите, но ассемблер можно использовать и для написания игр

можно объединить эти пункты и запихать игру в загрузчик :)

Тут речь идёт не о кастомном загрузчике несколькокилобайтной игры, а о целиком игре, помещающейся в зарузчик, в 512 байт.
Сделать 512-байтный Pong — не такая уж сложность. Положить любой код в boot sector — тоже. Вот написать загрузчик ОС, помещающийся в 512 байт, другое дело.

Для FAT12 вообще не проблема, писал интереса ради https://pastebin.com/a7TLUNht

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

О, я тоже недавно писал PONG на ассемблере. Правда, для БК 0010. И в загрузчик он не умещается, потому что поддерживает звуки через Covox. Зато Станислав Масловский написал полноценный Тетрис для БК в 512 байт

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

Транслятор в объектные модули, в смысле? Тут грань между трансляцией и компиляцией довольно условная, ИМХО, поскольку они же в машинный формат транслируют, а чем это не компиляция?

Да и, к примеру, NASM и fasm – вполне полноценные компиляторы (первый хоть и не во все исполняемые форматы переводит).

Хочу сразу оговориться, что правильно говорить не «ассемблер» (assembler), а «язык ассемблера»

Пусть меня заминусуют, но не правильно говорить «язык ассемблера», у ассемблера нет языка, поскольку без контекста конкретной марки процессора не понятно, какие мнемоники писать. Ассемблер это транслятор (вернее завершающий этап трансляции) с мнемоник процессора в коды процессора (упрощённо), поэтому на Арм «язык» будет один, на x86 другой. Соответственно, правильно говорить: Транслятор, и конкретно сборщик (Ассемблер) размещает уже транслированные данные в адресном пространстве (именно для него пишется в начале программы с какого адреса размещается программа), но поскольку от этого зависят коды обращений к памяти, то в трансляции он принимает непосредственное участие.
При этом, опять же, всё это относится только к процессу, а не к написанию, то есть, фактически это не Pascal, а FreePascalCompiler и т.п. Я думаю, что термин язык, тут вводить вообще не уместно и что-то вроде «Программа для транслятора» (ближе к понятию язык было бы монструозное: «система комманд процессора» или «представление комманд процессора», «язык комманд процессора») тоже совсем не внятно. Предлагаю термин «Низкоуровневая программа», можно уточнить для какого процессора, если нужно. Хотя, конечно, я понимаю, что «Ассемблер», это столп, уважуха и +10 в карму, а низкоуровневая программа это «ГраммарНаци».

"Низкоуровневая программа" – не очень понятный термин. Программа на C, работающая с оборудованием – это низкоуровневая программа? Да и к чему изобретать замену уже устоявшимся терминам? Понятие "язык" в данном случае вполне уместен, хоть он и имеет разные диалекты и разные правила написания под разные процессоры. "Язык ассемблера" можно сравнить с "языком людей", который в то же время может быть "русскими", "английским", "французский" или "японским" (x86, ARM, Z80...). При этом каждый из этих языков может иметь несколько диалектов (MASM, NASM, GAS).

Тот же Python тоже бывает версии 2 и 3, которые довольно серьёзные различия. Тот же C++ тоже имеет некоторые различия в стандартах C++03 и C++20. И даже C/C++ одной и той же редакции будет иметь отличия в интринсиках и библиотеках для разных ОС/процессоров (более того, даже компиляторы привносят свои нюансы: VC++ vs GCC). Может, тогда и эти языки не стоит называть языками?

Ассемблеры состоят из нескольких модулей: транслятор в объектный модуль и сборщик (линкер; хотя есть и 2 в 1: тот же fasm), поэтому называть линкер ассемблером как-то не очень корректно (хоть он и переводится как "сборщик").


Фу, зануда

В английском данная тема проста, элементарна, понятна, последовательна.

Assembly code is converted into executable machine code by a utility program referred to as an assembler

In communications and information processingcode is a system of rules to convert information—such as a letterword, sound, image, or gesture—into another form, sometimes shortened or secret, for communication through a communication channel or storage in a storage medium

Любой "язык", будь то русский, формальная логика или С++ - это алгоритм (т.е. набор правил) совместно с алфавитом. Языки ассемблеров - не исключение.

Используем асм на работе для генерации модулей для интеграции файлов в бинарь* и для некоторых реализаций алгоритмов для скорости (например sha1, который быстрее чем реализация в openssl)

*генерируем вот такие файлы
#if defined(__MINGW32__) || defined(__MINGW64__)
# define VAL_TYPE(S)
# define VAL_NAME(S) _ ## S
#else
# define VAL_TYPE(S) .type S, @object
# define VAL_NAME(S) S
#endif

/* @todo Для ARM нужно заменить @ на # */

.section .rodata
.global VAL_NAME(dev_valid_job_add)
VAL_TYPE(dev_valid_job_add)
.align 4
VAL_NAME(dev_valid_job_add):
.incbin "./projects/shared/libdevice/code//validate/job/dev_valid_job_add.json"
.byte 0
VAL_NAME(dev_valid_job_add_end):
.global VAL_NAME(dev_valid_job_add_size)
VAL_TYPE(dev_valid_job_add_size)
.align 4
VAL_NAME(dev_valid_job_add_size):
.int VAL_NAME(dev_valid_job_add_end) - VAL_NAME(dev_valid_job_add)


Также генерируется .h файл, который подключается к коду и определяет переменные для использования в коде:
extern const char dev_valid_job_add[];
extern const u32 dev_valid_job_add_size;


P.S.
Хабр не уважает ассемблер и C — для них нет подсветки кода.

Как же я вас понимаю! Сам увлекался ассемблером. Однажды, ради челленджа написал консольную программу, которая решала задачу расстановки ферзей. Размер области принимался в качестве параметра командной строки. В откомпилированном варианте программа занимала ... 182 байта. Еще написал программу обхода конем всех клеток шахматного поля, 516 байт.

Это действительно кайф, писать такие программы :)

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

Ассемблер x86 великолепен. Легко читается и пишется. Были ведь разумные инженеры, понимавшие что один процессор делается для всех программ и лучше один раз вложится в процессор ради удобства работы с любым кодом, которого возможно бесконечное множество. А не сэкономить на архитектуре, но потом мучаться всегда, как принято в нынешних говнорисках.
Комп — это же не просто универсальный девайс для работы с информацией, а в первую очередь свобода. Важная часть которой — я могу любую программу нажать правой кнопочкой, выбрать «открыть в дебаггере» и поправить всё что мне не нравится.
Это скорее про PDP-11.

Я изучаю ARM и могу сказать, что он не менее великолепен, очень интересные штуки в нём есть :)

Меня в своё время просто убила FJCVTZS, я сначала подумал это прикол какой-то )

Что же в ней такого особенного?

Не часто в низкоуровневых спеках встретишь слово Javascript; удивление было не инженерного свойства, скорее как в учебнике по алгебре встретить анекдот.

В x86 тоже не мало всяких gf2p8affineinvqb, ldmxcsr, mpsadbw, pclmulhqlqdq, v4fnmaddps, vfmsubadd132pd, vp4dpwssds, xgetbv... :)

upd: Ах, вон о чём речь. Вообще, некоторые процы ARM и Java-байткод понимают.

Не знаю, почему вы именно их в пример привели, на х86_64 ближе всего к fjcvtzs будет видимо cvttss2si c проверками – но и там Javascript не упоминается, может потому что во времена PIII JS ещё из пелёнок не вылез )

Не, cvttss2si преобразует FP32 в INT32. А надо чтоб FP64 в INT32 одной операцией.


P.S. Интересно, сколько байт занимает один только команда v4fnmaddps (опкод со всеми префиксам и аргументами)?

Вы правы, cvttsd2si имелся в виду, сорри.

После ассемблеров DEC (PDP-11) и Motorola (6800, 68000) c ассемблера x86 меня всегда тошнило и выворачивало мехом внутрь :)

За “говнориски” ты зело неправ. Видимо, ты просто в них не смог :) Но спешу тебя порадовать — их создавали не для “торчков по ассемблерам”. “говнориск” показывает ту же условную производительность, что и “шоколадциск”, только содержит при этом на два порядка меньше транзисторов, работает на порядок ниже частоте, при на два порядка меньших энергозатратах. Сама Intel не раз порывалась (432, 93x), но пипл хотел и дальше хавать говно (и это было х86), и требовал только ложку по-больше (мегагерц).

И за “разумных инженеров” замечу — ни одному действительно разумному инженеру не придёт в голову мысль сделать “что-то одно и для всего вообще”. Любое универсальное решение практически всегда и во всём проиграет частному. Почему-то в IBM в своё время не нашлось (к счастью) “разумного” инженера, который такой “А давайте видеокарту тоже на 8086 забульбеним, йопта, чё мудрить-то?!”

Почему-то в IBM в своё время не нашлось (к счастью) “разумного” инженера, который такой “А давайте видеокарту тоже на 8086 забульбеним, йопта, чё мудрить-то?!”

Ну как сказать, не нашлось

Между 8086 и 386 разница большая, на 386 кодить гораздо легче, а вот с х86-64 и х86-32 уже нет такой разницы. Так что я бы не сказал что 386 или х86-32 хуже PDP11, 68000 хотя некоторые ограничении в х86-32 мне тоже не нравятся.

По-моему, ты не знаешь системы команд pdp-11. Это просто глупо сравнивать с x86 (любой “ширины”). Начнём хотя бы с функциональной ограниченности регистров.

Поскольку ассемблер – самый низкоуровневый язык программирования
САМЫМ низкоуровневым является машинный код, не?

Обычно ассемблер является отображением машинных кодов практически 1 в 1. Мы, например, на 1 курсе университета писали программы в машинных кодах в debug.exe, чтобы потом вздохнуть с облегчением, когда начался ассемблер. Да транслятор вычисляет размеры операндов и адреса меток за вас, но в остальном не сказал бы, что есть какая-то существенная разница. Зная ассемблер, например, вы можете в отладчике остановиться на вызове функции отображения месседжбокса ("This program is not licensed"), промотать код немножко вверх и заменить jne на je (например, обычно конечно всё сложнее) - и вот уже программа принимает любой ключ, кроме собственно верного. Затем, зная, где находится это место в коде - открываете какой-нибудь HIEW и патчите опкод перехода руками. Просматривая голые hex-коды сделать то же самое будет гораздо сложнее.

Между кодом и мнемониками есть разница, например, есть 8 машинных кодов (и мнемоник) для установки бита в регистре принимающих в качестве параметра только регистр и 3 бита в машинном коде отвечают за то, какой бит установить. Программируя в машинных кодах, вы можете тупо по маске писать в эту комманду номер бита «передавая», таким образом, недостающий параметр. Мнемоническая запись, более высокоуровневая потому что предлагает абстракцию машинных кодов, точно так же, как более высокоуровневые языки абстрагируют уже целые блоки машинных кодов до операторов. Поэтому — да, машинный код, является ещё более низкоуровневым.

Не понял, про какие команды вы говорите в начале.

Никто не мешает вам, используя ассемблер, писать машинные коды через db :)

Машинные коды вряд ли можно назвать языком программирования. Если брать определение из Википедии, то "Язы́к программи́рования — формальный язык, предназначенный для записи компьютерных программ. Язык программирования определяет набор лексических, синтаксических и семантических правил, определяющих внешний вид программы и действия, которые выполнит исполнитель (обычно — ЭВМ) под её управлением."

Если так докапываться, то можно сказать, что и машинные коды не всегда являются самыми низкоуровневыми, ведь бывает ещё и микрокод :)

Да, бывает ещё и микрокод, машинные коды объеденены в систему, поэтому имеют свои семантические и синтаксические правила.
То, что можно писать через db ни о чём не гвоорит, в Pascal тоже можно писать прямо мнемониками ассемблера или использовать Goto. Речь идёт о слое абстракции: если вы умеете писать на высокоуровневом языке, то вам не нужны для этого знания более низкого уровня, если же они у вас есть, то, как правило, даже высокоуровневые инструменты позволяют копнуть глубже. Если же утверждать, что разницы нет, тогда, да, можно бубенить прямо db на любом языке и это будет высокоуровневая программа.

Это что за словоблудие? Ассемблерная мнемоника “xor eax, eax” — это всего лишь человекоудобная запись “машинного кода” 0x5d. И никак иначе ты эту операцию не запишешь. Такое “программирование в машинных кодах”, о котором ты говоришь — это тупо ручное исполнение работы ассемблеров. “Программирование в hex-редакторе”

Ассемблерная мнемоника “xor eax, eax” — это всего лишь человекоудобная запись “машинного кода” 0x5d.

Во-первых 0x31 0xC0; а 0x5D — это pop ebp.

И никак иначе ты эту операцию не запишешь.

Во-вторых, у весьма многих инструкций есть по несколько вариантов кодирования. Например, 0x33 0xC0 — это тот же самый xor eax, eax.

а бывает и наоборот, когда код один, а мнемоник несколько. например, nop и xchg eax, eax. :)

Ну да, про 0x59 не туда глянул, только сути это не меняет. А суть, повторяю, в том, что “программирование в машинных кодах” — это не какое-то ещё более низкоуровневое программирование, а всего лишь “ручное” исполнение того, с чем на 100500 порядков быстрее справляется ассемблер.

И не надо откровенной чуши про “тот же самый xor eax, eax”, поскольку “xor al, al” это совсем не то же самое.

Откровенная чушь — это ваши комментарии.
Введите «31 c0 33 c0» на onlinedisassembler.com/odaweb и убедитесь сами.
$ echo "0x33 0xc0 0x31 0xc0" | llvm-mc -mcpu=i686 -disassemble -show-inst
        .text
        xorl    %eax, %eax              # <MCInst #15279 XOR32rr_REV
                                        #  <MCOperand Reg:22>
                                        #  <MCOperand Reg:22>
                                        #  <MCOperand Reg:22>>
        xorl    %eax, %eax              # <MCInst #15278 XOR32rr
                                        #  <MCOperand Reg:22>
                                        #  <MCOperand Reg:22>
                                        #  <MCOperand Reg:22>>

Нет никакой разницы, да? Может, ты тогда откроешь всё же второй том «Intel​ 64 and IA-32 Architectures Software Developer’s Manual»? Там очень много интересного найти можно.

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

Нет никакой разницы, да.

Протрите экран, и вы увидите, что аргумент - не al.

Речь давно не про 0x30 (это был мой косяк). Речь про КОПы 0x31 и 0x33.

Таки почитай рекомендованную литературу. Внимательно.

Вы сами-то в эту литературу заглядывали, прежде чем мне рекомендовать? Там написано то же самое, что напечатал вам llvm-mc: что это две кодировки одной и той же ассемблерной инструкции xor eax, eax

Если вы пишете мнемонику, то вам не зачем знать про 0x5d, так же как программисту на Pascal незачем знать мнемоники. В машинных кода 0x5d, это не просто число, там имеется система.
Например, для z80 мнемоника Set 0, reg, где 0 и регистр жто часть 16 битной комманды, они не берутся из данных или регистров, вот как выглядят 16 бит в машинном коде: 1100 1011 11bi tSSS, зная структуру машинного кода можно перезаписать часть комманды превратив её в переменную и всего пара инструкций позволит из регистра записать номер бита, сделав что-то вроде «set reg, reg», надеюсь я не очень сумбурно изъясняюсь. Система комманд z80 Я не хочу заявить о каких-то серьёзных преимуществах машинных кодов, я всего лишь говорю о том. что мнемоники и машинные коды это разные вещи и машинные коды это не просто числа, а система кодов.

Нет у машинных кодов никаких преимуществ, кроме тех, которые имеет, например, сваренное яйцо перед сырым.

А про “систему” знает любой программист, который имеет опыт программирования на ассемблерах. Система называется “Архитектура”, частью которой является и система команд (instruction set). Назначение всех битов в кодах команд расписано подробно в любом reference guide к конкретному процессору. И от того, как эти команды записаны — битами или в мнемонической форме, не зависит ровным счётом ничего, кроме удобства чтения.

Справедливости ради про микрокод речь не шла, конечно процессор под капотом транслирует шестнадцатеричные коды в микрокод, и если рассматривать его (ассемблер) в этом аспекте, то он уже давно не является самым низкоуровневым кодом. Но разве у нас есть возможность писать напрямую в микрокоде?

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

Помимо демосцены существует ещё ретрокодинг - писать не выкрутасы, как на демосцене, а самые обычные программы (почти всегда игры) для старого железа. И на этом поприще асм это альфа и омега.

Если ассемблер так хорош, почему же мы не видим десктопных программ на нем? Компиляторов? СУБД?


Потому что это сложные программы, работающие со сложными данными (массивы, структуры, хеш-таблицы). В Си мы пишем index.fields[FIELD_NAME].offset, а в ассемблере вы будете сидеть вручную высчитывать смещение от указателя. Вы потратите в разы больше времени. И какой смысл этим заниматься?


Или Питон. В Питоне мы пишем [some_dict[x] for x in values if x > 0], а в ассемблере вам надо написать кучу строчек, чтобы сделать тот же объем работы.


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


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


Даже если нужна высокая производительность, то глупо руками писать код на ассемблере. Умно — написать эффективный транслятор, который будет без потерь транслировать высокоуровневый код в ассемблер. И примеры есть: регулярки транслируются в ассемблер, SQL-запросы, JS-код. Вот где искусство — преобразовать сложный запрос в набор низкоуровневых команд. А не сидеть часами переставлять mov и inc местами.


Вы пишете, что ассемблер дает "полный контроль над кодом". Не дает. Современные процессоры используют out-of-order выполнение команд, то есть произвольно их переставляют местами. Вы над этим не имеете контроля и скорее всего даже не знаете, как это работает. И при написании программы не можете учесть это и писать программу оптимальным образом. А вот, кстати, процессор Эльбрус действительно дает вам полный контроль над выполнением команды.


Вы пишете, что ассемблер позволяет обходиться "без стандартных библиотек". Опять же, это глупо — переходить на ассемблер ради сокращения программы. Умно — переделать компилятор, чтобы он умел выкидывать неиспользуемые функции. gcc это более-менее умеет. Ну и без библиотек тоже плохо. Что вы будете делать, когда вам понадобится множество, словарь и другие структуры данных? Что вы будете делать, когда понадобится применить к данным фильтр низких частот? Я, например, просто возьму scipy и решу проблему за пару десятков минут.


Получаемый код даже самого умного и навороченного компилятора, как правило, можно оптимизировать (как по скорости, так и по размеру).

И компьютер способен сделать это лучше человека. Почитайте про "супероптимизацию". Кратко: человек написал программу, которая генерирует все возможные комбинации ассемблерных команд, чтобы получить эквивалент данной на вход программы. Например, компьютер смог найти эквивалент из 4 команд для программы из 9 команд. Супероптимизация — это умно. Сидеть руками переставлять байты — глупо.


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


Ещё одна интересная область применения ассемблера – создание файлов данных с помощью макросов и директив генерации данных.

Питон это делает лучше.


Для внедрения кода в другие процессы
создания различных антиотладочных приёмов
Блоки распаковки, защиты кода
Эта дрянь не нужна. Это верный способ ввести труднообнаружимые баги или нарушить переносимость программы на другие ОС или другие версии ОС. Пример: вы используете какую-то недокументируемую функцию или смещение, а в новой версии ОС оно поменялось. Также, из-за таких любителей "защищать" код часто игры не работают под Wine. То есть, это значит что в будущем, когда Windows перейдет на другую архитектуру, их ни на чем нельзя будет запустить.

Отдельно хочется сказать про систему команд Интел. Она безнадежно плоха из-за необходимости совместимости с 8086. 8086 вышел по моему в 70-х годах, в нем 16-битные команды исполнялись строго по очереди, и с тех пор все поменялось радикально: процессоры стали 64-битные, в них используется out-of-order параллельное исполнение команд, а Интел должен тянуть это дремучее легаси. Ну представьте, например, как сложно процессору определять зависимости команд (то, что команду add dl, 1 нельзя выполнить параллельно с mov rdx, [rdi]). Команда занимает от 1 до 15 байт, с кучей префиксов. Регистры могут быть указаны в куче разных мест кучей разных способов. Данные могут читаться 1, 2, 4, 8 байтами без выравнивания. Или флаги: они тоже здорово мешают параллельности.


Лучшее, что можно сделать с архитектурой x86 — это выкинуть ее на помойку. Опять же, если брать Эльбрус, то система команд там намного современнее и логичнее, жаль только, что команды очень жирные.


Комп — это же не просто универсальный девайс для работы с информацией, а в первую очередь свобода. Важная часть которой — я могу любую программу нажать правой кнопочкой, выбрать «открыть в дебаггере» и поправить всё что мне не нравится.

Это не свобода, а насмешка. Свобода — это Линукс, где вы можете открыть нормальный читабельный исходник. Единственное, что огорчает в Линуксе: для Си нет нормального менеджера зависимостей, там на полном серьезе предлагают скачать исходники в tar.gz и до сих пор используют страшные нечитаемые Makefile.


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

Если ассемблер так хорош, почему же мы не видим десктопных программ на нем? Компиляторов? СУБД?

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

Умно — написать эффективный транслятор, который будет без потерь транслировать высокоуровневый код в ассемблер

Значит, ассемблер вам всё-таки пригодится? Иначе что вы будете делать потом с этим кодом, не зная ассемблера и не имея программ трансляции/компиляции?

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

Над исполнением кода вы не имеете 100% контроля (хотя на out-of-order тоже можно влиять, существуют барьерные и сериализирующие инструкции; к тому же, для отдельных процессоров это всё возможно изучить, да сложно). А над кодом имеете.

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

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

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

Я не призываю писать всё на асме (см. выше). Что я буду делать? Если очень надо, буду реализовывать его на асме (либо найду модуль/либу, делающую то, что мне нужно), либо буду использовать другой язык – это же очевидно :)

Супероптимизация — это умно. Сидеть руками переставлять байты — глупо.

Идея прикольная, но где же эти ваши супероптимизаторы в реальности? Или это просто очередная недореализованная идея? Опять же, всё зависит от ситуации. Текущие компиляторы далеко не всегда умеют генерить самый быстрый код. А дальше всё зависит от опыта и компетенций. Кстати, справится ли этот супероптимизатор с программой, которая использует свой же код как данные (сейчас вы, наверное, скажете, что это бредовая затея)?

Эта дрянь не нужна.

Как скажете. Кстати, почему вы решили, что использование недокументированных функций – неотъемлемая часть защиты и антиотладки?

8086 вышел по моему в 70-х годах, в нем 16-битные команды исполнялись строго по очереди, и с тех пор все поменялось радикально: процессоры стали 64-битные, в них используется out-of-order параллельное исполнение команд, а Интел должен тянуть это дремучее легаси.

Легко и удобно рассуждать, сидя в кресле. А что сделали бы вы на месте архитектора? Они уже попытались всё сломать, создав Itanium, и где он теперь? Кстати говоря, в x64 часть legacy вполне успешно вырезали.

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

Хорошо, когда процессор разрабатывается тогда, когда было создано уже много всего и можно с оглядкой на конкурентов сразу придумать нормальную архитектуру, правда? Посмотрим, насколько эффективен и чист будет Эльбрус, когда мы перейдём к какому-нибудь 256-битному коду :)

Комп — это же не просто универсальный девайс для работы с информацией, а в первую очередь свобода. Важная часть которой — я могу любую программу нажать правой кнопочкой, выбрать «открыть в дебаггере» и поправить всё что мне не нравится.

Это не моя цитата... А Линукс – это уже холивар.

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

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

Если ассемблер так хорош, почему же мы не видим десктопных программ на нем? Компиляторов? СУБД?
Потому что это сложные программы, работающие со сложными данными (массивы, структуры, хеш-таблицы). В Си мы пишем index.fields[FIELD_NAME].offset, а в ассемблере вы будете сидеть вручную высчитывать смещение от указателя. Вы потратите в разы больше времени.

Не факт. Я бы сказал, что на ассемблере с массивами работать не сложнее, чем на си, а в ряде случаев и гораздо проще. Во-первых, у нас есть возможность задействовать пару регистров, в один из которых (базовый) мы помещаем адрес массива, а в другой (индексный) — смещение нужного элемента от его начала. Процессор сам выполняет все адресные операции, а нам остается только модифицировать содержимое индексного регистра. А если размер элемента 1, 2, 4 или 8 байт, то и следить не нужно — процессор это делает сам, а мы только индекс элемента в этот индексный регистр кладем.
А во-вторых, массивы в си — это не массивы, как например, в фортране, а всего лишь алиасы для операций с указателями, о чем именно так и написано в стандарте
6.5.2.1(2)...The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).

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

Я давно как-то с BBS скачивал исходники файла turbo.exe для Turbo Pascal 6.0, так там было полно вставок на асм 286. Наверно, потому он так быстро транслировал.

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

А вот про красоту ассемблера x86 это спорно. Я пробовал писать на асме под БК-0010, ктотрый как известно слизан с архитектуры PDP, там система команд и сам ассемблер гораздо логичнее и приятнее. Не знаю как объяснить, просто удобнее и комфортнее, чем под x86 - просто надо попробовать, удобство практически сразу чувствуется.

Мне доводилось писать на ассемблере под MSP430, который тоже с PDP11 стянут, так что да, с Вашим утверждением соглашусь.

Почему именно об x86? Чем не угодил ARM? В Z80 или 6502 мало инструкций? Ну, так и на brainfuck люди выделывают ого-го что. Взгляните на демосцену, которая в РФ зиждется на 70-80% на одном только спектруме.

В современном мире, когда софт должен работать на x86, armv7, aarch64, mipsel, mipsbe, power7 и riscv из одной кодовой базы — не смешно предлагать писать его на asm? Вредительство и только.

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

>> Вы не поверите, но ассемблер можно использовать и для написания обычного прикладного ПО (консольного или с графическим интерфейсом – GUI), игр, драйверов и библиотек :)

Вот это огромное зло, только дрова (и то не все) можно простить.

Почему зло? Если по приколу, почему нет?

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

С какого я должен armv7, aarch64, mipsel, mipsbe, power7 и riscv это во обще что. Есть куча программ где можно просто забить на какие другие архитектуры. Windows понимает практически только x86, вроде как то бесятка АРМ может. Я только с виндой работаю и других систем не вижу, суперкомп с не х86 мне точно никогда не видать.

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

У разных ОС (я не имею в виду разные версии Windows или разные сборки Linux, разумеется, хотя и там есть свои нюансы), во-первых, разный формат исполняемых файлов, а во-вторых, разный набор и метод вызова системных функций. Конечно, 2+2*2 и т.п. будет работать на любой ОС, а что вы будете делать с этим дальше?

К примеру, автоматическую векторизацию кода (приведение обычных скалярных вычислений к параллельным вычислениям с использованием SIMD: SSE, AVX и т.п.), компиляторы делают весьма посредственно.

Небольшое уточнение по цитируемому — компиляторы С/C++. Интеловский компилятор с фортрана делает векторизацию на своих процах очень хорошо. Кроме этого, он генерирует более безопасный код в отношении разного рода непредвиденных вычислительных ситуаций типа переполнений, потери точности и прочего вычислительного дерьма, с которыми мы сталкиваемся на си, если не мониторим постоянно операнды.

Спасибо, добавлю про C/C++.

Добавьте в перечень отладчиков отладчик edb для linux (официальная поддержка) и прочих ОС. Поддерживает все новые SIMD-расширения и любую разрядность кода.
На ассемблере можно написать ВСЁ, он всемогущ!

Домашнюю страничку Васи Пупкина с гостевой книгой слабо?

Прикольно! Но такое можно и на С/С++ сделать, и работать будет не хуже, разве размер может немного больше. Только по возможности использовать низкоуровневый стиль с минимум библиотек.

Ну это ж чел сделал просто по приколу. Так же как KolibriOS сделали по приколу.

Есть один недостаток, который перекрывает все достоинства. Стоимость владения кодом.

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

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

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


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


Именно поэтому прочитать (и написать) 1000-строчную программу на языке ассемблера значительно проще, чем прочитать (и написать) 1000-строчную программу на языке высокого уровня.


Так что, будет ли сопровождение просто или сложно как всегда зависит от:


  1. Качество кода – структурное программирование и хорошие практики на ассемблере так же важны как и на ЯВУ.


  2. Знают ли программисты и насколько хорошо данный язык программирования.



Конечно на ассемблере и 1 и 2 труднее найти. Но ассемблер в этом не виновен. Он просто предоставляет свободу. А как вы ею воспользуетесь, ваша ответственность.

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

Он просто предоставляет свободу.

Обратный интересный пример Rust, тоже низкоуровневый, минимум свободы, всё для обеспечения безопасности исполнения кода.

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

В качестве средств для организации кода, асм предлагает макросы. И всё...

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

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

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

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


А насчет других людей, вот, почитайте и скажите:


Более абстрактный код:
https://asm32.info/fossil/asmbb/file?name=source/accounts.asm&ci=tip


Менее абстрактный код:
https://asm32.info/fossil/asmbb/file?name=source/fcgi.asm&ci=tip

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

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

Странно, что не нашел в статье упоминания Fresh:
fresh.flatassembler.net
Open source, визуальное проектирование аля Delphi, относительная мультиплатформенность…

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

Пожалуйста!
Рад помочь для полезной статьи.

Тоже люблю асм, по началу MASM, потом перешёл на UASM, а вот FASM не заладилось, оставил его на потом, но когда освоил UASM, понял что фасм мне просто не нужен.

Хотя на С++ можно кодить в стиле ассемблер. Код получается на уровне с ассемблером. Называю такой стиль C/C++, с библиотеками по минимуму и меньше новых наворотов новых С++. Получаешь и компактность(ну немного больше асм) и скорость ассемблера. При этом меньше ошибок, код более читабельный. Хотя у меня код на асм тоже не плохо выглядит, кроме структурности я ещё С строками комментирую.

Говоря об ассемблере я бы предложил упоминать, о каком конкретно ассемблере идет речь. Я, например, как старый ассемблерщик помню ассемблеры IBM/360 и PDP-11 и они сильно отличаются от Intel. Отличия не только в архитектуре и системе команд, но и в самих ассемблерах.

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

ЯВУ, не путайте с Java

Точно, потому что Java - это бейсик, а не язык высокого уровня.

У Рихтера за 2008 год более новая книга(на русском "Windows via C/C++"). Там добавили некоторые особенности висты(юак) и зачем-то убрали главу про оконные сообщения. А самая новая книга по винапи - Павел Иосифович Windows System Programming.

Статья отличная, привет с васма!

Спасибо, добавил ;)

<blockquote>В ассемблере есть особая магия и притягательность!
Это особый кайф, азарт, челлендж.

</blockquote>
Спасибо, читаю и думаю.

<blockquote>
Для сравнения: VCL-программа на Delphi 10.2 Tokyo
</blockquote>
Насколько помню, окно с перерисовкой и рисованием графика в win32
VCL Delphi 6 - 256 KB
Visual C++ 6 12 KB
Fasm 5KB

И да, "История одного байта"
https://wasm.in/blogs/istorija-odnogo-bajta.290/
Юров В.И. Ассемблер

PS. SoftIce

А если к старому Делфи взять еще KOL/MCK, то получаются те-же пару килобайт

Пара килобайт и близко не будет. Исходник "begin end." компилируется в 14Кб на Delphi7 и в 8Кб на Delphi6.

Видно запамятовал уже, плюсом был UPX

Спасибо, обновил.

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

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

В итоге ассемблер для меня так и остался увлечением, но то самое чувство «настоящего программирования» навсегда теперь ассоциируется именно с ним.
Или, скажем, для проделывания чего-то вроде Mixing x86 with x64 code
О как, а мне попался перевод чуть более поздней статьи из Valhalla zine (5.Ⅷ.2011) «Врата рая: 64-битный код в 32-битном файле». Убийца эмуляторов. ;)
хм, с «рабочего» интернета на этот сайт не пускает – неужели из-за Native Shell (amdf), или NTFS Stream Explorer?
Не смотря на то, что NTFS StreamExplorer требует повышений привилегий, Drag'n'Drop работает из приложений с обычными правами! Ещё позволяет менять атрибуты файла с явными запреты на их изменение для «система», Администраторов и Все:(Deny)(W,D), из-за чего кажется, что сам NTFS ещё на стадии замысла был неграмотно «сформирован», и ACL можно обойти!

А есть литература описывающая использование dot net на ассемблере?

Привет! Отличная статья, не теряешь вкуса к жизни и ассемблеру. Так держать! Очень приятно встретить спустя 20 лет. Исходники, как это было давно ))

Ух ты, привет, дружище! Действительно, столько лет прошло!

jin_x :

Благодарю за post.

Возможно Вы согласитесь с тем,

1. чтобы эффективно писать на assembler (assembly language) желательно, помимо прочего,
знать «логику работы»
микропроцессоров,
железа ПК,
операционных систем на уровне инженера;

2. чтобы эффективно писать на C/C++ желательно, помимо прочего,
знать «логику работы»
железа ПК,
операционных систем на уровне инженера;

3. чтобы эффективно писать на PHP, JavaScript, etc.
уровня инженера можно и не иметь;

4. чтобы эффективно писать на Python желательно иметь математическое образование.

операционных систем на уровне инженера

Сильно зависит от задач, которые вы решаете.


чтобы эффективно писать на Python желательно иметь математическое образование.

Зачем? Питон сам по себе этого не требует.

0xd34df00d :

>Зачем? Питон сам по себе этого не требует.

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

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

Спасибо автору. Хоть что-то полезное на хабре.

Нельзя быть действительно хорошим программистом, не понимая, как устроен и работает процессор. Ассемблер в смысле "потроха процессора" знать полезно. Отдельно полезно понимать, как работают немейнстримные процессоры. Тот же Эльбрус и Мультиклет.

ПРОГРАММИРОВАТЬ на ассемблере что-то отличное от бут сектора - сумасшествие. То есть делать это можно - но исключительно в порядке онанизма - ради удовольствия от процесса, а не ради результата. Как программист с почти сорокалетним стажем, имеющий представление о нескольких десятках ассемблеров (начиная с ламповых ЭВМ и заканчивая IAPX432) и программировавший на половине из них я это могу сказать с уверенностью. Пишите на Java, если вам нужен результат, а не процесс.

И да, на любом ЯП можно написать всё.

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