Ненормальное программирование

индекс
287,20

Мандельброт на .bat «for fun»

Вот эта картинка создана .bat файлом:



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

Например, как сделать паузу на заданное количество секунд? Команда pause тут бессильна. В место неё паузу удобно организовать через ping.
Пауза на 5 секунд будет выглядеть вот так:
ping 127.0.0.1 -n 6 -w 1000 > nul

Вот как узнать, содержит ли строка подстроку? Опять же, на первый взгляд ничего подходящего нет. На помощь приходит замена подстроки в строке:
set string=SOME TEXT
if not "%string%"=="%string:TEXT=%" echo YES

Ещё на .bat можно организовать вычисления с плавающей точкой (изначально плавающая точка не поддерживается), распараллеленные вычисления, синхронизацию между «процессами», распараллеленное вычисление на нескольких компьютерах и т.п. Я как-то раз видел исходники полиморфного(!) вируса, который полностью написан на bat-файле :)

В общем, время от времени я пишу что-нибудь на .bat, не могу пройти мимо такого вызова :)
Cейчас выкладываю одну из своих работ: батник, который рендерит множество Мандельброта в bmp.

@echo off
set /a xPixels = 180
set /a yPixels = 120
set /a xStart = -22000
set /a yStart = -10000
set /a xSize = 32000
set /a ySize = 20000
set /a maxIter = 32
call ::make_bmp_header
 
set /a xStep = xSize/xPixels
set /a yStep = ySize/yPixels
 
set /a iy = 0
:iyLoop
 
  set /a ix = 0
  :ixLoop
 
    set /a x = xStart + ix * xStep
    set /a y = yStart + iy * yStep
    set /a x0 = x
    set /a y0 = y
 
    set /a iteration = 0
   
    :formula
      set /a xtemp = x*x/10000 - y*y/10000 + x0
      set /a y = 2*x*y/10000 + y0
      set /a x = xtemp
      set /a iteration+=1
 
      set /a dist = x*x/10000 + y*y/10000
      if [%iteration%]==[%maxIter%] goto breakFormula
    if /I %dist% LEQ 40000 goto :formula
    :breakFormula
   
    if [%iteration%]==[%maxIter%] (call :plot_black) else (call :plot_color %iteration%)
 
  set /a ix += 1
  if not [%ix%]==[%xPixels%] goto ixLoop
 
  set /a progress = yPixels - iy
  echo.%progress%
 
set /a iy += 1
if not [%iy%]==[%yPixels%] goto iyLoop
 
call ::make_bin
ren file$ result.bmp
mspaint result.bmp
exit/b
 
 
:plot_black
call :write_byte 0
call :write_byte 0
call :write_byte 0
exit/b
 
:plot_color
set /a rc=%1*5 + 32
set /a gc=%1*7 + 6
set /a bc=128 - (%1*3 + 4)
call :write_byte %rc%
call :write_byte %gc%
call :write_byte %bc%
exit/b
 
 
:make_bmp_header

set /a dataSize = xPixels * yPixels * 3 + 54
set /a dataSize0 = dataSize%%256
set /a dataSize1 = (dataSize/256)%%256
set /a dataSize2 = (dataSize/(256*256))%%256
set /a dataSize3 = (dataSize/(256*256*256))%%256
 
call :init_bin
 
call :write_byte 66
call :write_byte 77
 
call :write_byte 118
call :write_byte 56
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 54
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 40
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %xPixels%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %yPixels%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 1
call :write_byte 0
call :write_byte 24
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %dataSize0%
call :write_byte %dataSize1%
call :write_byte %dataSize2%
call :write_byte %dataSize3%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
 
exit /b
 
 
:init_bin
echo.n file$>bin$
set /a addr=0x0100
call set "hstr=e "
call :write_word %addr%
set mustflush=0
exit /b
 
:write_byte
set /a a=%1
set hexs=0123456789ABCDEF
set /a a0=a/16
set /a a1=a%%16
call set res= %%hexs:~%a0%,1%%%%hexs:~%a1%,1%%
set hstr=%hstr%%res%
set /a addr+=1
set /a mod16=addr%%16
set mustflush=1
if not %mod16%==0 exit /b
echo.%hstr%>>bin$
call set "hstr=e "
call :write_word %addr%
set mustflush=0
exit /b
 
:write_word
set /a a=%1
set hexs=0123456789ABCDEF
set /a a0=a/4096
set /a a1=a/256%%16
set /a a2=a/16%%16
set /a a3=a%%16
call set res=%%hexs:~%a0%,1%%%%hexs:~%a1%,1%%%%hexs:~%a2%,1%%%%hexs:~%a3%,1%%
set hstr=%hstr%%res%
exit /b
 
