Воробьёвы

(-:

№42. Потребность в IDE - миф или реальность?

Дела дано минувших дней,
Преданья старины
глубокой...

А.С. Пушкин

# Пролог

<00E>
Ну вот, как хорошо, что осень наступила.
Уж на конец не станет комаров
В дыхании чернеющих прудов,
Мой взляд листвою затопило...

<00F>
Что-то я вижу 00E Пушкина перечитался ?

<00E>
А причём здесь Пушкин?

Что как стихи так сказу Пушкин?
А как кино, так Голливуд?
А чем программа не поэма?
Сложить её всё тот же труд…

<00F>
Кх..

Ну, хорошо, мой друг, Edmond
Коль хочешь строк, то будут строки.
Но только, чур, не удалять
Мои поэмные мороки.

<00E>
Да будет так.
Пиши свой труд.
А мы над ним, склоняясь строго,
Подправим что-то там и тут,
Не удаляя в строках много :)

<00A>
Я вижу все, сошли сума!!!
HI-TECH безумцев наплодило!
Хоть, слава богу, я пока,
Залог спокойствия и мира.

<00S>
Ну ничего. То осень на дворе.
К кому-то муза залетела.
К кому sars пришёл по тело,
Лишь было бы полезно голове.

<00E>
Ну вот, а я начну…
Про дядю значит. ?
Был он хороший человек.

…..

<00F>
Не надо ДЯДИ!!!
Лучше есть!!!

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

Вам представляем мы выпуск осенний рассылки,
Мучаясь долго, мозги, напрягая изрядно -
Мы порешили, что будет, сей труд стихотворным
(Ибо Рифму умело сложить все равно,
что составить программу)

Впрочем, еще один стиль идеально подходит
Славить мужей развлеченье ассемблера дело святое
(Видно, на форуме "яти" не зря появились)
Пенного эля налей же, и вспомним былое!

(все достают электронные гусли ;))

Ой ты гой еси читатель, добрый молодец!
Ты не бойся, родный наш, не беспокоися!
То не ты с ума сошел, а лишь рассказчики,
Дурачины-простофили да насмешники.

Дикой горлицею WinAmp надрывается,
Стон идет с динамиков по комнате,
То не ясный сокол бъется о землю
Не за аленьким цветочком рычит чудище!

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

Не зловредная то спамщина-рекламщина
Не порнуха, зело тело возбуждающа -
То рассылка не простая, а особая
Низколевеловый кодинг да для дзенствущих!

Masquer

IDE для больших проектов на ассемблере

1. Введение

Итак, сначала небольшое введение, посвященное тому, зачем мне (в частности) вообще нужно IDE. Дело в том, что наличие IDE практически необязательно для проектов с небольшим размером. Под проектами с небольшим размером я подразумеваю проекты с количеством строк, меньшим 1000. Как правило такая программа состоит из одного файла (или один .asm и один .inc) и содержит 10-15 процедур, столько же структур, макросов, глобальных переменных и констант. Для работы над таким проектом вполне достаточно даже Notepad-а, а компиляцию запускать из bat файла. Все эти элементы программы достаточно легко запоминаются в голове и их применение практически не вызывает никаких трудностей, в худшем случае придется прокрутить текст, посмотреть название или элемент структуры и вернутся к коду. Насчет NotePad-а, это, конечно, утрированно, и подразумевается, что с этим заданием справится любой текстовый редактор. Выбор такого рода редакторов достаточно широкий. Все они, как правило, поддерживают настраиваемую подсветку синтаксиса, возможность запуска внешних приложений и захват текста, возвращаемого компилятором. Для таких целей я предпочитаю использовать UltraEdit (www.ultraedit.com). Почему? Кроме всего вышеперечисленного меня устраивает его компактность, скорость работы, удобные поиск и замена, возможность показа названий процедур (настраиваемая). На этом работы с небольшими проектами я касаться не буду.

2. Требования в IDE

Перейдем к более интересному, а именно большим проектам. Традиционно считается, что на ассемблере сейчас большие проекты не пишутся (или вообще ничего не пишется). А мне, например, нравится и у меня есть несколько проектов с количеством строк, большим 10 000 у каждого. Причем менять язык я не планирую, а число проектов - только увеличивать. Кроме этого каждый мой большой проект (незавершенный, кстати) имеет порядка 300 процедур, примерно такое же количество структур и глобальных переменных и дюжина макросов. При этом каждая процедура имеет 5-10 локальных переменных и 1-3 структуры. Все это разбросано по 5-6 asm-файлам и такому же количеству inc-файлов. Ну, и как прикажете этим хозяйством управлять? Самое время подумать о выборе IDE для управления такого ассорти.

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

