Pull to refresh

Comments 100

Да, ассемблер, сколько в этом звуке, для сердца нашего слилось. х86 асм я как-то миновал (ну то есть там пописывал, но серьёзно к этому относиться нельзя). Но вот основательно пописал для с51 и AVR и чутка для arm. Даже сегодня, когда расчехляешь arduino, в голове считаешь такты.
Прекрасный язык, с одним чудовищным недостатком: непереносим.

Ну конечно. Хотя, не знаю что сказать, но недостатком ассемблера я это назвать не могу. Это как говорить о недостатках кентавров — нет рогов, и летать не умеет. Как бы и правда, но всё же не того типа лошадь. 8-)

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

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

В итоге - у тебя есть что надо, и память не течёт направо и налево.

Это Вы напрямую с DOS'овскими MCB не пытались работать, а мои поделки (светодиодами в LPT-порту помигать, попищать писи-скрипером по таймеру, загрузить в матричный принтер русские шрифты, если на LPT-порту статусы похожи на переинициализацию принтера) были более изобретательными при работе с оперативной памятью и файловыми буферами, и чтобы у TSR-сторожа, следящего за принтером, не "текла память" (я тогда даже термина такого не знал, но с явлением столкнулся), пришлось довольно много отладочной информации собирать.

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

Если вам нужен переносимый ассемблер, возьмите MSIL или JVM байткод.

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

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

Да мне си пока хватает

На ассемблере по сравнению с Си некоторые вещи можно сделать радикально по-другому, и иногда в разы лучше. Предоставляет ли какую-нибудь потенциальную выгоду использование JVM вместо Java? Кроме более громоздкого синтаксиса.

В прошлом году здесь постили хороший пример: компилятор Java позволяет использовать до 2746 значений в enum, тогда как при создании .class-файла вручную этот предел расширяется в 24 раза.

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

Я думаю, что и все примеры на Си такого рода: всё более полезное добавляют в язык как минимум интринсиками.

На ассемблере можно сделать процедуру с несколькими входами, нетривиальные операции со стеком, прыжки вместо setjmp/longjump.
Как на Си с помощью инстринсиков сделать продедуру, которая сигнализирует об ошибке в флаге переноса? Инстринсики для add with carry есть но они покрывают только ограниченные случаи использования.

Один из вариантов MSIL — возможность написать функцию по ансейф трансмутации из одного типа в другой. Что-то типа reinterpret cast — сама функция же просто делает ret собственного единственного аргумента. Бывает полезно при обработке низкоуровневых данных, когда нужно представить данные в немного другом виде (например преобразование byte[] -> long[]. В последних версиях C# оно появилось в стд в виде Unsafe.As<T> но во-первых раньше его не было, во-вторых если таргетится не последний неткор то этой функции в стандартной поставке нет и нужно продолжать использовать свою.

В MathCad 14, например, встроен прекрасный ассемблер, на котором удобно отлаживать программные вложенные циклы. Если битовые значения брать из массива BMP - картинки, то результат работы высвечивается подробно и красиво.

Ну, это всё же, другой ассемблер. Он хоть и ассемблер, но для виртуального процессора.

Это как тот пацан, который написал эмулятор процессора на экселе. Процессор Шрёдингера. Он одновременно и низкоуровневый и нет.

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

Тем что нужно больше мануалов читать. Спасибо большое, пойду их крутить дальше.

Лично я сразу вспоминаю ассемблер Z80... Некоторые машинные коды даже сейчас помню... )

С сожалением скажу, что до спектрума я так и не добрался. 8-(

Нет, на Спектруме только играли, а на ассемблере писал на КУВТ Yamaha MSX2.

На Спектруме демосцена так писала, как КУВТу и не снилось.
Защита с переписыванием LDIR инструкций во время исполнения, xor с регистром R, раскатывание циклов, недокументированные инструкции процессора, синхронизация с развёрткой для мультиколора, жонглирование теневым ПЗУ для прямого доступа к контроллеру FDD, семплирование через музсопроцессор в режиме COVOXa, божественные MONS, GENS и последователи их TASM и STS…

Ассемблер мини компьютера Д3-28 считаю был лучшим в своём классе по удобству и лёгкости освоения - всё множество команд было расписано в таблице на формате А3 и никаких дополнительных документов для работы не требовалось.

Однажды была сделана попытка скомпоновать команды ассемблера из софта AVR Studio аналогичным образом - этот вариант компоновки команд и сегодня был бы востребован...

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

Я только конец эры ДЗ-28 застал… Ни разу не пользовался… Не знал, что там тоже ассемблер был… Почитал документацию, прикольно!

Вот это ассемблер:

MOV R0,R1

010001 в восьмеричном. По памяти пишу )