:make_bin
if "%mustflush%"=="1" echo.%hstr%>>bin$
set /a filesz=addr-0x0100
echo.r cx>>bin$
set hstr=
call :write_word %filesz%
echo %hstr%>>bin$
echo.w>>bin$
echo.q>>bin$
debug<bin$
del bin$
exit /b


+200
14 июня 2009, 18:52
70

комментарии (102)

+19
slik #
Например, как сделать паузу на заданное количество секунд? Команда pause тут бессильна. В место неё паузу удобно организовать через ping.
Пауза на 5 секунд будет выглядеть вот так:
ping 127.0.0.1 -n 6 -w 1000 > nul

Вот как узнать, содержит ли строка подстроку? Опять же, на первый взгляд ничего подходящего нет. На помощь приходит замена подстроки в строке:
set string=SOME TEXT
if not "%string%"=="%string:TEXT=%" echo YES


да уж… прям через одно место это делается… но радует что есть люди которые умеют выйти из ситуации :)
+5
Imp5 #
Особенно интересно делается интерактивность =)
Когда делал игру «сокобан», приходилось учитывать разные версии командной строки.
+3
slik #
переходите на bash :)
+8
Imp5 #
а там нужно трудности преодолевать? =)
+25
slik #
трудности — да, но не через одно место :)
0
non7top #
сам по себе он не столько рулит (хотя конечно несравним с cmd), а вот вместе со стандартным набором консольных утилит… sed+awk это уже очень много.
0
BmW #
sed, awk, grep, find… Этот список можно долго продолжать :)
0
lamooof #
таких людей зовут програмисты!=)
+1
kolobog007 #
программисты
+32
Fil #
Код сходу непонятен, но чувствую, что круто! +
+16
Evgeny_Shiryaev #
Да, сходу ничего непонятно, но создается впечатление, что если прочитать этот скрипт Пи раз задом наперед, то можно призвать дух Ады Лавлейс O_o
+1
Imposeren #
Больше всего понравилось: текст habracut`a
(=
+61
habracut #
Я что-то писал?
0
medgimet #
Гениально!!!
+14
ecl #
плюс вам, тов. Маньяк
+1
porqz #
Вы это сами всё? Тогда вы большой молодец. Плюс вам.
+3
Imp5 #
сам =)
но время от времени заглядывал на разные сайты с tips and tricks
например, malektips.com/windows_xp_and_dos_help_and_tips.html
0
tehnolog #
Спасибо за ссылку. Очень познавательно
+2
GreenAngel #
Черепашка тож много чего нарисовать может…
0
csound #
ага, Logo многие недооценивают…
0
oisee #
«logo — это lisp без скобок», прочитал я в ZX-Review.
0
cherepaha #
я еще и крестиком вышивать умею!
+1
EvilX #
Это, конечно, не тетрис на sed, но всё равно круто.
Никогда бы не подумал, что это возможно в принципе.
+12
Rulin #
>паузу удобно организовать через ping

Майкросовский подход :)
+24
iscariot #
Мсье знает толк в извращениях…
+18
Bonch #
В подобных топиках обязательно найдется человек, которых напишет эту фразу.
+2
Dreammaker #
0
Dreammaker #
не весть урл злобный парсер съел :)
+5
Aldekein #
http://⌘.ws/湔, вот так вот лучше ;)
0
Azurre #
Прикольно :)
+1
Aldekein #
tinyarro.ws/ знает, как создавать странные УРЛки ))
0
Azurre #
Видимо он двоеточие недолюбливает…
+1
not_ice #
я программировать начал с bat в досе на 286 в 96 году)) правда недолго) что-то делал интерактивное, но что б такое… я поражен. правда, похоже, за это время функциональность командного процессора несколько возросла.
+1
not_ice #
а еще из извращений вспоминаются конфиги с навороченной логикой (менюшки там всякие, арт) для Quake 1 и 2 с их bind'ами и alias'ами :)
+2
Halt #
Ну не такие уж это и извращения. Часто батники как раз использовали для подобных вещей. Чтобы сделать некое подобие «интерфейса для секретарши».
0
Toshas #
А как такой код дебажить? Отладочными принтами, или есть возможность сделать это поудобнее?
И как юзать плавающую точку?
Да, это пожалуй самое оригинальное извращение из всех о которых я слышал =)
+2
Imp5 #
>А как такой код дебажить? Отладочными принтами, или есть возможность сделать это поудобнее?
Да, отладочными echo.
А ещё, если не делать @echo off, то можно видеть какие команды исполняются и с какими параметрами. Для удобства, этот вывод можно перенаправить в файл для дальнейшего изучения.

>И как юзать плавающую точку?
Надо написать функции для работы с плавающей точкой =)
В этой програме я использовал фиксированную точку, 4 десятичных разряда для дробной части.
+1
LegosX #
Когда программистам делать нечего :)
+4
Ctacus #
А вы не директор по ведущим разработкам Мелкософта? =)
+2
RuTs #
мандельброт в 61 байт:
tinyurl.com/llkbsd
НЛО прилетело и опубликовало эту надпись здесь
+2
Lux_In_Tenebris #
Я как-то раз видел исходники полиморфного(!) вируса, который полностью написан на bat-файле

Это не новость для посвящённых. В славные 90-е вирмейкеры куда больше изощрялись, чем сейчас. :)
Интересующиеся могут полистать старые e-zines вирсцены.
+2
Lux_In_Tenebris #
Из российских я там заметил Chaos AD, Infected Voice, MoonBug.
+2
Imp5 #
О да! Infected Voice — помню, помню =)
0
elw00d #
еще Infected Moscow помню был один выпуск, а второго вроде бы так и не дождались…
во были времена, когда натыкался на эти выпуски, приятно вспомнить.
0
Imp5 #
О да! Infected Voice — помню, помню =)
+3
Imp5 #
Не туда ответил %|
+2
Logonoff #
С gamedev.ru

Растеризация треугольника в консоли:
www.everfall.com/paste/id.php?t5ht4mw6kvls

Консольный сокобан:
www.everfall.com/paste/id.php?szlzpnwtsftu
+2
RomBinDaHouse #
Это один и тот же автор.
+5
unst #
«Pasted by Imp5»

это автор топика видимо запостил)
+4
Imp5 #
да, это был я
0
Logonoff #
Хех, вечером по запарке не заметил))
0
dazran #
Под дос был криптор исполняемых файлов написанный на .bat Trap авторства Christoph Gabler, последние версии правда уже полностью на asm вроде перевел.
0
Kastrulya #
круто у Вас на работе. есть чем заняться ;)
+3
Imp5 #
это в свободное время.
«programming for fun»
+17
leomac #
Ваша шайтан-программа грузит сеть весьма странным образом %)



Батник был запущен с сетевой расшарки на другом компе. Временных файлов на расшарке я не увидел :)
+3
darkside #
кстати графики сетевой активности тоже можно попорбывать батниками рисовать. должно быть даже проще, но не так эффектно, конечно)
0
Imp5 #
)))
+1
Bublik #
Учитывая, что автор интересовался Infected Voice, стоит прогнать машина антивирусом :))
0
Bublik #
*машину
0
Lux_In_Tenebris #
дык это ж из-за ping-задержки наверное?
+1
leomac #
компы в пределах одного роутера, второй комп под линуксом. Обычно задержка очень маленькая. Скорее, дело действительно в механизме исполнения батника. Кстати, батник сразу предупредил, что будет использовать не текущий путь (в расшарке), а c:\windows\.
0
Imp5 #
Вообще этот батник создаёт временные файлы в текущей папке.
Ещё дело может быть в том, как cmd исполняет батники. Он их читает по командам (из-за этого батники можно менять в процессе исполнения)
0
v_k #
временный файл создается, проверил (имя bin$)
+10
bogolt #
Леша — ты опять забыл принять лекарство! =))
0
zorro1211 #
Изображение в посте напоминает как раз картику, которую психиатр показывает пациенту и спрашивает что вы на ней видите =)
Мне напоминает повернутые пики или раздутые трефы
+1
v_k #
Это не картинка психиатра, там просто маленькая ящерка с выпотрошенными кишочками, которую ест ее мама
–2
kex #
:)))))!
0
Freeman85 #
У меня эта хрень минут 5 гудела, может потому что виртуалка, но вряд ли. Так что батник для таких вещей — не самый лучший выбор))
0
ayurganov #
у меня уже минут 20
что я делаю не так?
+2
Imp5 #
Freeman85 не жалуется, он хвастается =)
у меня на ноутбуке тоже где-то 20 минут работает.
0
Freeman85 #
Может и 20 минут, я как-то не засекал :) Просто говорю, что долго.
0
Agent_Smith #
у меня работает 8 минут, идут цифры от 120 до нуля, потом выдает ошибку что файл с картинкой не найден, что я делаю не так? 0_о
Батник в любой папке лежать может?
0
Imp5 #
Батник должен быть в папке, которая свободна для записи.

Посмотри, чтобы там уже не было result.bmp

В строках
set /a xPixels = 180
set /a yPixels = 120
замени разрешение на меньшее, например 8 на 8, чтобы не ждать результата долго.

Есть ли у тебя mspaint.exe?

Есть ли у тебя команда debug?
0
Agent_Smith #
команды debug нету
0
Imp5 #
А какая версия Windows?
+1
Agent_Smith #
Vista SP1 x64
+4
TiamaT #
Когда я читаю вот такие стать, как ваша, я вдохновляюсь. Очень приятно читать настоящего хакера.

Заметьте, ни одного заминусованного коммента к статье.
+2
Freeman85 #
Ваш минусовать начали :D, поднял обратно до нуля.
+1
TiamaT #
Я предвидел — меня это не оскорбляет. Спасибо вам, но право не стоило.
0
pdev #
Может кто в курсе, есть ли способ прервать выполнение батника для ввода данных и записи в переменную? Не считая сторонних программ которые записывают введенное значение в errolevel?
0
kentaskis #
rem SETLOCAL ENABLEEXTENSIONS
set /p var=Как Вас зовут?:
echo Hello, %var%

если не заработает, раскомментировать первую строчку
0
pdev #
То что надо, спасибо :)
0
Imp5 #
Если вам надо в определённом месте спросить что-то у пользователя, то вариант от kentaskis должен подойти.
Если это нужно сделать в произвольный момент, то к сожалению, я не знаю простых способов.
0
Denisio #
Для пауз есть waitfor
Ждем Doom на cmd скриптах :)
0
Imp5 #
Да, начиная с Vista или 2003, waitfor есть в штатной комплектации.
–8
hellomax #
А был ли мальчик? Короче, устал ждать счастья — убил выполнение. Используйте bash, удаляйте cmd.
+2
lostmsu #
Напишите Мандельброт на bash.
0
megabrain #
А мне вспомнился спектрум, как это не банально. И хоть мое счастливое детство прошло без детища синклера, но позже этот прекрасный компьютер чрезвычайно увлек меня в своем виртуальном (эмулируемом) воплощении. Многое тоже приходилось делать руками, а иногда и особым образом «удалять гланды». Как первому (операции с плавающей точкой, тригонометрия через ряды, умножение с делением, которые Z80 не поддерживал), так и второму (нестандартные видеорежимы, вывод на экран блоками по 8х8, внутри которых можно использовать лишь 2 различных цвета, 3d на такой простенькой машинке) можно было обучиться, читая ZX-прессу, дискмаги и газеты. Среди прочих равных выделялся журнал ZX Format. В нем всегда можно было найти статейку-другую о программировании для speccy. Эх…
+2
RomBinDaHouse #
… и тут все должны прослезиться?
+1
jandosul #
Такими темпами скоро варкрафт на бат перепишут )))
0
senyai #
20 минут и файл размером 180x120px :) Хорошо повеселили
0
Rulexec #
пару секунд и



Правда в Linux и с помощью специализированной программы Fraqtive.

С помощью пинга локалхоста задержки делать + (не могу пока).
0
Makaveli #
В универе в курсе Синергетики такие изображения назывались Фракталы. Есть также спец. программы, которые их строят.
0
Rulexec #
ага, вот например как />тут.
0
Rulexec #
парсер пожрал, rulexec.habrahabr.ru/blog/62094/
0
IGHOR #
Например, как сделать паузу на заданное количество секунд?
В Windows7, не знаю как в Vista наконецто добавили
+1
IGHOR #
Извиняюсь за отрывок, случайно отправил
Examples:
TIMEOUT /?
TIMEOUT /T 10
TIMEOUT /T 300 /NOBREAK
TIMEOUT /T -1

Parameter List:
/T timeout Specifies the number of seconds to wait.
Valid range is -1 to 99999 seconds.

/NOBREAK Ignore key presses and wait specified time.

/? Displays this help message.

NOTE: A timeout value of -1 means to wait indefinitely for a key press.
0
snch #
а я уж думал, что щас картинка 20 на 20 тыс. px вылезет…
0
VtD #
Теперь осталось написать на .bat-файлах веб-сервер
+1
aspect #
Люди знают толк в извращениях
0
Arris #
класс :)
вспоминаю молодость :)

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