1. Редактор текста.

1.1 Возможность настроить размер, стиль и имя шрифта. Я, например, предпочитаю все писать шрифтом Courier New, 14, bold;

1.2 Настраиваемая подсветка синтаксиса;

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

1.4 При наведении (клике) на переменную/константу/структуру/макрос/процедуру хотелось бы видеть ее во вспомогательном/всплывающем окне.

1.5 Желательно отделять цветом/стилем шрифта локальные переменные, глобальные и пр.

1.6 Неплохо (хотя и не критично для меня) было бы "сворачивать" процедуры и структуры.

1.7 Про прочие св-ва, присутствующие редакторам, типа настраиваемой табуляции и пр. даже неудобно напоминать.

2. Работа с проектами.

2.1 Удобство при добавлении и удалении файлов проекта (пофайловое добавление - это неудобство);

2.2 Возможность индивидуальных настроек у каждого проекта;

2.3 Копирование св-в одного проекта другому, наследование св-в

3. Непосредственно IDE

3.1 Отображение дерева из глобальных процедур, переменных, структур и констант с удобным поиском не только по первым символам (у меня многие процедуры начинаются одинаково);

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

3.3 Удобная настройка запуска внешних приложений (отладчика например) с присвоением кнопки на тулбаре и сочетания клавиш;

3.4 Удобное создание и использование репозитария кода (хотя мне не очень важно);

3.5 Поддержка средств контроля версий;

3.6 Интерфейс для написания плагинов;

3.7 В качестве общего требования - как можно больше кастомизации (я люблю все под себя настроить).

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

3. Некоторые примеры IDE

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

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

1. RadASM. Автор - Ketil Olsen. На этот продукт стоит однозначно обратить свое внимание, т.к. он сделан программистом на ассемблере для программистов на ассемблере. Кроме того, сам проект полностью написан на ассемблере. Один этот факт уже достоин уважения. Итак, мы имеем быстрый, маленький по объему и бесплатный IDE написанный энтузиастом для таких же энтузиастов. Среди возможностей - настраиваемая подсветка синтаксиса, автоподсказка при впечатывании функций WinApi, поддержка нескольких ассемблеров, плюс HLA, удобный выбор цветов и составление битовой маски, в панели свойств отображаются имена элементов языка с выпадающим списком либо аргументов (для процедур и макросов), либо элементов структуры (для структур соотв.), либо значений для констант. Есть возможность создавать ресурсы. Можно сворачивать процедуры и if-else a la MS Visual Studio .NET (collapsing). Есть интерфейс для плагинов. Вкратце - в нем есть все для работы со средними и малыми проектами. Почему он не пригоден для работы с большими? Допустим, у меня в проекте 300-400 процедур. Как мне в них ориентироваться, если нет абсолютно никакого поиска, простая сортировка по имени. Хорошо, хоть при впечатывании первых букв можно в выпадающем списке выбирать. При впечатывании имен структур и глобальных переменных меню с предложением вариантов возникает, только если нажать Ctrl-Space, а для этого я слишком ленив :) Локальные переменные и аргументы вообще не индексируются. Меню программы не продумано и неудобно (мне, например), для того, чтобы что-нибудь настроить, нужно хорошо полазить по меню. Нет возможности добавлять свои группы при подсветке синтаксиса.

2. Вторым пунктом хочу упомянуть небольшие, но (кажется?) развивающиеся проекты. Negatory Assembly Studio (www.negatory.com/asmstudio/) хочу упомянуть лишь как яркий пример того, что автор увлекся интерфейсом в ущерб функциональности. В результате получился симпатичный (хоть и спорный) интерфейс при практически полном отсутствии функциональности. По крайней я решил сохранить свое зрение, а не изучать функционал программы с жестко закодированным шрифтом размером в 6 pt. Еще одним продуктом, достойным упоминания (уже с лучшей стороны) является также индивидуальная разработка WinAsm (Antonis Kyprianou) (http://winasm.how.to/). Есть collapsing для процедур, при наборе понимает локальные переменные (после моей просьбы :)) Выпадающий список из процедур все с тем же прокручиванием или поиском по первым буквам. Поддержка AddIn У этого проекта определенно есть перспективы, но и сейчас его можно использовать для небольших проектов.

Самое интересное я оставил на конец. Следующие 2 программы относятся к многофункциональным IDE, в которых можно разрабатывать не только программы на ассмеблере (точнее - не столько). Это - дорогие коммерческие приложения, (в отличие от первых - бесплатных) и серьезные игроки - по функциональным возможностям они не хуже (а иногда и лучше чем Visual Studio от Microsoft). Начнем с самого дорогого...

3. Visual SlickEdit. (www.slickedit.com) Цена - $269. И по размеру, и по спартанскому в общем интерфейсу (ну, по сравнению с VS, например) сразу видно, что продукт очень серьезный. И после продолжительного тестирования я все больше и больше убеждался в этом. Вначале вкратце о пакете вообще - одним словом - предназначен для программиста, причем неважно на каком языке писать, SlickEdit имеет поддержку таких языков, о которых я даже и не слышал :). К своему немалому удивлению и радости ассемблер оказался в их числе, но об этом попозже. Пакет содержит мощный макроязык, синтаксически напоминающий С, с большим количеством примеров. Есть средство для сравнения файлов, причем все это с подсветкой и возможностью редактирования сравниваемых файлов. Для всех языков есть поддержка соответствующего синтаксиса, настраивается абсолютно все, что можно себе представить (и чего нельзя - тоже).