А это что за ассемблер?

PDP-11, ДВК-2, Электроника-60, СМ-4, Электроника БК-0010, и некоторые другие. Это очень популярная тема и удобная система команд.

Ого! Да, я всё-таки пропустил это. Начинал писать в 1997 году, но даже тогда у меня на руках был неимоверно понтовый компьютер. Букашек видел только в школе, но и там нам не давали ничего, кроме черепашки.

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

Система команд https://ru.wikipedia.org/wiki/PDP-11#Особенности_PDP-11

На формате листа А3 было размещено краткое описание 256 команд ассемблера - 16 строк по 16 квадратных табличек с описанием команды. Найти любую команду можно было за кратчайшее время...

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

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

Прямо сейчас, конечно, точно утверждать не могу, но ЕМНИП для консоли нужно user32 и/или kernel32. В общем надо пробовать.

Так, я это буду считать подначкой! :-) могу даже попробовать спортировать на фасм.

Вывод в консоль — это WriteFile из kernel32

user32 нужен только для GUI

Возможно, puts будет ещё меньше. Но там форматирования нет, надо ручками.

Не будет: хоть то хоть другое втаскивает msvcrt
Версия, более актуальная для 21 века: habr.com/ru/company/ruvds/blog/571624
Переписать её на ассемблере несложно, но делать этого я, конечно, не буду.
.global main
.data                                   
hello: 
.string "Hello world\0"
.text
main:
  push $0
  push $0
  lea  hello, %eax
  push %eax
  push $0
  call MessageBoxA
  ret

собирается tcc -m32 test.s -luser32 в 1.5кБ exe и хочет 1МБ памяти.

Запахло перфокартами и перфолентами. Всплакнул.

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

Но если вам так уж всплакнулось, то рекомендую послушать альбом замечательного композитора Йохана Йохансонна (который писал музыку к Прибытию). Альбом называется "IBM 1401 инструкция пользователя"

https://www.youtube.com/watch?v=lCiUtRnG-bg

линкер должен называться компоновщиком, но мне это непривычно

Также вам непривычно "скачать", да? "Слить" — сейчас это про утечки.

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

  1. Он всё ещё живой и люди им пользуются. Существует масса иснтрументов разработки для всех ОС. Вот, например, ассемблер для новых маковских чипов М1. А здесь можно слить более 5000 страниц документации по процессорам Intel. Ну а если у вас завалялась где-то Raspberry Pi (а у кого она не завалялась?), то вам сюда.

Похоже ссылки не работают.

Починил! Не гневите! 8-)

Починено.

Может у вас — кеш-агрессор?

Когда моя мини-программа которая много читала из файлов на диске, что-то с ними делала и опять записывала на диск (ну вот такая "сложная" программа для нескольких файлов в 10к) заработала, я был готов к ее оптимизации. Но время исполнения в 14 мс на 5600X убило идею в зародыше. Конечно я понимаю, что криворуких кодеров, которые пишут страшный код для чтения JSON в 10 Мб хватает, но для современных процессоров x86... Мне страшно это говорить в слух, но в большинстве случаев оптимизация не нужна, тем более на ассемблере.

А так, да - весело, проностальгировал, вспомнил программирование TSR-программ под DOS.

Согласен. Но я бы вот как сформулировал мыслю:

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

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

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

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

Полностью согласен. Кто статью писать будет? Вы или я?

Читал с ностальгией, но с надеждой никогда к ассемблеру не возвращаться. Хотя, может, в современных IDE все проще и надежнее… нет, никогда, никогда больше! хватит того, что в голове зачем-то хранится всякий jmp FFFF:0000 и int 19

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

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

Полагаю, для достижения нормального для такой программы размера, следует всё таки разбраться с линкером и дёргать winapi вместо подключения стандартной библиотеки.
Кстати, FASM классный!
%macro memtoreg 4
xor r10, r10
mov r10b, byte [stor + %4]
xor r11, r11
mov r11b, byte [stor + %3]
xor r12, r12
mov r12b, byte [stor + %2]
xor r13, r13
mov r13b, byte [stor + %1]
%endmacro

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

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

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

Надо будет написать статью про современное применение ассемблера там, где он реально нужен — в прошивке до инициализации оперативной памяти или cache-as-ram, в ядре ОС для перехода во всякие хитрые режимы исполнения и выхода из них, и т.п.

Байто**ля... Писец. New achievement unlocked. Согласен. Лучше слова и не придумаешь. Но тут я уже смотрел с точки зрения оптимизации, сколько это будет стоить в циклах. Я так предположил что память-то закешируется и тянуть её из L1 в регистры будет несложно, в таком случае двигание регистров будет дополнительной нагрузкой, которая себя просто не окупит.

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

А по поводу статьи - это вы правы. Посмотрим 8-)

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

Наверное, если сильно заморочиться можно на одних регистрах написать. Вон, сортировку внутри широченного xmm/ymm делают же, чем тут хуже? :)

2048, v2 извращённая. Убираем поддержку стандартной библиотеки винды, выводим поле опкодами BSOD или как-нить так. Пилим всё аккуратно и сохраняем всё поле в одном регистре. Радуемся футпринту в 2кб.

Кстати... Я так подумал, а ведь если я запущю всё это на FreeDOS у меня будет возможность добираться до современных регистров и, в то же время, использовать int 21h, что жутко сэкономит память.

Я так подумал, а ведь если я запущю всё это на FreeDOS у меня будет возможность добираться до современных регистров и, в то же время, использовать int 21h, что жутко сэкономит память.

Формально вам понадобится какой-нибудь 64-битный dos-extender, если не хотите сами писать кучу обвязки для перехода в 64-битный режим и вызова оттуда какого-нибудь int 21h. Можно обойтись и 32-битным расширителем, выбор коих намного больше. Но зачем, если сэкономить память можно и в современных windows/linux.

2048, v2 извращённая.

Уж если речь зашла про dos, то можно на голом mmu написать, он на x86 вполне тьюринг-полный. Такие извращения только под dos и можно пускать, ну или прямо из первичного загрузчика.

В DOS можно совершенно спокойно использовать 32-х битные регистры без всяких расширителей. Расширитель нужен для адресации памяти за пределами 1Мб.

Мерять надо, понятно, но мой собственный палец (это которым «в небо») говорит, что арифметические операции, выполняемые целиком на ALU, выполняются нынче за один такт (на современных х86 после Skylake это так даже для 256- и 512-битовых регистрах), а половина примерно мувов из регистра в регистр — за ноль (потому что там внизу регистровый файл, и переименование фактически бесплатное). L1D на этих же процессорах умеет при идеальных условиях читать две линии по 512 бит за такт, или писать одну, но там если самому с выравниванием не заморочиться хоть немного, можно попасть на границу кэш-линии (и просесть вдвое на ровном месте), или физической страницы (и просесть в ~200 раз), ну и плюс мы тут всяко не одни исполняемся, и из кэша наше игровое поле может вымыть в любой момент…

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

Снимаю шляпу!

Переписывать это можно бесконечно. Если посмотрите на исходники - всё это писалось быстро и без уж очень большой оптимизации.

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

Насчет сыты по горло — это правда. Это же объясняет, почему так мало статей, а тем более не в корпоративных блогах.
А насчет задач со зведочкой, я даю такую: сколько доступов в память в худшем случае может быть сделано при выполнении команды nop, включая ее выборку. И сколько (хотя бы примерно) их вообще может быть максимально для одной команды x86.
Хорошая задача, но нуждается в дополнительных уточнениях условий, потому что реально худший случай может быть CXL-устройством, подключенным в адресное пространство процессора, которое при попытке декодировать с него nop пойдет этот самый доступ в память осуществлять, а процессору скажет подождать немного, пока оно не закончит, и ждать он там может до ишачьей пасхи, или пока вочдог всех не прибьет.

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