Имеется поддержка нескольких систем контроля версий (включая CVS). Возможностей пакета вполне хватает для конкуренции на равных с VS, а по некоторым параметрам - и превосходить. Что же мы имеем для работы с ассемблером? Легко настраивается подсветка синтаксиса, формата чисел. Возможность запуска внешних приложений с захватом и очень быстрым парсингом вывода - компилятора, например. При этом в случае ошибки к ней можно добраться одним щелчком. Есть поиск и замена. Для проекта на ассемблере есть дерево процедур в стиле MS VS, высвечиваются также глобальные переменные, макросы и структуры, правда, элементы структуры выводятся рядом, как независимые переменные (хотя для структур на C collapsing работает), и как это настроить для ассемблера, я так и не понял (возможно, скрипт переделывать).

4. Итак, последним по списку, но не по значению у меня Source Insight 3.5 (Source Dynamics, Inc.) Сайт - www.sourceinsight.com (Цена - $269).

При размере, на порядок меньшем (как у дистрибутива, так и в установленном виде), чем у SlickEdit функциональность не меньше, а порой и больше, чем у последнего. Хорошая настраиваемость, есть бейсикоподобный макроязык, но нет средств для коллективной работы (хотя я особо не искал). Интерфейс несколько отличается как от остальных, рассмотренных выше IDE, так и от VS. Что мне очень понравилось, так это то, что я могу видеть все процедуры, макросы, etc. как всего проекта, так и каждого файла по отдельности, плюс настроить, что именно я хочу видеть в данный момент - процедуры или константы, и т.д. Очень удобно сделан поиск по части названия (процедуры, например), а не по первым буквам.

Еще понравилась одна вещь, которой нет ни в одном IDE - Source Insight индексирует все мои структурные элементы программы и при наведении на них курсора, показывается нужный кусок кода внизу на панели. Для этой панели можно также задать ее размер и св-ва шрифта, но подсветка синтаксиса сохранится!

О подсветке синтаксиса тоже спою дифирамб - так, как ее можно настроить в Source Insight, я больше нигде не увидел в других продуктах. Очень удобно настраивается навигация по коду - я легко настроил ее как в броузере. Можно вывести статистику об используемых структурных элементах - об их встречаемости в проекте. Есть возможность вывести Relationship для процедур (надо сказать что для ассемблера эта функция работает, но несколько странновато результаты показаны). Для настройки парсинга локальных переменных пришлось написать регулярное выражение, правда, при этом включаются все локальные переменные файла, а не процедуры - не очень удобно, но терпимо. Зато при наборе любого текста появляется всплывающее меню autocompletion, при этом я могу пробежаться по предложенному списку, а все то же окошко внизу мне показывает первый десяток строк процедуры, например. Во время работы делается backup проекта, так что я практически застрахован от всяких неожиданностей, при аварийном завершении мне будет предложено восстановить работу на том месте, где ее прервал сбой. Кнопки сборки и запуска проекта идентичны кнопкам в VS. Из минусов, хоть и не критичных - долгий парсинг вывода, но зато я опять же могу не переходя сразу к коду, просмотреть первые строчки, при парсинге сразу же идет переход к первой ошибке (если они есть). Еще одна приятная мелочь - при печатании выражения, в котором есть несколько вложенных скобок, внешние становятся больше внутренних и сразу видна вложенность (хотя для ассемблера это не часто встречается). Еще одна немаловажная особенность, которой я больше нигде не видел, это подсвечивание строк, в которых произошли изменения - т.е. сразу можно увидеть, что и где я за этот сеанс изменил. Фактически, мне Source Insight напомнил улучшенный вариант VS + Visual Assist, и пока я свой выбор остановил на этом продукте.