image
Уточню: команда лежит в обычной кэшируемой оперативной памяти, это 1-байтовый nop, который ни при предвыборке, ни при исполнении не вызвал никаких исключений. Рассматриваем только результат одной команды, никаких крешей, прерываний, dma/rdma/smm и т.п. нет. Ядро при простоты тоже одно.

Сразу скажу, что число чтений памяти больше одного, число записей (!) тоже больше одного. А есть еще не nop, а более хитрые команды, там все еще хитрее.
То, что чтений может быть больше одного — это нетрудно сделать, TLB-промаха достаточно для того, чтобы процессор вынужден был выполнить трансляцию адресов, для которой понадобится одно или несколько обращений к таблице трансляции (в зависимости от того, как именно настроен paging).
С несколькими записями тоже проблем нет — кладем инструкцию последним байтом страницы, заполняем кэши так, чтобы ничего ни с этой, ни со следующей страницы в них не было, выполняем на эту нашу инструкцию nop неожиданный дальний переход — pipeline flush, cache flush, протокол когерентности заставил сделать write-back как минимум двух вымытых из кэшей линий (которые теперь заменили одна с конца этой страницы, ее запросил декодер, а другая — с начала следующей, эту запросил префетчер).
Я не сомневался, что вы ответите на этот несложный вопрос :)
Просто хотел подчеркнуть, что иногда последствия самых вроде безобидных команд могут быть не сразу очевидными. Обычные программисты с такими фокусами вряд ли столкнутся, разве что при очень тщательной оптимизации, а вот системщики — более вероятно. Кроме того, это просто полезно знать, чтобы понимать как устроена не самая простая архитектура x86.

p.s. позволю себе еще немного коварства: а если кэша нет (отключен и по коду и по данным, память не кешируемая и т.д.) можно ли получить несколько записей в память? а на каком-нибудь i386sx, где все еще проще можно?
иногда последствия самых вроде безобидных команд могут быть не сразу очевидными
Зачастую, эти последствия бывают неочевидными даже для самих разработчиков процессора, целая плеяда микроархитектурных атак вроде Spectre, Meltdown, Foreshadow, RIDL, Fallout и остальных — отличное тому подтверждение. Знать и понимать — надо, конечно, но надо тоже осознавать пределы своего понимания, а то ведь я до сих пор вижу в индустрии людей, которые в своем ассемблерном коде старательно избегают pipeline hazard'ы, которых их нынешний процессор давно уже не боится, а на Pentium Pro их код запускаться точно уже не будет…

Про ситуацию с «кэша нет» думать уже не хочу, прошу пардону, потому что и лень, и «так верстают только мудаки (тм)». Можно пойти почитать мануал на тему «кто там в память сбрасывает свой architectural state, и при каких условиях», вспомнить про сегментную адресацию и thread local storage, и прочие разные штуки, но я уже в пижаме и мне уже слишком влом.
p.s. позволю себе еще немного коварства: а если кэша нет (отключен и по коду и по данным, память не кешируемая и т.д.) можно ли получить несколько записей в память? а на каком-нибудь i386sx, где все еще проще можно?
В таблицах для страничной адресации есть флаг «accessed», на 386 при любой трансляции линейного адреса просматриваются 2 таблицы, в каждой нужно бит установить.

из кэша наше игровое поле может вымыть в любой момент

На некоторых архитектурах есть cache locking и предзагрузка данных/кода в кэш.

Более того, благодаря SSE, SSSE и AVX у нас на руках ещё есть 15 регистров по 128 или 256 бит. Они названы XMM0-XMM15 для 128 бит и YMM0-YMM15 для 256 бит.

16 же, от 0 до 15. В 32-битном режиме только 8. А еще 8 FPU/MMX тоже есть и в них тоже можно хранить что угодно при желании. Ну а уж если AVX512 вспомнить, то там аж 32 ZMM и еще маски…

p.s. младшие части XMM/YMM/ZMM — это одни и те же регистры, т.е. биты 0-127 совпадают в xmm0 и в ymm0 и в zmm0.
UFO just landed and posted this here
Пожалуйста, не надо превращать технический блог в фидопойку.

Это вы ещё не заметили, что в коде вместо .bss автор опечатался и поставил .bbs :D
«Я понял, в чём ваша беда. Вы слишком серьёзны. Умное лицо — ещё не признак ума, господа. Все глупости на Земле делаются именно с этим выражением. Улыбайтесь, господа, улыбайтесь!»


На самом деле стиль автора — это отсылка ко времени «Хакера», тем кто его не читал, не понять такой формат общения, хотя именно на нём выросли современные специалисты IT в СНГ. И, да, я согласен на счёт алкоголя, но данный стиль — это просто добрые воспоминания.
UFO just landed and posted this here
Интересно, к кому причисляете себя вы, с таким высокомерием и пафосом, а главное серьезным лицом? Можете не отвечать, и так всё ясно.
UFO just landed and posted this here
UFO just landed and posted this here
Забавные выводы, каждый видит то, что хочет увидеть и пожалеть других. Хотя про 90-е речи даже не было, как и «Хакера» в те годы.

Ох, и не знал, что я подонок и разговариваю на сленге) И "погнали", и "поехали" я использую в своем разговоре...

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

Мне это всё напоминает:

Щенок! Щенок... не нужен? Дёшево отдам. (Погуглите если не знаете)

Хе-хе, начали с подсчета полубайт, а в итоге все равно получилось 2.5Мб :) Если бы написать на чистом Си, думаю было бы не сильно больше, но зато 100% переносимо, хоть на CP/M запускай. Автору респект, но нет, обратно на ассемблер уже не тянет :)

Это потому что автор линкуется с сишной стандартной библиотекой.
Если переписать на WinAPI, WS сразу снижается до 1.5 МБ

ИМХО не самое полезное применение ассемблера. Вот если эту штуку написать для Arduino или любого другого микроконтроллера с четырьмя кнопками и экраном - будет нагляднее. Под Windows все равно все упирается в системные вызовы, которые нам не подвластны, а на голом железе все в наших руках.

Ассемблер не пугает. Главное, чтобы мануалы по инструкциям были. В свое время я учил ассемблер для AVR микроконтроллеров. Потом перешёл на Си и С++. И вот однажды мне пришлось на STM32F407 организовать цепочку цифровых обработок одного сигнала и выжать максимум производительности с ядра ARM Cortex-M4. А тут только ассемблер и нужен. Мануал по ассемблеру вышеупомянутого ядра оказался довольно увлекательным. Там очень много интересных инструкций на все случаи жизни. Ну и задачу я свою решил. Не стал писать вставки и ограничился вызовами intrinsic функций библиотеки CMSIS.

cygwin еще не советовали для ленивых?
Там есть всё, что требуется для таких развлечений. И yasm и yasm и MinGW и линкеры

А на что заменить mov ax,13h; int 10h;?

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

А на что заменить mov ax,13h; int 10h;?

На RegisterClass/CreateWindow
Шекспира лучше читать в подлиннике.
Так и с процессором лучше разговаривать на его родном языке — языке Ассемблера, без дополнительного «переводчика» в виде Си компилятора.
Был и остаюсь фанатом FASM: х86, AVR, ARM.
UFO just landed and posted this here
Сонеты Шекспира меня не заинтересовали. А вот детективы Сидни Шелдона — да, прочел штук пять в подлиннике.
Минус Вашему комментарию я не ставил. Но тоже считаю его неуместным, т.к. в той крылатой фразе заложен смысл не про Шекспира, а про native language.
UFO just landed and posted this here

Есть masm64 от того же hutch (автор замечательного пакета masm32). Да,ехе нужно брать со студии,но тут есть макросы,инклуды , примеры. Также советую посмотреть uasm - masm синтаксис но гораздо больше возможностей ( создание файлов пол разные ос,даже подобие ооп)

Sign up to leave a comment.