4. Заключение

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

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

Sars

Поиск адресов API в win95-XP

Введение

На эту "избитую" тему написано уже много статей, но представлю на ваше обозрение еще одну.

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

Итак, особенности этой статьи заключаются в следующем:

  1. Код, рассмотренный в данной статье, будет работать на платформах win95-XP, за счет получения Image Base кернела не со стека, а через анализ SEH.
  2. Для поиска имени API-функции, код использует хеш от имени этой ф-ии. Это не бросается в глаза при рассмотрении зараженного файла в HEX Editor'е, в случае незашифрованного вируса, а так же сокращает размер кода.
  3. В коде нет переменных, адреса API-функций и другие нужные нам значения помещаются в стек, что бывает полезным в том случае, когда ваш вирус не должен производить запись в переменные до извлечения адресов API.

Итак поехали... (сначала код, потом комментарии)

      Start:

      Call _Delta

      

      _Delta:

      sub dword ptr [esp], offset _Delta 

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

    _ReadSEH:

    xor edx,edx

    mov eax,fs:[edx]

    dec edx


    _SearchK32:
    cmp [eax],edx
    je _CheckK32
    mov eax,dword [eax]
    jmp _SearchK32

    _CheckK32:
    mov eax,[eax+4]
    xor ax,ax

По адресу fs:0, находится seh, цепочка адресов на обработчики исключений. Формат одной записи таков:

    next_handler dd ?   ; указатель на следующую такую же запись
    seh_handler  dd ?   ; адрес обработчика исключения

Последний указатель на следующую запись имеет маркировку 0FFFFFFFFh, а адрес последнего обработчика находится где-то в kernel. В общем, глядите в отладчик, мы нашли адрес последнего обработчика, а значит и адрес внутри kernel. Дальше выравним полученный адрес на 64 Кбайта, т.к. kernel грузится по адресу кратному этому значению. Теперь нам осталось найти Image Base пресловутого и небезызвестного кернела. Делается это путем поиска сигнатуры MZ и проверки на PE формат...

    _SearchMZ: 
    cmp word ptr [eax],5A4Dh
    je _CheckMZ
    sub eax,10000h
    jmp _SearchMZ
    _CheckMZ: 
    mov edx,[eax+3ch]
    cmp word ptr [eax+edx],4550h
    jne _Exit

Так, теперь сравним слово по полученному адресу с 'MZ', если не совпало, то отнимем 64Кбайта, и повторим, если совпало, то проверим это заголовок PE или нет. Если да, то можно утверждать, что Image Base Kernel найден, если нет, то выйдем. Существует ли вероятность не найти Kernel? При использовании seh, навряд ли, по крайней мере, я этого не наблюдал при тестировании. В случае, когда адрес внутри Kernel берется со стека, заводится счетчик, чтоб не вылезти черт знает куда, но это описано в др. статьях. Для перестраховки можно завести свой обработчик исключений.

    _SearchAPI: 
              mov esi,[eax+edx+78h]         ;Export Table RVA   
              add esi,eax                   ;Export Teble VA
              add esi,18h
              xchg eax,ebx
              lodsd                         ;Num of Name Pointers
              push eax
              lodsd                         ;Address Table RVA
              push eax
              lodsd                         ;Name Pointers RVA 
              push eax 
              add eax,ebx
              push eax                      ;Index
              lodsd                         ;Ordinal Table RVA  
              push eax
              mov edi,[esp+4*5]             ;Delta offset
              lea edi,[edi+HeshTable] 
              mov ebp,esp

Здесь я не буду заострять особого внимания, почему, читайте выше. (см. документацию по PE формату).

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

В edi у нас смещение таблицы хешей искомых функций.

Т.к. дальше мы будем помещать в стек адреса найденных API ф-ий, то сохраним указатель стека в ebp, через ebp потом и будем обращаться к найденным адресам. Несколько слов, что такое index, первоначально он равен Name Pointers и указывает на таблицу адресов имен экспорта, каждый элемент таблицы равен двойному слову, и указывает на начало ASCII строки с именем API функции, если к Index прибавить 4, то он будет указывать на следующий адрес в таблице адресов имен... Конечно много непонятного, но поглядите в отладчик и половина вопросов отпадет.

    _BeginSearch:
    mov ecx,[ebp+4*4] ;NumOfNamePointers
    xor edx,edx
    _SearchAPIName: 
    mov esi,[ebp+4*1] ;Index 
    mov esi,[esi]
    add esi,ebx 

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

Обнулим edx, там потом будет порядковый номер найденной функции, начиная с нуля. Это понадобится для нахождения адреса. В esi адрес ACSII имени API функции, первоначально указывает на первую.

    _GetHash:
              xor  eax,eax
              push eax
    _CalcHash:
              ror  eax,7
              xor  [esp],eax
              lodsb
              test al,al
              jnz _CalcHash
              pop eax

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

    OkHash:
              cmp eax,dword ptr [edi]
              je _OkAPI
              add dword ptr [ebp+4*1],4     ;I=I+4 (I--Index)
              inc edx
              loop _SearchAPIName 
              jmp _Exit                            

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

    _OkAPI:
              shl edx,1
              mov ecx,[ebp]                 ;OrdinalTableRVA
              add ecx,ebx
              add ecx,edx
              mov ecx,[ecx]
              and ecx,0FFFFh
              mov edx,[ebp+4*3]             ;AddressTableRVA
              add edx,ebx
              shl ecx,2
              add edx,ecx
              mov edx,[edx]
              add edx,ebx

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

      push edx
              cmp word ptr [edi+4],0FFFFh   ;0FFFFh-End of HeshTable
              je _FindFirstFile
              add edi,4

    _NextName:          
              mov ecx,[ebp+4*2]             ;NamePointersRVA
              add ecx,ebx
              mov [ebp+4*1],ecx             ;Index
              jmp short _BeginSearch

Адрес найден!!! Что и требовалось доказать, помещаем его в стек, смотрим последняя ли это требуемая функция из таблицы хешей, если нет, то устанавливаем edi на следующий хеш. Возвращаем Index в первозданное состояние, т.е. что бы он указывал на адрес имени первой функции в таблице экспорта кернела, и повторяемся...

Если кому-нибудь поможет данная статья, не сочтите за труд черкануть пару строк автору, тогда возможно продолжу эту тему. Все вопросы по коду туда же, кроме таких как: "Что такое стек?" и т.д.

Рекомендую отладчики SoftIce и OllyDebugger.

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

Ссылки:

www.wasm.ru – есть неплохая обучалка по Win32 VX от Billy Belcebu

www.zombie.host.sk – имеется хороший FAQ для начинающих вирмейкеров и еще много чего

/\ & ()

(алгоритмы и оптимизация)

Циклические счетчики

Несколько реализаций алгоритмов циклического счётчика, который при достижении верхней границы переходят в нижнию, и наоборот, предложили masquer, Fixer, and Black_mirror:

    by masquer


    mov eax,  A; initial value
     mov edx, X+1 ; upper limit value + 1
     mov ecx, -1 ; forward = -1 backward = 1
    @@: sub eax, ecx
     mov edi, eax
     add edi, 1
     sbb ebx, ebx
     add edi, edx
     and edi, ebx
     add eax, edi
     mov edi, eax
     sub edi, 1
     sbb ebx, ebx
     not ebx
     and eax, ebx
     mov edi, eax 
     sub edi, edx
     sbb ebx, ebx
     and eax, ebx
     cmp eax, X
     jz @F
     ; 1 cycle takes 11 clocks
     ; here we can process the value calculated before
     jmp @B
    @@:

    ----------------------------------------------------------------

    by Fixer

    Вероятно самый компактный алгоритм 
        mov   eax, A ; initial value
        mov   ebx, X+1 ; upper limit value + 1
        mov   ecx, step

        sub   eax, ecx
    _beg_loop:
        add   eax, ecx
        xor   edx, edx
        add   eax, ebx
        div   ebx
        mov   eax, edx
    ;
        jmp   _beg_loop

    ----------------------------------------------------------------

    by Black_mirror

    inc eax 
    cmp eax,X+1 
    sbb ebx,ebx 
    and eax,ebx 

    dec eax 
    sbb ebx,ebx 
    and ebx,X+1 
    add eax,ebx

По следам FORUM.WASM.RU

И пробуждается поэзия во мне....

KiNDeR

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

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

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

MSDN

Aquila

В душе кипит бешенная яpость,
Тело pазpывает безумная стpасть,
Вопящее тело может упасть,
В падении на пол сбавляя скоpость.

Стоны и кpики заполняют уши,
От злобы пеpекошенно pот pычит,
Втоpя ему живот pычит,
Банда воpвалась в pайские кущи.

Сознанья усталого иссушенный залив
Пеною мудpости вдpуг обмочился,
Пpиступ интеллекта внезапно случился,
Здpавого смысла буpный отлив.

Мягкие, мелкие волны,
Солнцем ночным освещаются,
Достанный хелпом пpогpаммеp
Hагpетым пивком упивается.

# Эпилог

И я там был,
Мёд, пиво пил,
По усам текло,
А в рот не попало.